Index: C:/opensource/projects/castor/src/main/java/org/exolab/castor/xml/Marshaller.java =================================================================== --- C:/opensource/projects/castor/src/main/java/org/exolab/castor/xml/Marshaller.java (revision 6121) +++ C:/opensource/projects/castor/src/main/java/org/exolab/castor/xml/Marshaller.java (working copy) @@ -88,6 +88,7 @@ //import java.io.Serializable; import java.io.Writer; import java.lang.reflect.Array; +import java.lang.reflect.Proxy; import java.util.Enumeration; @@ -922,8 +923,53 @@ Class _class = null; - if (!isNil) { - _class = object.getClass(); + if (!isNil) + { + /* + * Check to see if this is a Proxied object, if it is, it needs to be handled special + * + * Fetch all the interfaces on the Proxied Object, see if you can find a match in + * the XMLMapping for the given interface. + * If you do, return the interface class else return the proxy class + * + * Need to set the class attribute verify-constructable="false" on the Mapped interface. + * + * Limitations: + * A proxy can proxy more then one interface. + * If you have mappings for more then one of the interfaces in the mapping file, it will + * choose the first match in the Proxy -> Class[] interfaces + * + */ + if(Proxy.isProxyClass(object.getClass())) + { + if(this._debug)System.out.println("Current object is a proxy class"); + XMLMappingLoader ml = (XMLMappingLoader) _cdResolver.getMappingLoader(); + if (ml != null) + { + Class[] interfaces = object.getClass().getInterfaces(); + for(int i = 0; i < interfaces.length; i++) + { + Class interfaceClass = interfaces[i]; + if(this._debug)System.out.println("Looking up interface on proxy: " + interfaceClass.getName()); + if(ml.getDescriptor(interfaceClass.getName()) != null) + { + if(this._debug)System.out.println("Found mapping for interface " + interfaceClass.getName()); + _class = interfaceClass; + break; + } + } + if(_class == null) + { + if(_debug) + System.out.println("No mapped interface found on proxy class.. using proxy class"); + _class = object.getClass(); + } + } + else + if(this._debug)System.out.println("No XMLMappingLoader found"); + } + else + _class = object.getClass(); } else { _class = ((NilObject)object).getClassDescriptor().getJavaClass(); Index: C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DefaultObjectFactory.java =================================================================== --- C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DefaultObjectFactory.java (revision 6121) +++ C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DefaultObjectFactory.java (working copy) @@ -110,6 +110,15 @@ if (java.util.Date.class.isAssignableFrom(type)) { return handleDates(type); } + /* + * If the type is an interface we can't make a normal instanace of using .newInstance() + * + * We fake a new instance via a proxy.. + */ + if(type.isInterface()) + { + return DynamicInstance.getInstance(type); + } return type.newInstance(); } Index: C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DynamicInstance.java =================================================================== --- C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DynamicInstance.java (revision 0) +++ C:/opensource/projects/castor/src/main/java/org/exolab/castor/util/DynamicInstance.java (revision 0) @@ -0,0 +1,102 @@ +package org.exolab.castor.util; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +/* + * Helper class to make runtime instances of valueobjects. + * + * Returns a proxied interface. + * + * Example of lookup: + * Signature Name Type + * -------------------------------- + * getMethod Method GET + * setMethod Method SET + * getName Name GET + * setName Name SET + * + * setMethods put value to the internal values Map + * getMethods get value from the internal values Map + */ +public class DynamicInstance implements InvocationHandler { + + public static Object getInstance(final Class inter) + { + if(inter == null) + return null; + + return Proxy.newProxyInstance( + inter.getClassLoader(), + new Class[] {inter}, + new DynamicInstance()); + } + + private Map values; // + + private DynamicInstance() + { + this.values = new HashMap(); // + } + + public final int TypeSET = 0; + public final int TypeGET = 1; + public final int TypeOTHER = 2; + + public Object invoke(final Object object, final Method method, final Object[] arguments) + throws Throwable + { + int methodType = getMethodType(method); + + // no clue witch to return on the get if there is more then one parameter to set + if(methodType == TypeSET && (arguments != null && arguments.length != 1)) + throw new IllegalArgumentException("only handles set methods with one parmeter"); + + switch(methodType) + { + case TypeSET: + setValue(getMethodName(method), arguments[0]); + break; + case TypeGET: + { + Object result = getValue(getMethodName(method)); + return result; + } + } + return null; + } + + private Object getValue(String name) + { + return this.values.get(name); + } + + private void setValue(String name, Object object) + { + this.values.put(name, object); + } + + private int getMethodType(Method method) + { + String methodName = method.getName(); + if(methodName.startsWith("set")) + return TypeSET; + if(methodName.startsWith("get")) + return TypeGET; + + return TypeOTHER; + } + + private String getMethodName(Method method) + { + String methodName = method.getName(); + if(methodName.startsWith("set")) + return methodName.substring(3); + if(methodName.startsWith("get")) + return methodName.substring(3); + return null; + } +}