Java tutorial
/* * Copyright (c) 2001-2011 Convertigo SA. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. * * $URL$ * $Author$ * $Revision$ * $Date$ */ package com.twinsoft.convertigo.beans.core; import java.beans.BeanDescriptor; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.swing.Icon; import javax.swing.ImageIcon; import org.apache.commons.lang3.ClassUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.twinsoft.convertigo.beans.Version; import com.twinsoft.convertigo.beans.common.XMLVector; import com.twinsoft.convertigo.beans.steps.SmartType; import com.twinsoft.convertigo.engine.DatabaseObjectNotFoundException; import com.twinsoft.convertigo.engine.DatabaseObjectsManager; import com.twinsoft.convertigo.engine.Engine; import com.twinsoft.convertigo.engine.EngineException; import com.twinsoft.convertigo.engine.ObjectWithSameNameException; import com.twinsoft.convertigo.engine.UndefinedSymbolsException; import com.twinsoft.convertigo.engine.enums.Visibility; import com.twinsoft.convertigo.engine.helpers.WalkHelper; import com.twinsoft.convertigo.engine.util.CachedIntrospector; import com.twinsoft.convertigo.engine.util.Crypto2; import com.twinsoft.convertigo.engine.util.EnumUtils; import com.twinsoft.convertigo.engine.util.GenericUtils; import com.twinsoft.convertigo.engine.util.StringUtils; import com.twinsoft.convertigo.engine.util.VersionUtils; import com.twinsoft.convertigo.engine.util.XMLUtils; /** * This is the base class for all Convertigo objects which should be serialized * in the Convertigo database. */ public abstract class DatabaseObject implements Serializable, Cloneable, ITokenPath { private static final long serialVersionUID = -873065042105207891L; public static final String PROPERTY_XMLNAME = "xmlname"; private transient Map<String, Set<String>> symbolsErrors = null; private static class SubLoader extends WalkHelper { DatabaseObject databaseObject; @Override public void init(DatabaseObject databaseObject) throws Exception { try { this.databaseObject = databaseObject; super.init(databaseObject); } finally { this.databaseObject = null; } } @Override protected void walk(DatabaseObject subDatabaseObject) throws Exception { if (subDatabaseObject.original != null) { super.walk(subDatabaseObject.original); } else { databaseObject.add(subDatabaseObject.clone()); } } } public enum ExportOption { bIncludeDisplayName, bIncludeCompiledValue, bIncludeShortDescription, bIncludeEditorClass, bIncludeBlackListedElements, bIncludeVersion, bHidePassword; } transient protected static long lastTime = 0; transient private final static ThreadLocal<SubLoader> subLoader = new ThreadLocal<SubLoader>() { @Override protected SubLoader initialValue() { return new SubLoader(); } }; transient protected long identity; transient public boolean isImporting = false; transient private DatabaseObject original = null; transient public boolean isSubLoaded = false; /** * The source values map for compilable properties. */ transient private Map<String, Object> compilablePropertySourceValuesMap; transient protected Collection<ExportOption> exportOptions = new HashSet<ExportOption>(); public Object getCompilablePropertySourceValue(String propertyName) { return compilablePropertySourceValuesMap.get(propertyName); } public void setCompilablePropertySourceValue(String propertyName, Object uncompiledPropertyValue) { compilablePropertySourceValuesMap.put(propertyName, uncompiledPropertyValue); } public void removeCompilablePropertySourceValue(String propertyName) { compilablePropertySourceValuesMap.remove(propertyName); } public DatabaseObject() { try { BeanInfo bi = CachedIntrospector.getBeanInfo(getClass()); BeanDescriptor bd = bi.getBeanDescriptor(); setBeanName(StringUtils.normalize(bd.getDisplayName())); // normalize // bean // name // #283 identity = getNewOrderValue(); compilablePropertySourceValuesMap = new HashMap<String, Object>(5); } catch (Exception e) { name = getClass().getName(); Engine.logBeans .error("Unable to set the default name; using the class name instead (\"" + name + "\").", e); } } public Icon getIcon(int iconKind) { try { BeanInfo bi = CachedIntrospector.getBeanInfo(getClass()); return new ImageIcon(bi.getIcon(iconKind)); } catch (Exception e) { Engine.logBeans.error("Unable to get the bean icon.", e); return null; } } public void checkSymbols() throws EngineException { if (isSymbolError()) { for (String property : symbolsErrors.keySet()) { String message = "The property '" + property + "' of '" + getName() + "' has an undefined global symbol!"; if (Engine.isStudioMode()) { try { Class<?> convertigoPlugin = Class .forName("com.twinsoft.convertigo.eclipse.ConvertigoPlugin"); Method m = convertigoPlugin.getMethod("warningMessageBox", String.class); m.invoke(null, message); } catch (Exception e) { Engine.logBeans.error("Unable to invoke the warningMessageBox method.", e); } } throw new EngineException(message); } } } @Override public DatabaseObject clone() throws CloneNotSupportedException { if (original == null) { try { DatabaseObject clone = (DatabaseObject) super.clone(); clone.original = this; clone.parent = null; clone.bNew = false; clone.isImporting = false; clone.isSubLoaded = false; //Engine.isEngineMode() ? isSubLoaded : false; clone.hasChanged = false; //Engine.isEngineMode() ? false : hasChanged;// Studio // case // of // refresh // without // saving clone.compilablePropertySourceValuesMap = new HashMap<String, Object>(5); clone.compilablePropertySourceValuesMap.putAll(compilablePropertySourceValuesMap); return clone; } catch (Exception e) { Engine.logBeans.error("Unable to clone the object \"" + getName() + "\"", e); String message = "DatabaseObject.clone() " + e.getClass().getName() + "\n" + e.getMessage(); throw new CloneNotSupportedException(message); } } else { return original.clone(); } } public void add(DatabaseObject databaseObject) throws EngineException { databaseObject.setParent(this); } public void remove(DatabaseObject databaseObject) throws EngineException { databaseObject.parent = null; } public void delete() throws EngineException { Engine.logBeans.info("Deleting the object \"" + getName() + "\""); if (parent != null) { parent.remove(this); } parent = null; } public transient boolean hasChanged = false; public transient boolean bNew = false; /** * The type of the database object. This type is used for storing the object * into the database. */ transient protected String databaseType = "undefined"; public String getDatabaseType() { return databaseType; } /** * The parent database object (null only for top object : project). */ transient protected DatabaseObject parent = null; /** * Retrieves the parent Object object. */ public DatabaseObject getParent() { return parent; } public Project getProject() { DatabaseObject databaseObject = this; while (!(databaseObject instanceof Project) && databaseObject != null) { databaseObject = databaseObject.getParent(); } if (databaseObject == null) return null; else return (Project) databaseObject; } public String getTokenPath(String oldName) { String tokenPath = oldName == null ? getName() : oldName; DatabaseObject parentDbo = parent; while (parentDbo != null) { tokenPath = parentDbo.getName() + "." + tokenPath; if (parentDbo instanceof Project) break; else parentDbo = parentDbo.getParent(); } return tokenPath; } public Connector getConnector() { if (this instanceof Project) { return null; } if (this instanceof Sequence) { return null; } if (this instanceof Step) { return null; } if (this instanceof Connector) { return (Connector) this; } else { DatabaseObject databaseObject = parent; while (!(databaseObject instanceof Connector)) { databaseObject = databaseObject.getParent(); } return (Connector) databaseObject; } } /** * Sets the parent Object object. */ public void setParent(DatabaseObject databaseObject) { if (parent != null) { parent.changed(); } parent = databaseObject; if (parent != null) { parent.changed(); } changed(); } /** * Returns the fully qualified name of the object, i.e. with the object * path, for writing purposes. * * @return the fully qualified name of the object. */ public String getQName() { String qname; if (parent != null) { qname = parent.getQName() + "." + getName(); } else { qname = "?." + getName(); } return qname; } /** * The priority of object. */ transient public long priority = 0; /** * The object name. */ private String name = "new object"; /** * Retrieves the object name. * * @return the object name. */ public String getName() { return name; } /** * Sets the bean name and computes file name. * * @param name * the bean name. */ private void setBeanName(String name) throws EngineException { if (name.length() == 0) { throw new EngineException("The object name cannot be empty!"); } this.name = name; } /** * Sets the object name. * * @param name * the object name. */ public void setName(String name) throws EngineException { if (name == null) { throw new EngineException("The object name cannot be null!"); } if (name.length() == 0) { throw new EngineException("The object name cannot be empty!"); } // warns if bean name is not normalized if (!name.equals(StringUtils.normalize(name))) { Engine.logBeans.warn( "Unnormalized name: \"" + name + "\" for databaseObject (" + getClass().getSimpleName() + ")"); } // set new name and new computed file name setBeanName(name); } /** * Returns an available name for a new child database object to add. * * @param eDatabaseObjects * an enumeration of children database objects * @param dboName * the name of a new child database object * @return */ public String getChildBeanName(Collection<? extends DatabaseObject> v, String dboName, boolean isNew) { String newDatabaseObjectName = dboName; boolean bContinue = isNew; int index = 0; while (bContinue) { if (index == 0) { newDatabaseObjectName = dboName; } else { newDatabaseObjectName = dboName + index; } try { for (DatabaseObject databaseObject : v) { if (newDatabaseObjectName.equals(databaseObject.getName())) { throw new ObjectWithSameNameException("Unable to add the object \"" + newDatabaseObjectName + "\" because an object with the same name already exists."); } } bContinue = false; } catch (ObjectWithSameNameException e) { index++; } } return newDatabaseObjectName; } /** * Get order for quick sort. */ public Object getOrderedValue() { return name.toLowerCase(); } synchronized public long getNewOrderValue() { long now = System.currentTimeMillis(); if (lastTime < now) { lastTime = now; } else { lastTime++; } return lastTime; } /** * Get representation of order for quick sort of a given database object. */ public Object getOrder(Object object) throws EngineException { if (object instanceof DatabaseObject) { return ((DatabaseObject) object).getOrderedValue(); } return object.toString(); } @Override public String toString() { return name; } public transient long newPriority = 0; public Element toXml(Document document) throws EngineException { Element element = document.createElement(getDatabaseType().toLowerCase()); element.setAttribute("classname", getClass().getName()); if (exportOptions.contains(ExportOption.bIncludeVersion)) { element.setAttribute("version", com.twinsoft.convertigo.beans.Version.version); } // Storing the database object priority element.setAttribute("priority", new Long(priority).toString()); int len; PropertyDescriptor[] propertyDescriptors; PropertyDescriptor propertyDescriptor; Element propertyElement; try { BeanInfo bi = CachedIntrospector.getBeanInfo(getClass()); propertyDescriptors = bi.getPropertyDescriptors(); len = propertyDescriptors.length; if (exportOptions.contains(ExportOption.bIncludeDisplayName)) { element.setAttribute("displayName", bi.getBeanDescriptor().getDisplayName()); } } catch (IntrospectionException e) { throw new EngineException("Couldn't introspect the bean \"" + getName() + "\"", e); } for (int i = 0; i < len; i++) { propertyDescriptor = propertyDescriptors[i]; String name = propertyDescriptor.getName(); String displayName = propertyDescriptor.getDisplayName(); String shortDescription = propertyDescriptor.getShortDescription(); Method getter = propertyDescriptor.getReadMethod(); // Only analyze read propertyDescriptors. if (getter == null) { continue; } if (checkBlackListParentClass(propertyDescriptor)) { continue; } try { // Storing the database object bean properties Object uncompiledValue = getCompilablePropertySourceValue(name); Object compiledValue = null; Object cypheredValue = null; Object value = getter.invoke(this); if (uncompiledValue != null) { compiledValue = value; value = uncompiledValue; } // Only write non-null values if (value == null) { Engine.logBeans.warn("Attempting to store null property (\"" + name + "\"); skipping..."); continue; } propertyElement = document.createElement("property"); propertyElement.setAttribute("name", name); // Encrypts value if needed //if (isCipheredProperty(name) && !this.exportOptions.contains(ExportOption.bIncludeDisplayName)) { if (isCipheredProperty(name) && (this.exportOptions.contains(ExportOption.bHidePassword) || !this.exportOptions.contains(ExportOption.bIncludeDisplayName))) { cypheredValue = encryptPropertyValue(value); if (!value.equals(cypheredValue)) { value = cypheredValue; propertyElement.setAttribute("ciphered", "true"); } } // Stores the value Node node = null; if (exportOptions.contains(ExportOption.bIncludeCompiledValue)) { node = XMLUtils.writeObjectToXml(document, value, compiledValue); } else { node = XMLUtils.writeObjectToXml(document, value); } propertyElement.appendChild(node); // Add visibility for logs if (!isTraceableProperty(name)) { propertyElement.setAttribute("traceable", "false"); } if (exportOptions.contains(ExportOption.bIncludeBlackListedElements)) { Object propertyDescriptorBlackListValue = propertyDescriptor .getValue(MySimpleBeanInfo.BLACK_LIST_NAME); if (propertyDescriptorBlackListValue != null && (Boolean) propertyDescriptorBlackListValue) { propertyElement.setAttribute("blackListed", "blackListed"); } } if (exportOptions.contains(ExportOption.bIncludeDisplayName)) { propertyElement.setAttribute("displayName", displayName); propertyElement.setAttribute("isHidden", Boolean.toString(propertyDescriptor.isHidden())); propertyElement.setAttribute("isMasked", isMaskedProperty(Visibility.Platform, name) ? "true" : "false"); propertyElement.setAttribute("isExpert", Boolean.toString(propertyDescriptor.isExpert())); } if (exportOptions.contains(ExportOption.bIncludeShortDescription)) { propertyElement.setAttribute("shortDescription", shortDescription); } if (exportOptions.contains(ExportOption.bIncludeEditorClass)) { Class<?> pec = propertyDescriptor.getPropertyEditorClass(); String message = ""; if (pec != null) { message = propertyDescriptor.getPropertyEditorClass().toString().replaceFirst("(.)*\\.", ""); } else { message = "null"; } if (this instanceof ITagsProperty || (pec != null && Enum.class.isAssignableFrom(pec))) { String[] sResults = null; try { if (this instanceof ITagsProperty) { sResults = ((ITagsProperty) this).getTagsForProperty(name); } else { sResults = EnumUtils.toNames(pec); } } catch (Exception ex) { sResults = new String[0]; } if (sResults != null) { if (sResults.length > 0) { Element possibleValues = document.createElement("possibleValues"); Element possibleValue = null; for (int j = 0; j < sResults.length; j++) { possibleValue = document.createElement("value"); possibleValue.setTextContent(sResults[j]); possibleValues.appendChild(possibleValue); } propertyElement.appendChild(possibleValues); } } } propertyElement.setAttribute("editorClass", message); } element.appendChild(propertyElement); if (Boolean.TRUE.equals(propertyDescriptor.getValue("nillable"))) { try { Method method = this.getClass().getMethod("isNullProperty", new Class[] { String.class }); Object isNull = method.invoke(this, new Object[] { name }); propertyElement.setAttribute("isNull", isNull.toString()); } catch (Exception ex) { Engine.logBeans.error( "[Serialization] Skipping 'isNull' attribute for property \"" + name + "\".", ex); } } } catch (Exception e) { Engine.logBeans.error("[Serialization] Skipping property \"" + name + "\".", e); } } return element; } public Element toXml(Document document, ExportOption... exportOptions) throws EngineException { try { this.exportOptions.addAll(Arrays.asList(exportOptions)); return toXml(document); } finally { this.exportOptions.clear(); } } /** * Performs custom configuration on the XML document for this database * object BEFORE its de-serialization. */ public void preconfigure(Element element) throws Exception { // Do nothing by default } /** * Performs custom configuration on the database object AFTER its * de-serialization. */ public void configure(Element element) throws Exception { // Do nothing by default } /** * Reads the object from XML serialized data. */ public static DatabaseObject read(String filename) throws EngineException, IOException { Element rootElement = null; try { Document document = XMLUtils.parseDOM(filename); rootElement = document.getDocumentElement(); } catch (IOException e) { throw e; } catch (Exception e) { throw new EngineException("Unable to create the object from the serialized data.", e); } return DatabaseObject.read(rootElement); } public static DatabaseObject read(Node node) throws EngineException { String objectClassName = "n/a"; String childNodeName = "n/a"; String propertyName = "n/a"; String propertyValue = "n/a"; DatabaseObject databaseObject = null; Element element = (Element) node; objectClassName = element.getAttribute("classname"); // Migration to 4.x+ projects if (objectClassName.equals("com.twinsoft.convertigo.beans.core.ScreenClass")) { objectClassName = "com.twinsoft.convertigo.beans.screenclasses.JavelinScreenClass"; } String version = element.getAttribute("version"); if ("".equals(version)) { version = node.getOwnerDocument().getDocumentElement().getAttribute("beans"); if (!"".equals(version)) { element.setAttribute("version", version); } } // Verifying product version if (VersionUtils.compareProductVersion(Version.productVersion, version) < 0) { String message = "Unable to create an object of product version superior to the current beans product version (" + com.twinsoft.convertigo.beans.Version.version + ").\n" + "Object class: " + objectClassName + "\n" + "Object version: " + version; EngineException ee = new EngineException(message); throw ee; } try { Engine.logBeans.trace("Creating object of class \"" + objectClassName + "\""); databaseObject = (DatabaseObject) Class.forName(objectClassName).newInstance(); } catch (Exception e) { String s = node.getNodeName();// XMLUtils.prettyPrintDOM(node); String message = "Unable to create a new instance of the object from the serialized XML data.\n" + "Object class: '" + objectClassName + "'\n" + "Object version: " + version + "\n" + "XML data:\n" + s; EngineException ee = new EngineException(message, e); throw ee; } try { // Performs custom configuration before object de-serialization databaseObject.preconfigure(element); } catch (Exception e) { String s = XMLUtils.prettyPrintDOM(node); String message = "Unable to configure the object from serialized XML data before its creation.\n" + "Object class: '" + objectClassName + "'\n" + "XML data:\n" + s; EngineException ee = new EngineException(message, e); throw ee; } try { long priority = new Long(element.getAttribute("priority")).longValue(); databaseObject.priority = priority; Class<? extends DatabaseObject> databaseObjectClass = databaseObject.getClass(); BeanInfo bi = CachedIntrospector.getBeanInfo(databaseObjectClass); PropertyDescriptor[] pds = bi.getPropertyDescriptors(); NodeList childNodes = element.getChildNodes(); int len = childNodes.getLength(); PropertyDescriptor pd; Object propertyObjectValue; Class<?> propertyType; NamedNodeMap childAttributes; boolean maskValue = false; for (int i = 0; i < len; i++) { Node childNode = childNodes.item(i); if (childNode.getNodeType() != Node.ELEMENT_NODE) { continue; } Element childElement = (Element) childNode; childNodeName = childNode.getNodeName(); Engine.logBeans.trace("Analyzing node '" + childNodeName + "'"); if (childNodeName.equalsIgnoreCase("property")) { childAttributes = childNode.getAttributes(); propertyName = childAttributes.getNamedItem("name").getNodeValue(); Engine.logBeans.trace(" name = '" + propertyName + "'"); pd = findPropertyDescriptor(pds, propertyName); if (pd == null) { Engine.logBeans.warn( "Unable to find the definition of property \"" + propertyName + "\"; skipping."); continue; } propertyType = pd.getPropertyType(); propertyObjectValue = XMLUtils .readObjectFromXml((Element) XMLUtils.findChildNode(childNode, Node.ELEMENT_NODE)); // Hides value in log trace if needed if ("false".equals(childElement.getAttribute("traceable"))) { maskValue = true; } Engine.logBeans.trace(" value='" + (maskValue ? Visibility.maskValue(propertyObjectValue) : propertyObjectValue) + "'"); // Decrypts value if needed try { if ("true".equals(childElement.getAttribute("ciphered"))) { propertyObjectValue = decryptPropertyValue(propertyObjectValue); } } catch (Exception e) { } propertyObjectValue = databaseObject.compileProperty(propertyType, propertyName, propertyObjectValue); if (Enum.class.isAssignableFrom(propertyType)) { propertyObjectValue = EnumUtils.valueOf(propertyType, propertyObjectValue); } propertyValue = propertyObjectValue.toString(); Method setter = pd.getWriteMethod(); Engine.logBeans.trace(" setter='" + setter.getName() + "'"); Engine.logBeans.trace(" param type='" + propertyObjectValue.getClass().getName() + "'"); Engine.logBeans.trace(" expected type='" + propertyType.getName() + "'"); try { setter.invoke(databaseObject, new Object[] { propertyObjectValue }); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); Engine.logBeans.warn("Unable to set the property '" + propertyName + "' for the object '" + databaseObject.getName() + "' (" + objectClassName + "): [" + targetException.getClass().getName() + "] " + targetException.getMessage()); } if (Boolean.TRUE.equals(pd.getValue("nillable"))) { Node nodeNull = childAttributes.getNamedItem("isNull"); String valNull = (nodeNull == null) ? "false" : nodeNull.getNodeValue(); Engine.logBeans.trace(" treats as null='" + valNull + "'"); try { Method method = databaseObject.getClass().getMethod("setNullProperty", new Class[] { String.class, Boolean.class }); method.invoke(databaseObject, new Object[] { propertyName, Boolean.valueOf(valNull) }); } catch (Exception ex) { Engine.logBeans.warn("Unable to set the 'isNull' attribute for property '" + propertyName + "' of '" + databaseObject.getName() + "' object"); } } } } } catch (Exception e) { String message = "Unable to set the object properties from the serialized XML data.\n" + "Object class: '" + objectClassName + "'\n" + "XML analyzed node: " + childNodeName + "\n" + "Property name: " + propertyName + "\n" + "Property value: " + propertyValue; EngineException ee = new EngineException(message, e); throw ee; } try { // Performs custom configuration databaseObject.configure(element); } catch (Exception e) { String s = XMLUtils.prettyPrintDOM(node); String message = "Unable to configure the object from serialized XML data after its creation.\n" + "Object class: '" + objectClassName + "'\n" + "XML data:\n" + s; EngineException ee = new EngineException(message, e); throw ee; } return databaseObject; } public Object compileProperty(String propertyName, Object propertyObjectValue) { return compileProperty(String.class, propertyName, propertyObjectValue); } public Object compileProperty(Class<?> propertyType, String propertyName, Object propertyObjectValue) { Object compiled; try { compiled = Engine.theApp.databaseObjectsManager.getCompiledValue(propertyObjectValue); removeSymbolError(propertyName); } catch (UndefinedSymbolsException e) { addSymbolError(propertyName, e.undefinedSymbols()); compiled = e.incompletValue(); } if (compiled != propertyObjectValue) { setCompilablePropertySourceValue(propertyName, propertyObjectValue); propertyObjectValue = compiled; } else { removeCompilablePropertySourceValue(propertyName); } propertyType = ClassUtils.primitiveToWrapper(propertyType); if (Number.class.isAssignableFrom(propertyType)) { try { try { propertyObjectValue = propertyType.getConstructor(String.class) .newInstance(propertyObjectValue.toString()); } catch (Exception e) { Engine.logBeans.warn("(DatabaseObject) Failed to parse '" + propertyObjectValue + "' as " + propertyType.getSimpleName() + ". Set 0 instead."); propertyObjectValue = propertyType.getConstructor(String.class).newInstance("0"); } } catch (Exception e) { Engine.logBeans.error("(DatabaseObject) Failed to parse '" + propertyObjectValue + "' as " + propertyType.getSimpleName()); } } else if (Boolean.class.isAssignableFrom(propertyType)) { if (propertyObjectValue instanceof Integer) { propertyObjectValue = (Integer) propertyObjectValue == 0; } else { propertyObjectValue = Boolean.parseBoolean(propertyObjectValue.toString()); } } else if (Enum.class.isAssignableFrom(propertyType) && propertyObjectValue instanceof String) { propertyObjectValue = EnumUtils.valueOf(propertyType, propertyObjectValue); } return propertyObjectValue; } public boolean isMaskedProperty(Visibility target, String propertyName) { return false; } public boolean isCipheredProperty(String propertyName) { return false; } public boolean isTraceableProperty(String propertyName) { return true; } public static String encryptPropertyValue(String propertyValue) { return Crypto2.encodeToHexString(propertyValue); } public static <E> E encryptPropertyValue(E propertyValue) { if (propertyValue == null) { return null; } E encryptedValue = null; if (propertyValue instanceof String) { encryptedValue = GenericUtils.cast(Crypto2.encodeToHexString((String) propertyValue)); } else if (propertyValue instanceof XMLVector<?>) { try { XMLVector<Object> xmlv = new XMLVector<Object>(GenericUtils.<XMLVector<Object>>cast(propertyValue)); for (int i = 0; i < xmlv.size(); i++) { Object ob = xmlv.get(i); xmlv.set(i, encryptPropertyValue(ob)); } encryptedValue = GenericUtils.cast(xmlv); } catch (Exception e) { } } else if (propertyValue instanceof SmartType) { SmartType st = (SmartType) propertyValue; SmartType newSt = new SmartType(); newSt.setMode(st.getMode()); newSt.setExpression(encryptPropertyValue(st.getExpression())); newSt.setSourceDefinition(encryptPropertyValue(st.getSourceDefinition())); encryptedValue = GenericUtils.cast(newSt); } if (encryptedValue == null) { encryptedValue = propertyValue; } return encryptedValue; } public static <E> E decryptPropertyValue(E encryptedValue) { if (encryptedValue == null) { return null; } E propertyValue = null; if (encryptedValue instanceof String) { try { propertyValue = GenericUtils.cast(Crypto2.decodeFromHexString3((String) encryptedValue)); } catch (Exception e) { Engine.logBeans.trace("Failed to decode a property value", e); propertyValue = encryptedValue; } } else if (encryptedValue instanceof XMLVector<?>) { try { XMLVector<Object> xmlv = new XMLVector<Object>( GenericUtils.<XMLVector<Object>>cast(encryptedValue)); for (int i = 0; i < xmlv.size(); i++) { Object ob = xmlv.get(i); xmlv.set(i, decryptPropertyValue(ob)); } propertyValue = GenericUtils.cast(xmlv); } catch (Exception e) { } } else if (encryptedValue instanceof SmartType) { SmartType st = (SmartType) encryptedValue; SmartType newSt = new SmartType(); newSt.setMode(st.getMode()); newSt.setExpression(decryptPropertyValue(st.getExpression())); newSt.setSourceDefinition(decryptPropertyValue(st.getSourceDefinition())); propertyValue = GenericUtils.cast(newSt); } if (propertyValue == null) { propertyValue = encryptedValue; } return propertyValue; } protected static PropertyDescriptor findPropertyDescriptor(PropertyDescriptor[] pds, String pn) { int len = pds.length; PropertyDescriptor pd; for (int i = 0; i < len; i++) { pd = pds[i]; if (pn.equals(pd.getName())) { return pd; } } return null; } /** * Writes the object to the Convertigo repository database. */ public void write() throws EngineException { hasChanged = false; bNew = false; } /** * Writes the object to the Convertigo repository database. */ public void write(String databaseObjectQName) throws EngineException { write(); } /** Holds value of property version. */ private String version = ""; /** * Setter for property version. * * @param version * New value of property version. */ public void setVersion(String version) { this.version = version; } /** * Getter for property version. * * @return Value of property version. */ public String getVersion() { return this.version; } /** Holds value of property comment. */ private String comment = ""; /** * Getter for property comment. * * @return Value of property comment. */ public String getComment() { return comment; } /** * Setter for property comment. * * @param comment * New value of property comment. */ public void setComment(String comment) { this.comment = comment; } synchronized public void checkSubLoaded() { if (original != null && !isSubLoaded) { isSubLoaded = true; try { subLoader.get().init(this); } catch (EngineException e) { Engine.logBeans.error("(DatabaseObject) getSubDatabaseObjects failed with EngineException!", e); } catch (DatabaseObjectNotFoundException e) { Engine.logBeans.error("Database object not found: " + e.getMessage()); } catch (Exception e) { Engine.logBeans.error("Another Exception: " + e.getMessage(), e); } } } public long getIdentity() { return identity; } public DatabaseObject getOriginal() { return original != null ? original : this; } public boolean isOriginal() { return original == null; } protected <E extends DatabaseObject> List<E> sort(List<E> list) { return sort(list, true); } protected <E extends Object> List<E> sort(List<E> list, boolean ascending) { Collections.sort(list, new Comparator<Object>() { @SuppressWarnings("unchecked") public int compare(Object o1, Object o2) { try { return ((Comparable<Object>) getOrder(o1)).compareTo(getOrder(o2)); } catch (EngineException e) { return 0; } } }); List<E> res = new ArrayList<E>(list); if (!ascending) { Collections.reverse(res); } return res; } public String[] getNames(Collection<? extends DatabaseObject> dbos) { int i = 0; String[] res = new String[dbos.size()]; for (DatabaseObject dbo : dbos) { res[i++] = dbo != null ? dbo.getName() : ""; } return res; } public String[] getNamesWithFirstEmptyItem(Collection<? extends DatabaseObject> dbos) { String[] res = new String[dbos.size() + 1]; res[0] = ""; int i = 1; for (DatabaseObject dbo : dbos) { res[i++] = dbo != null ? dbo.getName() : ""; } return res; } public <E extends DatabaseObject> List<E> getAllChildren() { return new ArrayList<E>(); } public void changed() { if (!isImporting && !hasChanged) { hasChanged = true; } } public void addSymbolError(String propertyName, Set<String> undefinedSymbols) { if (symbolsErrors == null) { symbolsErrors = new HashMap<String, Set<String>>(); } symbolsErrors.put(propertyName, undefinedSymbols); DatabaseObjectsManager.getProjectLoadingData().undefinedGlobalSymbol = true; } private synchronized void removeSymbolError(String propertyName) { if (symbolsErrors != null) { symbolsErrors.remove(propertyName); if (symbolsErrors.isEmpty()) { symbolsErrors = null; } } } public synchronized boolean isSymbolError() { return symbolsErrors != null; } public boolean checkBlackListParentClass(PropertyDescriptor propertyDescriptor) { return parent != null && parent.getClass().getCanonicalName() .equals(propertyDescriptor.getValue(MySimpleBeanInfo.BLACK_LIST_PARENT_CLASS)); } public synchronized Map<String, Set<String>> getSymbolsErrors() { return new HashMap<String, Set<String>>(symbolsErrors); } public synchronized Set<String> getSymbolsErrors(String parameterName) { return symbolsErrors == null ? null : symbolsErrors.get(parameterName); } public void updateSymbols() throws Exception { if (!compilablePropertySourceValuesMap.isEmpty()) { PropertyDescriptor[] propertyDescriptors = CachedIntrospector.getBeanInfo(getClass()) .getPropertyDescriptors(); for (Entry<String, Object> propertySource : compilablePropertySourceValuesMap.entrySet()) { String propertyName = propertySource.getKey(); Object propertyValue = propertySource.getValue(); PropertyDescriptor propertyDescriptor = findPropertyDescriptor(propertyDescriptors, propertyName); Class<?> propertyType = propertyDescriptor.getPropertyType(); Object newValue = compileProperty(propertyType, propertyName, propertyValue); propertyDescriptor.getWriteMethod().invoke(this, newValue); } } } }