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