svn commit: r901192 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/model/dataformat/ components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/ components/camel-jaxb/src/test/java/org/apache/camel/example/ components/camel-jaxb/...

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r901192 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/model/dataformat/ components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/ components/camel-jaxb/src/test/java/org/apache/camel/example/ components/camel-jaxb/...

davsclaus-2
Author: davsclaus
Date: Wed Jan 20 13:32:34 2010
New Revision: 901192

URL: http://svn.apache.org/viewvc?rev=901192&view=rev
Log:
CAMEL-2391: JAXB data format not supports partial (not marshal/unmarshal the entire graph). Applied patch with much thanks to Lukasz Dywicik.

Added:
    camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java   (with props)
    camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java   (with props)
    camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml   (with props)
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
    camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
    camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/dataformat/JaxbDataFormat.java Wed Jan 20 13:32:34 2010
@@ -20,6 +20,7 @@
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.namespace.QName;
 
 import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.spi.DataFormat;
@@ -44,6 +45,12 @@
     @XmlAttribute(required = false)
     private String encoding;
 
+    // Partial encoding
+    @XmlAttribute(required = false)
+    private String partClass;
+    @XmlAttribute(required = false)
+    private String partNamespace;
+
     public JaxbDataFormat() {
         super("jaxb");
     }
@@ -84,7 +91,19 @@
     public void setFilterNonXmlChars(Boolean filterNonXmlChars) {
         this.filterNonXmlChars = filterNonXmlChars;
     }
-    
+
+    public String getPartClass() {
+        return partClass;
+    }
+
+    public void setPartClass(String partClass) {
+        this.partClass = partClass;
+    }
+
+    public void setPartNamespace(String partNamespace) {
+        this.partNamespace = partNamespace;
+    }
+
     @Override
     protected void configureDataFormat(DataFormat dataFormat) {
         Boolean answer = ObjectHelper.toBoolean(getPrettyPrint());
@@ -104,7 +123,13 @@
             setProperty(dataFormat, "filterNonXmlChars", Boolean.TRUE);
         } else { // the default value is false
             setProperty(dataFormat, "filterNonXmlChars", Boolean.FALSE);
-        }        
+        }
+        if (partClass != null) {
+            setProperty(dataFormat, "partClass", partClass);
+        }
+        if (partNamespace != null) {
+            setProperty(dataFormat, "partNamespace", QName.valueOf(partNamespace));
+        }
         if (encoding != null) {
             setProperty(dataFormat, "encoding", encoding);
         }

Modified: camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java (original)
+++ camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java Wed Jan 20 13:32:34 2010
@@ -20,14 +20,20 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.stream.FactoryConfigurationError;
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.converter.IOConverter;
@@ -48,6 +54,10 @@
     private boolean ignoreJAXBElement = true;
     private boolean filterNonXmlChars;
     private String encoding;
+    // partial support
+    private QName partNamespace;
+    private String partClass;
+    private Class partialClass;
 
     public JaxbDataFormat() {
     }
@@ -85,26 +95,52 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
     void marshal(Exchange exchange, Object graph, OutputStream stream, Marshaller marshaller)
         throws XMLStreamException, JAXBException {
+
+        Object e = graph;
+        if (getPartClass() != null && getPartNamespace() != null) {
+            e = new JAXBElement(getPartNamespace(), getPartialClass(exchange), graph);
+        }
+
         if (needFiltering(exchange)) {
-            XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(stream);
-            FilteringXmlStreamWriter filteringWriter = new FilteringXmlStreamWriter(writer);
-            marshaller.marshal(graph, filteringWriter);
+            marshaller.marshal(e, createFilteringWriter(stream));
         } else {
-            marshaller.marshal(graph, stream);
+            marshaller.marshal(e, stream);
         }
     }
