Red Hat Application Migration Toolkit
package org.exolab.castor.xml; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.castor.xml.InternalContext; import org.castor.xml.JavaNaming; import org.castor.xml.XMLNaming; import org.exolab.castor.mapping.CollectionHandler; import org.exolab.castor.mapping.FieldHandler; import org.exolab.castor.mapping.FieldHandlerFactory; import org.exolab.castor.mapping.GeneralizedFieldHandler; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.mapping.TypeConvertor; import org.exolab.castor.mapping.loader.CollectionHandlers; import org.exolab.castor.mapping.loader.FieldHandlerImpl; import org.exolab.castor.mapping.loader.TypeInfo; import org.exolab.castor.util.ReflectionUtil; import org.exolab.castor.xml.IntrospectedXMLClassDescriptor; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.NodeType; import org.exolab.castor.xml.XMLClassDescriptor; import org.exolab.castor.xml.descriptors.CoreDescriptors; import org.exolab.castor.xml.handlers.ContainerFieldHandler; import org.exolab.castor.xml.handlers.DateFieldHandler; import org.exolab.castor.xml.handlers.DefaultFieldHandlerFactory; import org.exolab.castor.xml.util.ContainerElement; import org.exolab.castor.xml.util.XMLClassDescriptorImpl; import org.exolab.castor.xml.util.XMLFieldDescriptorImpl; public final class Introspector { private static final FieldHandlerFactory DEFAULT_HANDLER_FACTORY = new DefaultFieldHandlerFactory(); private static final Class[] EMPTY_CLASS_ARGS = new Class[0]; private static final String LIST = "java.util.List"; private static final String MAP = "java.util.Map"; private static final String SET_COLLECTION = "java.util.Set"; private static final String COLLECTION_WRAPPER_PREFIX = "##container_for_"; private static final boolean WRAP_COLLECTIONS_DEFAULT = false; private static final Class[] COLLECTIONS = loadCollections(); private static XMLNaming _defaultNaming = null; private XMLNaming _xmlNaming; private NodeType _primitiveNodeType; private boolean _wrapCollectionsInContainer; private Vector _handlerFactoryList; private Hashtable _handlerFactoryMap; private boolean _saveMapKeys; private ClassLoader _classLoader; private JavaNaming _javaNaming; private InternalContext _internalContext; public Introspector() { this((ClassLoader)null); } public Introspector(ClassLoader classLoader) { this._xmlNaming = null; this._primitiveNodeType = null; this._wrapCollectionsInContainer = false; this._handlerFactoryList = null; this._handlerFactoryMap = null; this._saveMapKeys = true; this._classLoader = null; this._classLoader = classLoader; this.init(); } private void init() { if(this._internalContext != null) { this._javaNaming = this._internalContext.getJavaNaming(); this._xmlNaming = this._internalContext.getXMLNaming(); this.setPrimitiveNodeType(this._internalContext.getPrimitiveNodeType()); this._wrapCollectionsInContainer = this._internalContext.getBooleanProperty("org.exolab.castor.xml.introspector.wrapCollections").booleanValue(); this._saveMapKeys = this._internalContext.getBooleanProperty("org.exolab.castor.xml.saveMapKeys").booleanValue(); } } public void setInternalContext(InternalContext internalContext) { this._internalContext = internalContext; this.init(); } public synchronized void addFieldHandlerFactory(FieldHandlerFactory factory) { if(factory == null) { String err = "The argument \'factory\' must not be null."; throw new IllegalArgumentException(err); } else { if(this._handlerFactoryList == null) { this._handlerFactoryList = new Vector(); } this._handlerFactoryList.addElement(factory); this.registerHandlerFactory(factory); } } public NodeType getPrimitiveNodeType() { return this._primitiveNodeType; } public XMLClassDescriptor generateClassDescriptor(Class c) throws MarshalException { return this.generateClassDescriptor(c, (PrintWriter)null); } public XMLClassDescriptor generateClassDescriptor(Class c, PrintWriter errorWriter) throws MarshalException { if(c == null) { return null; } else if(c.isArray()) { return null; } else if(c != Void.class && c != Class.class && c != Object.class) { XMLClassDescriptor coreDesc = CoreDescriptors.getDescriptor(c); if(coreDesc != null) { return coreDesc; } else { IntrospectedXMLClassDescriptor classDesc = new IntrospectedXMLClassDescriptor(c); Method[] methods = c.getMethods(); ArrayList dateDescriptors = new ArrayList(3); Hashtable methodSets = new Hashtable(); int methodCount = 0; Class superClass = c.getSuperclass(); Class[] interfaces = c.getInterfaces(); boolean handler; Method type; Class var47; for(int enumeration = 0; enumeration < methods.length; ++enumeration) { Method mx = methods[enumeration]; Class fieldDesc = mx.getDeclaringClass(); String var44; if(fieldDesc != c) { if(!fieldDesc.isInterface()) { continue; } if(interfaces.length > 0) { handler = false; for(int dfh = 0; dfh < interfaces.length; ++dfh) { if(interfaces[dfh] == fieldDesc) { handler = true; break; } } if(!handler) { continue; } } } else if(superClass != null) { Class[] var42 = mx.getParameterTypes(); var44 = mx.getName(); type = null; try { type = superClass.getMethod(var44, var42); } catch (NoSuchMethodException var31) { ; } if(type != null) { continue; } } if((mx.getModifiers() & 8) == 0) { String var43 = mx.getName(); Introspector.MethodSet modifiers; String var49; if(var43.startsWith("get")) { if(mx.getParameterTypes().length == 0) { ++methodCount; var47 = mx.getReturnType(); if(var47 != null && isDescriptable(var47)) { var49 = var43.substring(3); var49 = this._javaNaming.toJavaMemberName(var49); modifiers = (Introspector.MethodSet)methodSets.get(var49); if(modifiers == null) { modifiers = new Introspector.MethodSet(var49); methodSets.put(var49, modifiers); } modifiers._get = mx; } } } else if(var43.startsWith("is")) { if(mx.getParameterTypes().length == 0) { var47 = mx.getReturnType(); if(var47 != null) { if(var47.isPrimitive()) { if(var47 != Boolean.TYPE) { continue; } } else if(var47 != Boolean.class) { continue; } ++methodCount; var49 = var43.substring("is".length()); var49 = this._javaNaming.toJavaMemberName(var49); modifiers = (Introspector.MethodSet)methodSets.get(var49); if(modifiers == null) { modifiers = new Introspector.MethodSet(var49); methodSets.put(var49, modifiers); } modifiers._get = mx; } } } else { Introspector.MethodSet var46; if(var43.startsWith("add")) { if(mx.getParameterTypes().length == 1) { ++methodCount; if(isDescriptable(mx.getParameterTypes()[0])) { var44 = var43.substring(3); var44 = this._javaNaming.toJavaMemberName(var44); var46 = (Introspector.MethodSet)methodSets.get(var44); if(var46 == null) { var46 = new Introspector.MethodSet(var44); methodSets.put(var44, var46); } var46._add = mx; } } } else if(var43.startsWith("set")) { if(mx.getParameterTypes().length == 1) { ++methodCount; if(isDescriptable(mx.getParameterTypes()[0])) { var44 = var43.substring(3); var44 = this._javaNaming.toJavaMemberName(var44); var46 = (Introspector.MethodSet)methodSets.get(var44); if(var46 == null) { var46 = new Introspector.MethodSet(var44); methodSets.put(var44, var46); } var46._set = mx; } } } else if(var43.startsWith("create") && mx.getParameterTypes().length == 0) { var47 = mx.getReturnType(); if(isDescriptable(var47)) { var49 = var43.substring("create".length()); var49 = this._javaNaming.toJavaMemberName(var49); modifiers = (Introspector.MethodSet)methodSets.get(var49); if(modifiers == null) { modifiers = new Introspector.MethodSet(var49); methodSets.put(var49, modifiers); } modifiers._create = mx; } } } } } Enumeration var34 = methodSets.elements(); boolean isCollection; FieldHandlerFactory typeInfo; ContainerFieldHandler handler1; while(var34.hasMoreElements()) { Introspector.MethodSet var35 = (Introspector.MethodSet)var34.nextElement(); String var38 = this._xmlNaming.toXMLName(var35._fieldName); handler = false; var47 = null; if(var35._add != null) { var47 = var35._add.getParameterTypes()[0]; handler = true; } if(var47 == null) { if(var35._get != null) { var47 = var35._get.getReturnType(); } else { if(var35._set == null) { continue; } var47 = var35._set.getParameterTypes()[0]; } } handler = handler || isCollection(var47); type = null; CollectionHandler var51 = null; if(handler && var35._add == null) { try { var51 = CollectionHandlers.getHandler(var47); } catch (MappingException var30) { ; } if(var47.isArray()) { if(var47.getComponentType() == Byte.TYPE) { var51 = null; } else { var47 = var47.getComponentType(); } } } TypeInfo var54 = new TypeInfo(var47, (TypeConvertor)null, (TypeConvertor)null, false, (Object)null, var51); Object type1 = null; isCollection = false; try { type1 = new FieldHandlerImpl(var35._fieldName, (Method[])null, (Method[])null, var35._get, var35._set, var54); if(var35._add != null) { ((FieldHandlerImpl)type1).setAddMethod(var35._add); } if(var35._create != null) { ((FieldHandlerImpl)type1).setCreateMethod(var35._create); } if(handler && this._saveMapKeys && isMapCollection(var47)) { ((FieldHandlerImpl)type1).setConvertFrom(new Introspector.IdentityConvertor()); } typeInfo = this.getHandlerFactory(var47); if(typeInfo != null) { GeneralizedFieldHandler colHandler = typeInfo.createFieldHandler(var47); if(colHandler != null) { colHandler.setFieldHandler((FieldHandler)type1); type1 = colHandler; isCollection = true; if(colHandler.getFieldType() != null) { var47 = colHandler.getFieldType(); } } } } catch (MappingException var33) { throw new MarshalException(var33); } XMLFieldDescriptorImpl var53 = this.createFieldDescriptor(var47, var35._fieldName, var38); if(handler) { var53.setMultivalued(true); var53.setNodeType(NodeType.Element); } if(Date.class.isAssignableFrom(var47) && !isCollection) { dateDescriptors.add(var53); } var53.setHandler((FieldHandler)type1); var53.setUseParentsNamespace(true); if(handler && this._wrapCollectionsInContainer) { String var56 = "##container_for_" + var35._fieldName; Class fieldName = ContainerElement.class; XMLClassDescriptorImpl xmlName = new XMLClassDescriptorImpl(fieldName); xmlName.addFieldDescriptor(var53); var53.setXMLName((String)null); var53.setMatches("*"); handler1 = new ContainerFieldHandler((FieldHandler)type1); var53.setHandler(handler1); var53 = this.createFieldDescriptor(fieldName, var56, var38); var53.setClassDescriptor(xmlName); var53.setHandler(handler1); var53.setUseParentsNamespace(true); } classDesc.addFieldDescriptor(var53); } Class var57; if(methodCount == 0) { Field[] var36 = c.getFields(); Hashtable var39 = new Hashtable(); for(int var45 = 0; var45 < var36.length; ++var45) { Field var60 = var36[var45]; var57 = var60.getDeclaringClass(); if(var57 != c) { if(!var57.isInterface()) { continue; } if(interfaces.length > 0) { boolean var55 = false; for(int var50 = 0; var50 < interfaces.length; ++var50) { if(interfaces[var50] == var57) { var55 = true; break; } } if(!var55) { continue; } } } int var61 = var60.getModifiers(); if(!Modifier.isTransient(var61) && (!Modifier.isFinal(var61) || !Modifier.isStatic(var61))) { Class var52 = var60.getType(); if(isDescriptable(var52)) { isCollection = isCollection(var52); typeInfo = null; CollectionHandler var58 = null; if(isCollection) { try { var58 = CollectionHandlers.getHandler(var52); } catch (MappingException var29) { ; } if(var52.isArray()) { if(var52.getComponentType() == Byte.TYPE) { var58 = null; } else { var52 = var52.getComponentType(); } } } String var62 = var60.getName(); String var64 = this._xmlNaming.toXMLName(var62); TypeInfo var59 = new TypeInfo(var52, (TypeConvertor)null, (TypeConvertor)null, false, (Object)null, var58); handler1 = null; boolean customHandler = false; Object var65; try { var65 = new FieldHandlerImpl(var60, var59); if(isCollection && this._saveMapKeys && isMapCollection(var52)) { ((FieldHandlerImpl)var65).setConvertFrom(new Introspector.IdentityConvertor()); } FieldHandlerFactory fieldDesc1 = this.getHandlerFactory(var52); if(fieldDesc1 != null) { GeneralizedFieldHandler gfh = fieldDesc1.createFieldHandler(var52); if(gfh != null) { gfh.setFieldHandler((FieldHandler)var65); var65 = gfh; customHandler = true; if(gfh.getFieldType() != null) { var52 = gfh.getFieldType(); } } } } catch (MappingException var32) { throw new MarshalException(var32); } XMLFieldDescriptorImpl var66 = this.createFieldDescriptor(var52, var62, var64); if(isCollection) { var66.setNodeType(NodeType.Element); var66.setMultivalued(true); } var39.put(var64, var66); classDesc.addFieldDescriptor(var66); var66.setHandler((FieldHandler)var65); var66.setUseParentsNamespace(true); if(Date.class.isAssignableFrom(var52) && !customHandler) { dateDescriptors.add(var66); } } } } } if(dateDescriptors != null) { for(int var37 = 0; var37 < dateDescriptors.size(); ++var37) { XMLFieldDescriptorImpl var41 = (XMLFieldDescriptorImpl)dateDescriptors.get(var37); FieldHandler var48 = var41.getHandler(); var41.setImmutable(true); DateFieldHandler var63 = new DateFieldHandler(var48); var57 = var41.getFieldType(); if(java.sql.Date.class.isAssignableFrom(var57)) { var63.setUseSQLDate(true); } var41.setHandler(var63); } } if(superClass != null && superClass != Void.class && superClass != Object.class && superClass != Class.class) { try { XMLClassDescriptor var40 = this.generateClassDescriptor(superClass, errorWriter); if(var40 != null) { classDesc.setExtends(var40); } } catch (MarshalException var28) { ; } } return classDesc; } } else { throw new MarshalException("The marshaller cannot marshal/unmarshal types of Void.class, Class.class or Object.class"); } } public synchronized boolean removeFieldHandlerFactory(FieldHandlerFactory factory) { if(factory == null) { String var4 = "The argument \'factory\' must not be null."; throw new IllegalArgumentException(var4); } else if(this._handlerFactoryList == null) { return false; } else if(!this._handlerFactoryList.removeElement(factory)) { return false; } else { this._handlerFactoryMap.clear(); for(int i = 0; i < this._handlerFactoryList.size(); ++i) { FieldHandlerFactory tmp = (FieldHandlerFactory)this._handlerFactoryList.elementAt(i); this.registerHandlerFactory(tmp); } return true; } } public void setWrapCollections(boolean wrapCollections) { this._wrapCollectionsInContainer = wrapCollections; } public static boolean introspected(XMLClassDescriptor descriptor) { return descriptor instanceof IntrospectedXMLClassDescriptor; } public static boolean marshallable(Class type) { if(type != Void.class && type != Class.class) { if((!type.isInterface() || type == Object.class) && !isPrimitive(type) && !type.isArray()) { try { type.getConstructor(EMPTY_CLASS_ARGS); } catch (NoSuchMethodException var2) { return CoreDescriptors.getDescriptor(type) != null; } } return true; } else { return false; } } public void setNaming(XMLNaming naming) { if(naming == null) { this._xmlNaming = _defaultNaming; } else { this._xmlNaming = naming; } } public void setPrimitiveNodeType(NodeType nodeType) { if(nodeType == NodeType.Element) { this._primitiveNodeType = nodeType; } else { this._primitiveNodeType = NodeType.Attribute; } } public void setSaveMapKeys(boolean saveMapKeys) { this._saveMapKeys = saveMapKeys; } public static String toJavaName(String name, boolean upperFirst) { int size = name.length(); char[] ncChars = name.toCharArray(); int next = 0; boolean uppercase = upperFirst; for(int i = 0; i < size; ++i) { char ch = ncChars[i]; switch(ch) { case '-': case ':': uppercase = true; break; default: if(uppercase) { ncChars[next] = Character.toUpperCase(ch); uppercase = false; } else { ncChars[next] = ch; } ++next; } } return new String(ncChars, 0, next); } private XMLFieldDescriptorImpl createFieldDescriptor(Class type, String fieldName, String xmlName) { XMLFieldDescriptorImpl fieldDesc = new XMLFieldDescriptorImpl(type, fieldName, xmlName, (NodeType)null); if(type.isArray()) { fieldDesc.setNodeType(NodeType.Element); } else if(type.isPrimitive()) { fieldDesc.setNodeType(this._primitiveNodeType); } else { fieldDesc.setNodeType(NodeType.Element); } if(type == Object.class) { fieldDesc.setMatches(xmlName + " *"); } return fieldDesc; } private FieldHandlerFactory getHandlerFactory(Class type) { if(this._handlerFactoryMap != null) { for(Class tmp = type; tmp != null; tmp = tmp.getSuperclass()) { Object obj = this._handlerFactoryMap.get(tmp); if(obj != null) { return (FieldHandlerFactory)obj; } } } return DEFAULT_HANDLER_FACTORY.isSupportedType(type)?DEFAULT_HANDLER_FACTORY:null; } private void registerHandlerFactory(FieldHandlerFactory factory) { if(this._handlerFactoryMap == null) { this._handlerFactoryMap = new Hashtable(); } Class[] types = factory.getSupportedTypes(); for(int i = 0; i < types.length; ++i) { this._handlerFactoryMap.put(types[i], factory); } } public static boolean isCollection(Class clazz) { if(clazz.isArray()) { return true; } else { for(int i = 0; i < COLLECTIONS.length; ++i) { if(clazz == COLLECTIONS[i] || COLLECTIONS[i].isAssignableFrom(clazz)) { return true; } } return false; } } public static boolean isMapCollection(Class clazz) { if(clazz.isArray()) { return false; } else { for(int i = 0; i < COLLECTIONS.length; ++i) { if(clazz == COLLECTIONS[i] || COLLECTIONS[i].isAssignableFrom(clazz)) { if(COLLECTIONS[i] == Hashtable.class) { return true; } if(COLLECTIONS[i].getName().equals("java.util.Map")) { return true; } } } return false; } } private static boolean isDescriptable(Class type) { if(type != Void.class && type != Class.class) { float javaVersion = Float.valueOf(System.getProperty("java.specification.version")).floatValue(); if((double)javaVersion >= 1.5D) { try { Boolean e = ReflectionUtil.isEnumViaReflection(type); if(e.booleanValue()) { return true; } } catch (Exception var3) { ; } } if(!type.isInterface() && type != Object.class && !isPrimitive(type) && !type.isArray()) { try { type.getConstructor(EMPTY_CLASS_ARGS); } catch (NoSuchMethodException var4) { return CoreDescriptors.getDescriptor(type) != null; } } return true; } else { return false; } } private static boolean isPrimitive(Class type) { if(type.isPrimitive()) { return true; } else if(type != Boolean.class && type != Character.class) { Class superClass = type.getSuperclass(); return superClass == Number.class?true:(superClass != null?superClass.getName().equals("java.lang.Enum"):false); } else { return true; } } private static Class[] loadCollections() { Vector collections = new Vector(6); collections.addElement(Vector.class); collections.addElement(Enumeration.class); collections.addElement(Hashtable.class); ClassLoader loader = Vector.class.getClassLoader(); Class clazz = null; try { if(loader != null) { clazz = loader.loadClass("java.util.List"); } else { clazz = Class.forName("java.util.List"); } } catch (ClassNotFoundException var5) { ; } if(clazz != null) { collections.addElement(clazz); clazz = null; try { if(loader != null) { clazz = loader.loadClass("java.util.Map"); } else { clazz = Class.forName("java.util.Map"); } if(clazz != null) { collections.addElement(clazz); } if(loader != null) { clazz = loader.loadClass("java.util.Set"); } else { clazz = Class.forName("java.util.Set"); } if(clazz != null) { collections.addElement(clazz); } } catch (ClassNotFoundException var4) { ; } } Class[] classes = new Class[collections.size()]; collections.copyInto(classes); return classes; } class MethodSet { Method _add = null; Method _create = null; Method _get = null; Method _set = null; String _fieldName = null; MethodSet(String fieldName) { this._fieldName = fieldName; } } class IdentityConvertor implements TypeConvertor { public Object convert(Object object) { return object; } } }