Author: davsclaus Date: Fri Jul 9 12:29:48 2010 New Revision: 962504 URL: http://svn.apache.org/viewvc?rev=962504&view=rev Log: CAMEL-2915: Applied patch with thanks to Mark Proctor.
Modified: camel/trunk/components/camel-xstream/src/main/java/org/apache/camel/dataformat/xstream/AbstractXStreamWrapper.java camel/trunk/components/camel-xstream/src/test/java/org/apache/camel/dataformat/xstream/XStreamConfigurationTest.java Modified: camel/trunk/components/camel-xstream/src/main/java/org/apache/camel/dataformat/xstream/AbstractXStreamWrapper.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-xstream/src/main/java/org/apache/camel/dataformat/xstream/AbstractXStreamWrapper.java?rev=962504&r1=962503&r2=962504&view=diff ============================================================================== --- camel/trunk/components/camel-xstream/src/main/java/org/apache/camel/dataformat/xstream/AbstractXStreamWrapper.java (original) +++ camel/trunk/components/camel-xstream/src/main/java/org/apache/camel/dataformat/xstream/AbstractXStreamWrapper.java Fri Jul 9 12:29:48 2010 @@ -18,6 +18,8 @@ package org.apache.camel.dataformat.xstr import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -33,6 +35,7 @@ import org.apache.camel.Exchange; import org.apache.camel.converter.jaxp.StaxConverter; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.DataFormat; +import org.apache.camel.util.ObjectHelper; /** * An abstract class which implement <a href="http://camel.apache.org/data-format.html">data format</a> @@ -40,7 +43,6 @@ import org.apache.camel.spi.DataFormat; * * @version $Revision$ */ - public abstract class AbstractXStreamWrapper implements DataFormat { private XStream xstream; @@ -86,16 +88,39 @@ public abstract class AbstractXStreamWra } if (this.converters != null) { - for (String converter : this.converters) { - xstream.registerConverter(resolver.resolveMandatoryClass(converter, Converter.class).newInstance()); + for (String name : this.converters) { + Class<Converter> converterClass = resolver.resolveMandatoryClass(name, Converter.class); + Converter converter; + + Constructor con = null; + try { + con = converterClass.getDeclaredConstructor(new Class[] {XStream.class}); + } catch (Exception e) { + //swallow as we null check in a moment. + } + if (con != null) { + converter = (Converter) con.newInstance(xstream); + } else { + converter = converterClass.newInstance(); + try { + Method method = converterClass.getMethod("setXStream", new Class[] {XStream.class}); + if (method != null) { + ObjectHelper.invokeMethod(method, converter, xstream); + } + } catch (Throwable e) { + // swallow, as it just means the user never add an XStream setter, which is optional + } + } + + xstream.registerConverter(converter); } } } catch (Exception e) { - throw new RuntimeException("Unable to build Xstream instance", e); + throw new RuntimeException("Unable to build XStream instance", e); } return xstream; - } + } public StaxConverter getStaxConverter() { if (staxConverter == null) { Modified: camel/trunk/components/camel-xstream/src/test/java/org/apache/camel/dataformat/xstream/XStreamConfigurationTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-xstream/src/test/java/org/apache/camel/dataformat/xstream/XStreamConfigurationTest.java?rev=962504&r1=962503&r2=962504&view=diff ============================================================================== --- camel/trunk/components/camel-xstream/src/test/java/org/apache/camel/dataformat/xstream/XStreamConfigurationTest.java (original) +++ camel/trunk/components/camel-xstream/src/test/java/org/apache/camel/dataformat/xstream/XStreamConfigurationTest.java Fri Jul 9 12:29:48 2010 @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; @@ -38,6 +39,21 @@ import org.junit.Test; */ public class XStreamConfigurationTest extends CamelTestSupport { + private static volatile boolean constructorInjected; + private static volatile boolean methodInjected; + + @Override + public void setUp() throws Exception { + super.setUp(); + constructorInjected = false; + methodInjected = false; + } + + public void testXStreamInjection() { + assertTrue(constructorInjected); + assertTrue(methodInjected); + } + @Test public void testCustomMarshalDomainObject() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); @@ -51,12 +67,11 @@ public class XStreamConfigurationTest ex list.add(11.5); list.add(97.5); - String ordereString = "<?xml version='1.0' encoding='UTF-8'?>" - + "<purchase-order name=\"Tiger\" price=\"99.95\" amount=\"1.0\"/>"; + String ordereString = "<?xml version='1.0' encoding='UTF-8'?>" + "<purchase-order name=\"Tiger\" price=\"99.95\" amount=\"1.0\"/>"; mock.expectedBodiesReceived(new Object[] {ordereString, order}); - template.sendBody("direct:marshal", order); - template.sendBody("direct:unmarshal", ordereString); + this.template.sendBody("direct:marshal", order); + this.template.sendBody("direct:unmarshal", ordereString); mock.assertIsSatisfied(); } @@ -72,14 +87,12 @@ public class XStreamConfigurationTest ex list.add(97.5); history.setHistory(list); - String ordereString = "<?xml version='1.0' encoding='UTF-8'?>" - + "<org.apache.camel.dataformat.xstream.PurchaseHistory>" - + "<double>11.5</double><double>97.5</double>" - + "</org.apache.camel.dataformat.xstream.PurchaseHistory>"; + String ordereString = "<?xml version='1.0' encoding='UTF-8'?>" + "<org.apache.camel.dataformat.xstream.PurchaseHistory>" + + "<double>11.5</double><double>97.5</double>" + "</org.apache.camel.dataformat.xstream.PurchaseHistory>"; mock.expectedBodiesReceived(new Object[] {ordereString, history}); - template.sendBody("direct:marshal", history); - template.sendBody("direct:unmarshal", ordereString); + this.template.sendBody("direct:marshal", history); + this.template.sendBody("direct:unmarshal", ordereString); mock.assertIsSatisfied(); } @@ -100,14 +113,16 @@ public class XStreamConfigurationTest ex String ordereString = "{\"purchase-order\":{\"@name\":\"Tiger\",\"@price\":\"99.95\",\"@amount\":\"1.0\"}}"; mock.expectedBodiesReceived(new Object[] {ordereString, order}); - template.sendBody("direct:marshal-json", order); - template.sendBody("direct:unmarshal-json", ordereString); + this.template.sendBody("direct:marshal-json", order); + this.template.sendBody("direct:unmarshal-json", ordereString); mock.assertIsSatisfied(); } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { + @Override public void configure() throws Exception { XStreamDataFormat xstreamDefinition = new XStreamDataFormat(); Map<String, String> aliases = new HashMap<String, String>(); @@ -116,6 +131,9 @@ public class XStreamConfigurationTest ex List<String> converters = new ArrayList<String>(); converters.add(PurchaseOrderConverter.class.getName()); + converters.add(CheckMethodInjection.class.getName()); + converters.add(CheckConstructorInjection.class.getName()); + xstreamDefinition.setConverters(converters); Map<String, String[]> implicits = new HashMap<String, String[]>(); @@ -156,9 +174,55 @@ public class XStreamConfigurationTest ex public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) { - writer.addAttribute("name", ((PurchaseOrder)object).getName()); + writer.addAttribute("name", ((PurchaseOrder) object).getName()); writer.addAttribute("price", Double.toString(((PurchaseOrder) object).getPrice())); writer.addAttribute("amount", Double.toString(((PurchaseOrder) object).getAmount())); } } + + public static class CheckConstructorInjection implements Converter { + public CheckConstructorInjection(XStream xstream) { + if (xstream != null) { + constructorInjected = true; + } else { + throw new RuntimeException("XStream should not be null"); + } + } + + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + } + + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + return null; + } + + public boolean canConvert(Class type) { + return false; + } + } + + public static class CheckMethodInjection implements Converter { + public CheckMethodInjection() { + + } + + public void setXStream(XStream xstream) { + if (xstream != null) { + methodInjected = true; + } else { + throw new RuntimeException("XStream should not be null"); + } + } + + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + } + + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + return null; + } + + public boolean canConvert(Class type) { + return false; + } + } } \ No newline at end of file