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;
}
}
}