-    
+
+    private FilteringXmlStreamWriter createFilteringWriter(OutputStream stream)
+        throws XMLStreamException, FactoryConfigurationError {
+        XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(stream);
+        FilteringXmlStreamWriter filteringWriter = new FilteringXmlStreamWriter(writer);
+        return filteringWriter;
+    }
+
+    @SuppressWarnings("unchecked")
     public Object unmarshal(Exchange exchange, InputStream stream) throws IOException {
         try {
             // must create a new instance of unmarshaller as its not thread safe
             Object answer;
             Unmarshaller unmarshaller = getContext().createUnmarshaller();
-            if (needFiltering(exchange)) {
-                answer = unmarshaller.unmarshal(new NonXmlFilterReader(new InputStreamReader(stream, IOConverter.getCharsetName(exchange))));
-            } else  {
-                answer = unmarshaller.unmarshal(stream);
+
+            if (getPartClass() != null) {
+                // partial unmarshalling
+                Source source;
+                if (needFiltering(exchange)) {
+                    source = new StreamSource(createNonXmlFilterReader(exchange, stream));
+                } else {
+                    source = new StreamSource(stream);
+                }
+                answer = unmarshaller.unmarshal(source, getPartialClass(exchange));
+            } else {
+                if (needFiltering(exchange)) {
+                    NonXmlFilterReader reader = createNonXmlFilterReader(exchange, stream);
+                    answer = unmarshaller.unmarshal(reader);
+                } else  {
+                    answer = unmarshaller.unmarshal(stream);
+                }
             }
 
             if (answer instanceof JAXBElement && isIgnoreJAXBElement()) {
@@ -115,12 +151,23 @@
             throw IOHelper.createIOException(e);
         }
     }
-    
+
+    private NonXmlFilterReader createNonXmlFilterReader(Exchange exchange, InputStream stream) throws UnsupportedEncodingException {
+        return new NonXmlFilterReader(new InputStreamReader(stream, IOConverter.getCharsetName(exchange)));
+    }
+
     protected boolean needFiltering(Exchange exchange) {
         // exchange property takes precedence over data format property
         return exchange == null ? filterNonXmlChars : exchange.getProperty(Exchange.FILTER_NON_XML_CHARS, filterNonXmlChars, Boolean.class);
     }
 
+    private synchronized Class getPartialClass(Exchange exchange) {
+        if (partialClass == null) {
+            partialClass = exchange.getContext().getClassResolver().resolveClass(getPartClass());
+        }
+        return partialClass;
+    }
+
     // Properties
     // -------------------------------------------------------------------------
     public boolean isIgnoreJAXBElement() {        
@@ -174,6 +221,22 @@
         this.encoding = encoding;
     }
 
+    public final QName getPartNamespace() {
+        return partNamespace;
+    }
+
+    public final void setPartNamespace(QName partNamespace) {
+        this.partNamespace = partNamespace;
+    }
+
+    public final String getPartClass() {
+        return partClass;
+    }
+
+    public final void setPartClass(String partClass) {
+        this.partClass = partClass;
+    }
+
     protected JAXBContext createContext() throws JAXBException {
         if (contextPath != null) {
             return JAXBContext.newInstance(contextPath);

Added: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java?rev=901192&view=auto
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java (added)
+++ camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java Wed Jan 20 13:32:34 2010
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Partial element without XmlRootElement annotation for partial testing.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Partial")
+public class Partial {
+
+    @XmlAttribute
+    private String name;
+
+    @XmlElement
+    private String location;
+
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(String name) {
+        this.name = name;
+    }
+
+    public final String getLocation() {
+        return location;
+    }
+
+    public final void setLocation(String location) {
+        this.location = location;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Partial partial = (Partial) o;
+
+        if (location != null ? !location.equals(partial.location) : partial.location != null) {
+            return false;
+        }
+        if (name != null ? !name.equals(partial.name) : partial.name != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (location != null ? location.hashCode() : 0);
+        return result;
+    }
+}

Propchange: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/Partial.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java?rev=901192&view=auto
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java (added)
+++ camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java Wed Jan 20 13:32:34 2010
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.language.MethodCallExpression;
+import org.apache.camel.model.language.XPathExpression;
+import org.apache.camel.test.junit4.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Partial operations test.
+ */
+public class SpringDataFormatPartialTest extends CamelSpringTestSupport {
+
+    @Test
+    public void testPartialMarshal() throws Exception {
+        PurchaseOrder bean = new PurchaseOrder();
+        bean.setName("Beer");
+        bean.setAmount(23);
+        bean.setPrice(2.5);
+
+        MockEndpoint mock = resolveMandatoryEndpoint("mock:marshal", MockEndpoint.class);
+        mock.expectedMessageCount(1);
+
+        XPathExpression xpath = new XPathExpression("count(//*[namespace-uri() = 'http://example.camel.org/apache' and local-name() = 'po']) = 1");
+        xpath.setResultType(Boolean.class);
+        mock.allMessages().body().matches(xpath);
+
+        template.sendBody("direct:marshal", bean);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testPartialUnmarshal() throws Exception {
+        MockEndpoint mock = resolveMandatoryEndpoint("mock:unmarshal", MockEndpoint.class);
+        mock.expectedMessageCount(1);
+
+        Partial partial = new Partial();
+        partial.setName("mock");
+        partial.setLocation("org.apache.camel");
+        mock.expectedBodyReceived().constant(partial);
+
+        String xml = "<Partial name=\"mock\"><location>org.apache.camel</location></Partial>";
+        template.sendBody("direct:unmarshal", xml);
+
+        mock.assertIsSatisfied();
+    }
+
+    protected ClassPathXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/example/springDataFormatPartial.xml");
+    }
+
+}
\ No newline at end of file

Propchange: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/SpringDataFormatPartialTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index?rev=901192&r1=901191&r2=901192&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index (original)
+++ camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/jaxb.index Wed Jan 20 13:32:34 2010
@@ -14,4 +14,5 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 ## ------------------------------------------------------------------------
-PurchaseOrder
\ No newline at end of file
+PurchaseOrder
+Partial
\ No newline at end of file

Added: camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml?rev=901192&view=auto
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml (added)
+++ camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml Wed Jan 20 13:32:34 2010
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+    <!-- START SNIPPET: example -->
+    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+        <route>
+            <from uri="direct:marshal"/>
+            <marshal>
+                <jaxb prettyPrint="false" contextPath="org.apache.camel.example"
+                    partClass="org.apache.camel.example.PurchaseOrder"
+                    partNamespace="{http://example.camel.org/apache}po" />
+            </marshal>
+            <to uri="mock:marshal"/>
+        </route>
+        <route>
+            <from uri="direct:unmarshal"/>
+            <unmarshal>
+                <jaxb prettyPrint="false" contextPath="org.apache.camel.example"
+                    partClass="org.apache.camel.example.Partial" />
+            </unmarshal>
+            <to uri="mock:unmarshal"/>
+        </route>
+    </camelContext>
+    <!-- END SNIPPET: example -->
+
+</beans>

Propchange: camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: camel/trunk/components/camel-jaxb/src/test/resources/org/apache/camel/example/springDataFormatPartial.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml