Index: /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Proxy.java
===================================================================
--- /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Proxy.java (Revision 0)
+++ /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Proxy.java (Revision 0)
@@ -0,0 +1,29 @@
+package xml.c1342;
+
+import java.lang.reflect.Method;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+public class Proxy implements MethodInterceptor {
+ public static Object newInstance(final Object object){
+ try{
+ Proxy proxy = new Proxy(object);
+ return Enhancer.create(object.getClass(), new Class[] {}, proxy);
+ } catch (Throwable e){
+ e.printStackTrace();
+ throw new Error(e.getMessage());
+ }
+ }
+
+ private final Object _object;
+
+ private Proxy(final Object object) {
+ _object = object;
+ }
+
+ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
+ return method.invoke(_object, args);
+ }
+}
Index: /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Bean.java
===================================================================
--- /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Bean.java (Revision 0)
+++ /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Bean.java (Revision 0)
@@ -0,0 +1,40 @@
+package xml.c1342;
+
+public class Bean {
+ private Integer _attribute;
+ private String _element;
+ private String _text;
+ private Bean _reference;
+
+ public Integer getAttribute() {
+ return _attribute;
+ }
+
+ public void setAttribute(final Integer attribute) {
+ _attribute = attribute;
+ }
+
+ public String getElement() {
+ return _element;
+ }
+
+ public void setElement(final String element) {
+ _element = element;
+ }
+
+ public String getText() {
+ return _text;
+ }
+
+ public void setText(final String text) {
+ _text = text;
+ }
+
+ public Bean getReference() {
+ return _reference;
+ }
+
+ public void setReference(final Bean reference) {
+ _reference = reference;
+ }
+}
Index: /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Test1342.java
===================================================================
--- /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Test1342.java (Revision 0)
+++ /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/Test1342.java (Revision 0)
@@ -0,0 +1,262 @@
+package xml.c1342;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import junit.framework.TestCase;
+
+import net.sf.cglib.proxy.Factory;
+
+import org.exolab.castor.mapping.Mapping;
+import org.exolab.castor.util.Configuration;
+import org.exolab.castor.util.LocalConfiguration;
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+
+public final class Test1342 extends TestCase {
+ private static final String MAPPING_FILE = "mapping.xml";
+
+ public Test1342() {
+ super();
+ }
+
+ /**
+ * Test unmarshalling of simple bean without proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testUnmarshalSimpleBean() throws Exception {
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ Unmarshaller unmarshaller = new Unmarshaller(Bean.class);
+ unmarshaller.setMapping(mapping);
+
+ String input
+ = "\n"
+ + ""
+ + "element of 999"
+ + "";
+
+ Bean bean = (Bean) unmarshaller.unmarshal(new StringReader(input));
+ assertNotNull(bean);
+ assertEquals(999, bean.getAttribute().intValue());
+ assertEquals("element of 999", bean.getElement());
+ assertNull(bean.getReference());
+ }
+
+ /**
+ * Test unmarshalling of bean refering to another one without proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testUnmarshalReferingBean() throws Exception {
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ Unmarshaller unmarshaller = new Unmarshaller(Bean.class);
+ unmarshaller.setMapping(mapping);
+
+ String input
+ = "\n"
+ + ""
+ + "element of 100"
+ + ""
+ + "element of 999"
+ + ""
+ + "";
+
+ Bean referer = (Bean) unmarshaller.unmarshal(new StringReader(input));
+ assertNotNull(referer);
+ assertEquals(100, referer.getAttribute().intValue());
+ assertEquals("element of 100", referer.getElement());
+ assertNotNull(referer.getReference());
+
+ Bean refered = referer.getReference();
+ assertNotNull(refered);
+ assertEquals(999, refered.getAttribute().intValue());
+ assertEquals("element of 999", refered.getElement());
+ assertNull(refered.getReference());
+ }
+
+ /**
+ * Test marshalling of simple bean without proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testMarshalSimpleBean() throws Exception {
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ StringWriter out = new StringWriter();
+ Marshaller marshaller = new Marshaller(out);
+ marshaller.setMapping(mapping);
+
+ Bean bean = new Bean();
+ bean.setAttribute(new Integer(999));
+ bean.setElement("element of 999");
+ bean.setReference(null);
+
+ marshaller.marshal(bean);
+
+ String output = out.toString();
+
+ String expected
+ = "\n"
+ + ""
+ + "element of 999"
+ + "";
+
+ assertEquals(expected, output);
+ }
+
+ /**
+ * Test marshalling of bean refering to another one without proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testMarshalReferingBean() throws Exception {
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ StringWriter out = new StringWriter();
+ Marshaller marshaller = new Marshaller(out);
+ marshaller.setMapping(mapping);
+
+ Bean refered = new Bean();
+ refered.setAttribute(new Integer(999));
+ refered.setElement("element of 999");
+ refered.setReference(null);
+
+ Bean referer = new Bean();
+ referer.setAttribute(new Integer(100));
+ referer.setElement("element of 100");
+ referer.setReference(refered);
+
+ marshaller.marshal(referer);
+
+ String output = out.toString();
+
+ String expected
+ = "\n"
+ + ""
+ + "element of 100"
+ + ""
+ + "element of 999"
+ + ""
+ + "";
+
+ assertEquals(expected, output);
+ }
+
+ /**
+ * Test marshalling of simple bean with proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testMarshalSimpleBeanProxy() throws Exception {
+ Configuration config = LocalConfiguration.getInstance();
+ config.getProperties().setProperty(
+ Configuration.Property.ProxyInterface, "net.sf.cglib.proxy.Factory");
+
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ StringWriter out = new StringWriter();
+ Marshaller marshaller = new Marshaller(out);
+ marshaller.setMapping(mapping);
+
+ Bean bean = new Bean();
+ bean.setAttribute(new Integer(999));
+ bean.setElement("element of 999");
+ bean.setReference(null);
+
+ Bean proxy = (Bean) Proxy.newInstance(bean);
+
+ assertNotNull(proxy);
+ assertEquals(Bean.class, proxy.getClass().getSuperclass());
+ assertEquals(1, proxy.getClass().getInterfaces().length);
+ assertEquals(Factory.class, proxy.getClass().getInterfaces()[0]);
+
+ assertEquals(999, proxy.getAttribute().intValue());
+ assertEquals("element of 999", proxy.getElement());
+ assertNull(proxy.getReference());
+
+ marshaller.marshal(proxy);
+
+ String output = out.toString();
+
+ String expected
+ = "\n"
+ + ""
+ + "element of 999"
+ + "";
+
+ assertEquals(expected, output);
+ }
+
+ /**
+ * Test marshalling of bean refering to another one with proxy.
+ *
+ * @throws Exception For any exception thrown.
+ */
+ public void testMarshalReferingBeanProxy() throws Exception {
+ Configuration config = LocalConfiguration.getInstance();
+ config.getProperties().setProperty(
+ Configuration.Property.ProxyInterface, "net.sf.cglib.proxy.Factory");
+
+ Mapping mapping = new Mapping();
+ mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+ StringWriter out = new StringWriter();
+ Marshaller marshaller = new Marshaller(out);
+ marshaller.setMapping(mapping);
+
+ Bean refered = new Bean();
+ refered.setAttribute(new Integer(999));
+ refered.setElement("element of 999");
+ refered.setReference(null);
+
+ Bean referedProxy = (Bean) Proxy.newInstance(refered);
+
+ assertNotNull(referedProxy);
+ assertEquals(Bean.class, referedProxy.getClass().getSuperclass());
+ assertEquals(1, referedProxy.getClass().getInterfaces().length);
+ assertEquals(Factory.class, referedProxy.getClass().getInterfaces()[0]);
+
+ assertEquals(999, referedProxy.getAttribute().intValue());
+ assertEquals("element of 999", referedProxy.getElement());
+ assertNull(referedProxy.getReference());
+
+ Bean referer = new Bean();
+ referer.setAttribute(new Integer(100));
+ referer.setElement("element of 100");
+ referer.setReference(referedProxy);
+
+ Bean refererProxy = (Bean) Proxy.newInstance(referer);
+
+ assertNotNull(refererProxy);
+ assertEquals(Bean.class, refererProxy.getClass().getSuperclass());
+ assertEquals(1, refererProxy.getClass().getInterfaces().length);
+ assertEquals(Factory.class, refererProxy.getClass().getInterfaces()[0]);
+
+ assertEquals(100, refererProxy.getAttribute().intValue());
+ assertEquals("element of 100", refererProxy.getElement());
+ assertNotNull(refererProxy.getReference());
+
+ marshaller.marshal(refererProxy);
+
+ String output = out.toString();
+
+ String expected
+ = "\n"
+ + ""
+ + "element of 100"
+ + ""
+ + "element of 999"
+ + ""
+ + "";
+
+ assertEquals(expected, output);
+ }
+}
Index: /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/mapping.xml
===================================================================
--- /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/mapping.xml (Revision 0)
+++ /home/ralf/Workspace/castor-2/src/bugs/xml/c1342/mapping.xml (Revision 0)
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/xml/Marshaller.java
===================================================================
--- /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/xml/Marshaller.java (Revision 7075)
+++ /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/xml/Marshaller.java (Arbeitskopie)
@@ -95,7 +95,6 @@
import java.util.List;
import java.util.Stack;
-
/**
* A Marshaller that serializes Java Object's to XML
*
@@ -281,10 +280,15 @@
/**
* The validation flag
- **/
+ */
private boolean _validate = false;
+ /** Shell the objects to be marshalled be searched if they implement a proxy interface? */
+ private boolean _proxySearch = false;
+ /** Full classname of the proxy interface to search for. */
+ private String _proxyInterface = null;
+
/**
* Creates a new Marshaller with the given DocumentHandler.
*
@@ -408,7 +412,10 @@
if ("false".equalsIgnoreCase(val) || "off".equalsIgnoreCase(val)) {
_saveMapKeys = false;
}
-
+
+ //-- proxy interface to search for if defined
+ _proxyInterface = _config.getProperty(Configuration.Property.ProxyInterface, null);
+ _proxySearch = (_proxyInterface != null) && !"".equals(_proxyInterface.trim());
} //-- initialize();
/**
@@ -912,10 +919,20 @@
if (!isNil) {
_class = object.getClass();
+
+ if (_proxySearch) {
+ boolean isProxy = false;
+
+ Class[] interfaces = _class.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (_proxyInterface.equals(interfaces[i].getName())) { isProxy = true; }
+ }
+
+ if (isProxy) { _class = _class.getSuperclass(); }
+ }
+ } else {
+ _class = ((NilObject) object).getClassDescriptor().getJavaClass();
}
- else {
- _class = ((NilObject)object).getClassDescriptor().getJavaClass();
- }
boolean byteArray = false;
if (_class.isArray())
@@ -952,8 +969,7 @@
if (object instanceof NilObject) {
classDesc = ((NilObject)object).getClassDescriptor();
- }
- else if (_class == descriptor.getFieldType()) {
+ } else if (_class == descriptor.getFieldType()) {
classDesc = (XMLClassDescriptor)descriptor.getClassDescriptor();
}
Index: /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/util/Configuration.java
===================================================================
--- /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/util/Configuration.java (Revision 7075)
+++ /home/ralf/Workspace/castor-2/src/main/java/org/exolab/castor/util/Configuration.java (Arbeitskopie)
@@ -298,6 +298,17 @@
*/
public static final String LenientIdValidation = "org.exolab.castor.xml.lenient.id.validation";
+ /**
+ * Property specifying whether or not to search for an proxy interface at marshalling.
+ * If property is not empty it the objects to be marshalled will be searched if they
+ * implement the given interface name. If the interface is implemented the marshaller
+ * will search for a descriptor of the superclass instead of the class itself.
+ *
+ * org.exolab.castor.xml.proxyInterface
+ *
+ * @since 1.2.2
+ */
+ public static final String ProxyInterface = "org.exolab.castor.xml.proxyInterface";
} //-- class: Property
Index: /home/ralf/Workspace/castor-2/src/main/resources/org/exolab/castor/castor.properties
===================================================================
--- /home/ralf/Workspace/castor-2/src/main/resources/org/exolab/castor/castor.properties (Revision 7075)
+++ /home/ralf/Workspace/castor-2/src/main/resources/org/exolab/castor/castor.properties (Arbeitskopie)
@@ -106,6 +106,13 @@
#
org.exolab.castor.debug=false
+# Property specifying whether or not to search for an proxy interface at marshalling.
+# If property is not empty it the objects to be marshalled will be searched if they
+# implement the given interface name. If the interface is implemented the marshaller
+# will search for a descriptor of the superclass instead of the class itself.
+#
+#org.exolab.castor.xml.proxyInterface=net.sf.cglib.proxy.Factory
+
# List of collection handlers for Java 1.1 and Java 1.2 run-times:
#
org.exolab.castor.mapping.collections=\