CAMEL-11332: Create a new camel-thrift data format
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/362a8943 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/362a8943 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/362a8943 Branch: refs/heads/master Commit: 362a8943f9a12ab4cf5b99dfebf4ac51a777f58f Parents: 64e7388 Author: Dmitry Volodin <dmvo...@gmail.com> Authored: Mon May 29 11:42:37 2017 +0300 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Jun 2 12:58:50 2017 +0200 ---------------------------------------------------------------------- .../apache/camel/builder/DataFormatClause.java | 29 + .../apache/camel/model/MarshalDefinition.java | 2 + .../apache/camel/model/UnmarshalDefinition.java | 2 + .../model/dataformat/DataFormatsDefinition.java | 1 + .../model/dataformat/ThriftDataFormat.java | 107 +++ .../DataFormatTransformerDefinition.java | 2 + .../apache/camel/model/dataformat/jaxb.index | 1 + .../src/main/docs/protobuf-dataformat.adoc | 22 +- .../ProtobufMarshalAndUnmarshalSpringTest.java | 60 +- .../dataformat/protobuf/springDataFormat.xml | 21 +- components/camel-thrift/ReadMe.md | 30 + components/camel-thrift/pom.xml | 92 +++ .../src/main/docs/thrift-dataformat.adoc | 156 ++++ .../dataformat/thrift/ThriftDataFormat.java | 204 +++++ .../src/main/resources/META-INF/LICENSE.txt | 203 +++++ .../src/main/resources/META-INF/NOTICE.txt | 14 + .../services/org/apache/camel/dataformat/thrift | 18 + .../src/test/java/META-INF/MANIFEST.MF | 3 + .../ThriftMarshalAndUnmarshalJsonTest.java | 106 +++ .../ThriftMarshalAndUnmarshalSpringTest.java | 95 +++ .../thrift/ThriftMarshalAndUnmarshalTest.java | 108 +++ .../dataformat/thrift/generated/Operation.java | 55 ++ .../camel/dataformat/thrift/generated/Work.java | 735 +++++++++++++++++++ .../src/test/resources/log4j2.properties | 28 + .../dataformat/thrift/springDataFormat.xml | 57 ++ .../camel-thrift/src/test/thrift/readme.txt | 5 + .../src/test/thrift/tutorial-dataformat.thrift | 84 +++ components/pom.xml | 1 + .../src/main/resources/config.properties | 0 .../features/src/main/resources/features.xml | 6 + .../camel-thrift-starter/pom.xml | 61 ++ .../ThriftDataFormatAutoConfiguration.java | 129 ++++ .../ThriftDataFormatConfiguration.java | 76 ++ .../src/main/resources/META-INF/LICENSE.txt | 203 +++++ .../src/main/resources/META-INF/NOTICE.txt | 11 + .../main/resources/META-INF/spring.factories | 19 + .../src/main/resources/META-INF/spring.provides | 17 + .../spring-boot/components-starter/pom.xml | 1 + 38 files changed, 2734 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java index 0b18e91..ec719b8 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java +++ b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java @@ -52,6 +52,7 @@ import org.apache.camel.model.dataformat.SoapJaxbDataFormat; import org.apache.camel.model.dataformat.StringDataFormat; import org.apache.camel.model.dataformat.SyslogDataFormat; import org.apache.camel.model.dataformat.TarFileDataFormat; +import org.apache.camel.model.dataformat.ThriftDataFormat; import org.apache.camel.model.dataformat.TidyMarkupDataFormat; import org.apache.camel.model.dataformat.XMLBeansDataFormat; import org.apache.camel.model.dataformat.XMLSecurityDataFormat; @@ -830,6 +831,34 @@ public class DataFormatClause<T extends ProcessorDefinition<?>> { public T syslog() { return dataFormat(new SyslogDataFormat()); } + + /** + * Uses the Thrift data format + */ + public T thrift() { + return dataFormat(new ThriftDataFormat()); + } + + public T thrift(Object defaultInstance) { + ThriftDataFormat dataFormat = new ThriftDataFormat(); + dataFormat.setDefaultInstance(defaultInstance); + return dataFormat(dataFormat); + } + + public T thrift(Object defaultInstance, String contentTypeFormat) { + ThriftDataFormat dataFormat = new ThriftDataFormat(); + dataFormat.setDefaultInstance(defaultInstance); + dataFormat.setContentTypeFormat(contentTypeFormat); + return dataFormat(dataFormat); + } + + public T thrift(String instanceClassName) { + return dataFormat(new ThriftDataFormat(instanceClassName)); + } + + public T thrift(String instanceClassName, String contentTypeFormat) { + return dataFormat(new ThriftDataFormat(instanceClassName, contentTypeFormat)); + } /** * Return WellFormed HTML (an XML Document) either http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/model/MarshalDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/MarshalDefinition.java b/camel-core/src/main/java/org/apache/camel/model/MarshalDefinition.java index e149b7e..a2bddfc 100644 --- a/camel-core/src/main/java/org/apache/camel/model/MarshalDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/MarshalDefinition.java @@ -49,6 +49,7 @@ import org.apache.camel.model.dataformat.SoapJaxbDataFormat; import org.apache.camel.model.dataformat.StringDataFormat; import org.apache.camel.model.dataformat.SyslogDataFormat; import org.apache.camel.model.dataformat.TarFileDataFormat; +import org.apache.camel.model.dataformat.ThriftDataFormat; import org.apache.camel.model.dataformat.TidyMarkupDataFormat; import org.apache.camel.model.dataformat.UniVocityCsvDataFormat; import org.apache.camel.model.dataformat.UniVocityFixedWidthDataFormat; @@ -105,6 +106,7 @@ public class MarshalDefinition extends NoOutputDefinition<MarshalDefinition> { @XmlElement(required = false, name = "string", type = StringDataFormat.class), @XmlElement(required = false, name = "syslog", type = SyslogDataFormat.class), @XmlElement(required = false, name = "tarfile", type = TarFileDataFormat.class), + @XmlElement(required = false, name = "thrift", type = ThriftDataFormat.class), @XmlElement(required = false, name = "tidyMarkup", type = TidyMarkupDataFormat.class), @XmlElement(required = false, name = "univocity-csv", type = UniVocityCsvDataFormat.class), @XmlElement(required = false, name = "univocity-fixed", type = UniVocityFixedWidthDataFormat.class), http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/model/UnmarshalDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/UnmarshalDefinition.java b/camel-core/src/main/java/org/apache/camel/model/UnmarshalDefinition.java index 34756f1..cd97c61 100644 --- a/camel-core/src/main/java/org/apache/camel/model/UnmarshalDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/UnmarshalDefinition.java @@ -49,6 +49,7 @@ import org.apache.camel.model.dataformat.SoapJaxbDataFormat; import org.apache.camel.model.dataformat.StringDataFormat; import org.apache.camel.model.dataformat.SyslogDataFormat; import org.apache.camel.model.dataformat.TarFileDataFormat; +import org.apache.camel.model.dataformat.ThriftDataFormat; import org.apache.camel.model.dataformat.TidyMarkupDataFormat; import org.apache.camel.model.dataformat.UniVocityCsvDataFormat; import org.apache.camel.model.dataformat.UniVocityFixedWidthDataFormat; @@ -105,6 +106,7 @@ public class UnmarshalDefinition extends NoOutputDefinition<UnmarshalDefinition> @XmlElement(required = false, name = "string", type = StringDataFormat.class), @XmlElement(required = false, name = "syslog", type = SyslogDataFormat.class), @XmlElement(required = false, name = "tarfile", type = TarFileDataFormat.class), + @XmlElement(required = false, name = "thrift", type = ThriftDataFormat.class), @XmlElement(required = false, name = "tidyMarkup", type = TidyMarkupDataFormat.class), @XmlElement(required = false, name = "univocity-csv", type = UniVocityCsvDataFormat.class), @XmlElement(required = false, name = "univocity-fixed", type = UniVocityFixedWidthDataFormat.class), http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java index 901130e..43133b0 100644 --- a/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java @@ -68,6 +68,7 @@ public class DataFormatsDefinition { @XmlElement(required = false, name = "string", type = StringDataFormat.class), @XmlElement(required = false, name = "syslog", type = SyslogDataFormat.class), @XmlElement(required = false, name = "tarfile", type = TarFileDataFormat.class), + @XmlElement(required = false, name = "thrift", type = ThriftDataFormat.class), @XmlElement(required = false, name = "tidyMarkup", type = TidyMarkupDataFormat.class), @XmlElement(required = false, name = "univocity-csv", type = UniVocityCsvDataFormat.class), @XmlElement(required = false, name = "univocity-fixed", type = UniVocityFixedWidthDataFormat.class), http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/model/dataformat/ThriftDataFormat.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/ThriftDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/ThriftDataFormat.java new file mode 100644 index 0000000..242ca25 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/ThriftDataFormat.java @@ -0,0 +1,107 @@ +/** + * 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.model.dataformat; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import org.apache.camel.CamelContext; +import org.apache.camel.model.DataFormatDefinition; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.Metadata; + +/** + * Apache Thrift data format + * + * @version + */ +@Metadata(firstVersion = "2.20.0", label = "dataformat,transformation", title = "Thrift") +@XmlRootElement(name = "thrift") +@XmlAccessorType(XmlAccessType.FIELD) +public class ThriftDataFormat extends DataFormatDefinition { + @XmlAttribute + private String instanceClass; + @XmlAttribute @Metadata(enums = "binary,json,sjson", defaultValue = "binary") + private String contentTypeFormat; + @XmlTransient + private Object defaultInstance; + + public ThriftDataFormat() { + super("thrift"); + } + + public ThriftDataFormat(String instanceClass) { + this(); + setInstanceClass(instanceClass); + } + + public ThriftDataFormat(String instanceClass, String contentTypeFormat) { + this(); + setInstanceClass(instanceClass); + setContentTypeFormat(contentTypeFormat); + } + + public String getInstanceClass() { + return instanceClass; + } + + /** + * Name of class to use when unarmshalling + */ + public void setInstanceClass(String instanceClass) { + this.instanceClass = instanceClass; + } + + /** + * Defines a content type format in which thrift message will be + * serialized/deserialized from(to) the Java been. + * The format can either be native or json for either native binary thrift, json or simple json fields representation. + * The default value is binary. + */ + public void setContentTypeFormat(String contentTypeFormat) { + this.contentTypeFormat = contentTypeFormat; + } + + public String getContentTypeFormat() { + return contentTypeFormat; + } + + public Object getDefaultInstance() { + return defaultInstance; + } + + public void setDefaultInstance(Object defaultInstance) { + this.defaultInstance = defaultInstance; + } + + @Override + protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { + if (this.instanceClass != null) { + setProperty(camelContext, dataFormat, "instanceClass", instanceClass); + } + if (this.contentTypeFormat != null) { + setProperty(camelContext, dataFormat, "contentTypeFormat", contentTypeFormat); + } + if (this.defaultInstance != null) { + setProperty(camelContext, dataFormat, "defaultInstance", defaultInstance); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java b/camel-core/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java index 97c3496..adda5df 100644 --- a/camel-core/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java @@ -54,6 +54,7 @@ import org.apache.camel.model.dataformat.SoapJaxbDataFormat; import org.apache.camel.model.dataformat.StringDataFormat; import org.apache.camel.model.dataformat.SyslogDataFormat; import org.apache.camel.model.dataformat.TarFileDataFormat; +import org.apache.camel.model.dataformat.ThriftDataFormat; import org.apache.camel.model.dataformat.TidyMarkupDataFormat; import org.apache.camel.model.dataformat.UniVocityCsvDataFormat; import org.apache.camel.model.dataformat.UniVocityFixedWidthDataFormat; @@ -113,6 +114,7 @@ public class DataFormatTransformerDefinition extends TransformerDefinition { @XmlElement(required = false, name = "string", type = StringDataFormat.class), @XmlElement(required = false, name = "syslog", type = SyslogDataFormat.class), @XmlElement(required = false, name = "tarfile", type = TarFileDataFormat.class), + @XmlElement(required = false, name = "thrift", type = ThriftDataFormat.class), @XmlElement(required = false, name = "tidyMarkup", type = TidyMarkupDataFormat.class), @XmlElement(required = false, name = "univocity-csv", type = UniVocityCsvDataFormat.class), @XmlElement(required = false, name = "univocity-fixed", type = UniVocityFixedWidthDataFormat.class), http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index ---------------------------------------------------------------------- diff --git a/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index index a8b348c..4fe9c7d 100644 --- a/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index +++ b/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index @@ -42,6 +42,7 @@ SoapJaxbDataFormat StringDataFormat SyslogDataFormat TarFileDataFormat +ThriftDataFormat TidyMarkupDataFormat UniVocityCsvDataFormat UniVocityFixedWidthDataFormat http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc ---------------------------------------------------------------------- diff --git a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc index 448cd01..091d742 100644 --- a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc +++ b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc @@ -7,19 +7,18 @@ Protobuf - Protocol Buffers "Protocol Buffers - Google's data interchange format" -Camel provides a link:data-format.html[Data Format] to serialse between +Camel provides a link:data-format.html[Data Format] to serialize between Java and the Protocol Buffer protocol. The project's site details why you may wish to -https://developers.google.com/protocol-buffers/docs/overview[choose -this format over xml]. Protocol Buffer is language-neutral and +https://developers.google.com/protocol-buffers/docs/overview[choose this format over xml]. +Protocol Buffer is language-neutral and platform-neutral, so messages produced by your Camel routes may be consumed by other language implementations. https://developers.google.com/protocol-buffers/docs/reference/java/[API Site] + https://github.com/google/protobuf[Protobuf Implementation] + -https://developers.google.com/protocol-buffers/docs/javatutorial[Protobuf -Java Tutorial] +https://developers.google.com/protocol-buffers/docs/javatutorial[Protobuf Java Tutorial] ### Protobuf Options @@ -55,8 +54,7 @@ from("direct:marshal") ### Protobuf overview This quick overview of how to use Protobuf. For more detail see the -http://code.google.com/apis/protocolbuffers/docs/javatutorial.html[complete -tutorial] +http://code.google.com/apis/protocolbuffers/docs/javatutorial.html[complete tutorial] ### Defining the proto format @@ -145,7 +143,7 @@ You can also run the compiler for any additional supported languages you require This will generate a single Java class named AddressBookProtos which contains inner classes for Person and AddressBook. Builders are also implemented for you. The generated classes implement -com.google.protobuf.Message which is required by the serialisation +com.google.protobuf.Message which is required by the serialization mechanism. For this reason it important that only these classes are used in the body of your exchanges. Camel will throw an exception on route creation if you attempt to tell the link:data-format.html[Data Format] @@ -156,7 +154,7 @@ domain classes. ### Java DSL You can use create the ProtobufDataFormat instance and pass it to Camel -DataFormat marshal and unmarsha API like this. +DataFormat marshal and unmarshal API like this. [source,java] ----------------------------------------------------------------------------------- @@ -173,9 +171,9 @@ default instance class name like this. -------------------------------------------------------------------------------------------------- // You don't need to specify the default instance for protobuf marshaling from("direct:marshal").marshal().protobuf(); - from("direct:unmarshalA").unmarshal(). - protobuf("org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person"). - to ("mock:reverse"); + from("direct:unmarshalA").unmarshal() + .protobuf("org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person") + .to("mock:reverse"); from("direct:unmarshalB").unmarshal().protobuf(Person.getDefaultInstance()).to("mock:reverse"); -------------------------------------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-protobuf/src/test/java/org/apache/camel/dataformat/protobuf/ProtobufMarshalAndUnmarshalSpringTest.java ---------------------------------------------------------------------- diff --git a/components/camel-protobuf/src/test/java/org/apache/camel/dataformat/protobuf/ProtobufMarshalAndUnmarshalSpringTest.java b/components/camel-protobuf/src/test/java/org/apache/camel/dataformat/protobuf/ProtobufMarshalAndUnmarshalSpringTest.java index 9ec978e..a190ec4 100644 --- a/components/camel-protobuf/src/test/java/org/apache/camel/dataformat/protobuf/ProtobufMarshalAndUnmarshalSpringTest.java +++ b/components/camel-protobuf/src/test/java/org/apache/camel/dataformat/protobuf/ProtobufMarshalAndUnmarshalSpringTest.java @@ -16,12 +16,70 @@ */ package org.apache.camel.dataformat.protobuf; +import org.apache.camel.CamelException; +import org.apache.camel.FailedToCreateRouteException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.dataformat.protobuf.generated.AddressBookProtos; +import org.apache.camel.dataformat.protobuf.generated.AddressBookProtos.Person; +import org.apache.camel.test.spring.CamelSpringTestSupport; + +import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; -public class ProtobufMarshalAndUnmarshalSpringTest extends ProtobufMarshalAndUnmarshalTest { +public class ProtobufMarshalAndUnmarshalSpringTest extends CamelSpringTestSupport { + @Override protected ClassPathXmlApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("org/apache/camel/dataformat/protobuf/springDataFormat.xml"); } + + @Test + public void testMarshalAndUnmarshalWithDataFormat() throws Exception { + marshalAndUnmarshal("direct:in", "direct:back"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL1() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalA"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL2() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalB"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL3() throws Exception { + try { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:unmarshalC").unmarshal().protobuf(new CamelException("wrong instance")).to("mock:reverse"); + } + }); + fail("Expect the exception here"); + } catch (Exception ex) { + assertTrue("Expect FailedToCreateRouteException", ex instanceof FailedToCreateRouteException); + assertTrue("Get a wrong reason", ex.getCause() instanceof IllegalArgumentException); + } + } + + private void marshalAndUnmarshal(String inURI, String outURI) throws Exception { + AddressBookProtos.Person input = AddressBookProtos.Person.newBuilder().setName("Martin").setId(1234).build(); + + MockEndpoint mock = getMockEndpoint("mock:reverse"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(Person.class); + mock.message(0).body().isEqualTo(input); + + Object marshalled = template.requestBody(inURI, input); + template.sendBody(outURI, marshalled); + + mock.assertIsSatisfied(); + + Person output = mock.getReceivedExchanges().get(0).getIn().getBody(Person.class); + assertEquals("Martin", output.getName()); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-protobuf/src/test/resources/org/apache/camel/dataformat/protobuf/springDataFormat.xml ---------------------------------------------------------------------- diff --git a/components/camel-protobuf/src/test/resources/org/apache/camel/dataformat/protobuf/springDataFormat.xml b/components/camel-protobuf/src/test/resources/org/apache/camel/dataformat/protobuf/springDataFormat.xml index 6716f51..eeeaafc 100644 --- a/components/camel-protobuf/src/test/resources/org/apache/camel/dataformat/protobuf/springDataFormat.xml +++ b/components/camel-protobuf/src/test/resources/org/apache/camel/dataformat/protobuf/springDataFormat.xml @@ -21,21 +21,8 @@ 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.xsd - http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd - "> - - <!-- START SNIPPET: example - from("direct:in").marshal(format); - from("direct:back").unmarshal(format).to("mock:reverse"); - - from("direct:marshal").marshal().protobuf(); - from("direct:unmarshalA").unmarshal().protobuf("org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person").to("mock:reverse"); - - from("direct:unmarshalB").unmarshal().protobuf(Person.getDefaultInstance()).to("mock:reverse"); - --> - - - + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <dataFormats> <protobuf id="protobuf1" instanceClass="org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person"/> @@ -69,8 +56,8 @@ </route> </camelContext> - <bean id="protobuf2" class="org.apache.camel.datafromat.protobuf.ProtobufDataFormat"> - <property name="instanceClassName" value="org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person"/> + <bean id="protobuf2" class="org.apache.camel.dataformat.protobuf.ProtobufDataFormat"> + <property name="instanceClass" value="org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person"/> </bean> </beans> http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/ReadMe.md ---------------------------------------------------------------------- diff --git a/components/camel-thrift/ReadMe.md b/components/camel-thrift/ReadMe.md new file mode 100644 index 0000000..0524974 --- /dev/null +++ b/components/camel-thrift/ReadMe.md @@ -0,0 +1,30 @@ +# How to upgrade Apache Thrift + +You need to install the thrift compiler from + + https://github.com/apache/thrift/releases + +For linux/osx you download the .tar distro, and untar it, and then + + sudo ./bootstrap.sh + export CXXFLAGS='-Os -ffunction-sections -Wl,--gc-sections -fno-asynchronous-unwind-tables -Wl,--strip-all' + sudo ./configure --without-c_glib --without-java --without-python --without-ruby --without-nodejs --disable-libs --disable-tests --disable-tutorial --disable-shared --enable-static + sudo ./make check + sudo ./make install + +If its succesful, you can type + + thrift --version + +To display the version of the thrift compiler. + +You then need to compile the sample test source for the `camel-thrift` component. + +The sample test source is an example taken from the Thrift Java tutorial at: https://thrift.apache.org/tutorial/java + + cd components/camel-thrift + cd src/test/thrift + thrift -r --gen java -out ../java/ ./tutorial-dataformat.thrift + +The generate source code will override the existing. + http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-thrift/pom.xml b/components/camel-thrift/pom.xml new file mode 100644 index 0000000..9e4bc91 --- /dev/null +++ b/components/camel-thrift/pom.xml @@ -0,0 +1,92 @@ +<?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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>2.20.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-thrift</artifactId> + <packaging>jar</packaging> + <name>Camel :: Thrift</name> + <description>Camel Apache Thrift data format and RPC support</description> + + <properties> + <camel.osgi.export.pkg>org.apache.camel.dataformat.thrift.*</camel.osgi.export.pkg> + <camel.osgi.export.service>org.apache.camel.spi.DataFormatResolver;dataformat=thrift</camel.osgi.export.service> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.thrift</groupId> + <artifactId>libthrift</artifactId> + <version>${libthrift-version}</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-spring</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson-version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/main/docs/thrift-dataformat.adoc ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/main/docs/thrift-dataformat.adoc b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc new file mode 100644 index 0000000..54a6267 --- /dev/null +++ b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc @@ -0,0 +1,156 @@ +## Thrift DataFormat + +*Available as of Camel version 2.20* + + +Camel provides a link:data-format.html[Data Format] to serialize between +Java and the Apache Thrift . The project's site details why +you may wish to +https://thrift.apache.org/. +Apache Thrift is language-neutral and +platform-neutral, so messages produced by your Camel routes may be +consumed by other language implementations. + +https://github.com/apache/thrift[Apache Thrift Implementation] + + +### Thrift Options + +// dataformat options: START +The Thrift dataformat supports 3 options which are listed below. + + + +[width="100%",cols="2s,1m,1m,6",options="header"] +|======================================================================= +| Name | Default | Java Type | Description +| instanceClass | | String | Name of class to use when unarmshalling +| contentTypeFormat | binary | String | Defines a content type format in which thrift message will be serialized/deserialized from(to) the Java been. The format can either be native or json for either native binary thrift json or simple json fields representation. The default value is binary. +| contentTypeHeader | false | Boolean | Whether the data format should set the Content-Type header with the type from the data format if the data format is capable of doing so. For example application/xml for data formats marshalling to XML or application/json for data formats marshalling to JSon etc. +|======================================================================= +// dataformat options: END + +### Content type format + +It's possible to parse JSON message to convert it to the Thrift format and unparse it back using native util converter. +To use this option, set contentTypeFormat value to 'json' or call thrift with second parameter. +If default instance is not specified, always use native binary Thrift format. +The simple JSON format is write-only (marshal) and produces a simple output format suitable for parsing by scripting languages. +The sample code shows below: + +[source,java] +-------------------------------------------------------------------------------------------------- +from("direct:marshal") + .unmarshal() + .thrift("org.apache.camel.dataformat.thrift.generated.Work", "json") + .to("mock:reverse"); +-------------------------------------------------------------------------------------------------- + +### Thrift overview + +This quick overview of how to use Thrift. For more detail see the +https://thrift.apache.org/tutorial/[complete tutorial] + +### Defining the thrift format + +The first step is to define the format for the body of your exchange. +This is defined in a .thrift file as so: + +*tutorial.thrift* + +[source,java] +------------------------------------------------------------ +namespace java org.apache.camel.dataformat.thrift.generated + +enum Operation { + ADD = 1, + SUBTRACT = 2, + MULTIPLY = 3, + DIVIDE = 4 +} + +struct Work { + 1: i32 num1 = 0, + 2: i32 num2, + 3: Operation op, + 4: optional string comment, +} +------------------------------------------------------------ + +### Generating Java classes + +The Apache Thrift provides a compiler which will generate the Java +classes for the format we defined in our .thrift file. + +You can also run the compiler for any additional supported languages you require manually. + +`thrift -r --gen java -out ../java/ ./tutorial-dataformat.thrift` + +This will generate separate Java class for each type defined in .thrift +file, i.e. struct or enum. +The generated classes implement org.apache.thrift.TBase which is required +by the serialization mechanism. For this reason it important that only +these classes are used in the body of your exchanges. +Camel will throw an exception on route creation if you attempt to tell +the link:data-format.html[Data Format] to use a class that does not implement +org.apache.thrift.TBase. + +### Java DSL + +You can use create the ThriftDataFormat instance and pass it to Camel +DataFormat marshal and unmarshal API like this. + +[source,java] +----------------------------------------------------------------------------------- + ThriftDataFormat format = new ThriftDataFormat(new Work()); + + from("direct:in").marshal(format); + from("direct:back").unmarshal(format).to("mock:reverse"); +----------------------------------------------------------------------------------- + +Or use the DSL thrift() passing the unmarshal default instance or +default instance class name like this. + +[source,java] +-------------------------------------------------------------------------------------------------- + // You don't need to specify the default instance for the thrift marshaling + from("direct:marshal").marshal().thrift(); + from("direct:unmarshalA").unmarshal() + .thrift("org.apache.camel.dataformat.thrift.generated.Work") + .to("mock:reverse"); + + from("direct:unmarshalB").unmarshal().thrift(new Work()).to("mock:reverse"); +-------------------------------------------------------------------------------------------------- + +### Spring DSL + +The following example shows how to use Thrift to unmarshal using Spring +configuring the thrift data type + +[source,java] +---------------------------------------------------------------------------------------------------------- +<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <unmarshal> + <thrift instanceClass="org.apache.camel.dataformat.thrift.generated.Work" /> + </unmarshal> + <to uri="mock:result"/> + </route> +</camelContext> +---------------------------------------------------------------------------------------------------------- + +### Dependencies + +To use Thrift in your camel routes you need to add the a dependency on +*camel-thrift* which implements this data format. + +[source,xml] +----------------------------------------- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-thrift</artifactId> + <version>x.x.x</version> + <!-- use the same version as your Camel core version --> +</dependency> +----------------------------------------- +### See Also http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java b/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java new file mode 100644 index 0000000..ecb9e69 --- /dev/null +++ b/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java @@ -0,0 +1,204 @@ +/** + * 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.dataformat.thrift; + +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.CamelException; +import org.apache.camel.Exchange; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.DataFormatName; +import org.apache.camel.support.ServiceSupport; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; +import org.apache.commons.io.IOUtils; +import org.apache.thrift.TBase; +import org.apache.thrift.TDeserializer; +import org.apache.thrift.TSerializer; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TJSONProtocol; +import org.apache.thrift.protocol.TSimpleJSONProtocol; + +public class ThriftDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { + + public static final String CONTENT_TYPE_FORMAT_BINARY = "binary"; + public static final String CONTENT_TYPE_FORMAT_JSON = "json"; + public static final String CONTENT_TYPE_FORMAT_SIMPLE_JSON = "sjson"; + + private static final String CONTENT_TYPE_HEADER_NATIVE = "application/octet-stream"; + private static final String CONTENT_TYPE_HEADER_JSON = "application/json"; + + private CamelContext camelContext; + @SuppressWarnings("rawtypes") + private TBase defaultInstance; + private String instanceClassName; + private boolean contentTypeHeader; + private String contentTypeFormat = CONTENT_TYPE_FORMAT_BINARY; + + public ThriftDataFormat() { + } + + @SuppressWarnings("rawtypes") + public ThriftDataFormat(TBase defaultInstance) { + this.defaultInstance = defaultInstance; + } + + @SuppressWarnings("rawtypes") + public ThriftDataFormat(TBase defaultInstance, String contentTypeFormat) { + this.defaultInstance = defaultInstance; + this.contentTypeFormat = contentTypeFormat; + } + + @Override + public String getDataFormatName() { + return "thrift"; + } + + public CamelContext getCamelContext() { + return camelContext; + } + + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @SuppressWarnings("rawtypes") + public void setDefaultInstance(TBase instance) { + this.defaultInstance = instance; + } + + @SuppressWarnings("rawtypes") + public void setDefaultInstance(Object instance) { + if (instance instanceof TBase) { + this.defaultInstance = (TBase)instance; + } else { + throw new IllegalArgumentException("The argument for setDefaultInstance should be subClass of org.apache.thrift.TBase"); + } + } + + public void setInstanceClass(String className) throws Exception { + ObjectHelper.notNull(className, "ThriftDataFormat instaceClass"); + instanceClassName = className; + } + + public void setContentTypeHeader(boolean contentTypeHeader) { + this.contentTypeHeader = contentTypeHeader; + } + + public boolean isContentTypeHeader() { + return contentTypeHeader; + } + + /* + * Defines a content type format in which thrift message will be + * serialized/deserialized from(to) the Java been. It can be native thrift + * format or JSON fields representation. The default value is 'native'. + */ + public void setContentTypeFormat(String contentTypeFormat) { + StringHelper.notEmpty(contentTypeFormat, "ThriftDataFormat contentTypeFormat"); + this.contentTypeFormat = contentTypeFormat; + } + + /* + * (non-Javadoc) + * @see org.apache.camel.spi.DataFormat#marshal(org.apache.camel.Exchange, + * java.lang.Object, java.io.OutputStream) + */ + @SuppressWarnings("rawtypes") + public void marshal(final Exchange exchange, final Object graph, final OutputStream outputStream) throws Exception { + String contentTypeHeader = CONTENT_TYPE_HEADER_NATIVE; + TSerializer serializer; + + if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_JSON)) { + serializer = new TSerializer(new TJSONProtocol.Factory()); + IOUtils.write(serializer.toString((TBase)graph, "UTF-8"), outputStream, "UTF-8"); + contentTypeHeader = CONTENT_TYPE_HEADER_JSON; + } else if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_SIMPLE_JSON)) { + serializer = new TSerializer(new TSimpleJSONProtocol.Factory()); + IOUtils.write(serializer.toString((TBase)graph, "UTF-8"), outputStream, "UTF-8"); + contentTypeHeader = CONTENT_TYPE_HEADER_JSON; + } else if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_BINARY)) { + serializer = new TSerializer(new TBinaryProtocol.Factory()); + IOUtils.write(serializer.serialize((TBase)graph), outputStream); + } else { + throw new CamelException("Invalid thrift content type format: " + contentTypeFormat); + } + + if (isContentTypeHeader()) { + if (exchange.hasOut()) { + exchange.getOut().setHeader(Exchange.CONTENT_TYPE, contentTypeHeader); + } else { + exchange.getIn().setHeader(Exchange.CONTENT_TYPE, contentTypeHeader); + } + } + } + + /* + * (non-Javadoc) + * @see org.apache.camel.spi.DataFormat#unmarshal(org.apache.camel.Exchange, + * java.io.InputStream) + */ + public Object unmarshal(final Exchange exchange, final InputStream inputStream) throws Exception { + TDeserializer deserializer; + ObjectHelper.notNull(defaultInstance, "defaultInstance or instanceClassName must be set", this); + + if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_JSON)) { + deserializer = new TDeserializer(new TJSONProtocol.Factory()); + deserializer.deserialize(defaultInstance, IOUtils.toByteArray(inputStream)); + } else if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_BINARY)) { + deserializer = new TDeserializer(new TBinaryProtocol.Factory()); + deserializer.deserialize(defaultInstance, IOUtils.toByteArray(inputStream)); + } else if (contentTypeFormat.equals(CONTENT_TYPE_FORMAT_SIMPLE_JSON)) { + throw new CamelException("Simple JSON format is avalable for the message marshalling only"); + } else { + throw new CamelException("Invalid thrift content type format: " + contentTypeFormat); + } + + return defaultInstance; + } + + @SuppressWarnings("rawtypes") + protected TBase loadDefaultInstance(final String className, final CamelContext context) throws CamelException, ClassNotFoundException { + Class<?> instanceClass = context.getClassResolver().resolveMandatoryClass(className); + if (TBase.class.isAssignableFrom(instanceClass)) { + try { + return (TBase)instanceClass.newInstance(); + } catch (final Exception ex) { + throw new CamelException("Can't set the defaultInstance of ThriftDataFormat with " + className + ", caused by " + ex); + } + } else { + throw new CamelException("Can't set the defaultInstance of ThriftDataFormat with " + className + + ", as the class is not a subClass of org.apache.thrift.TBase"); + } + } + + @Override + protected void doStart() throws Exception { + if (defaultInstance == null && instanceClassName != null) { + defaultInstance = loadDefaultInstance(instanceClassName, getCamelContext()); + } + } + + @Override + protected void doStop() throws Exception { + // noop + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/main/resources/META-INF/LICENSE.txt ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/main/resources/META-INF/LICENSE.txt b/components/camel-thrift/src/main/resources/META-INF/LICENSE.txt new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/components/camel-thrift/src/main/resources/META-INF/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/main/resources/META-INF/NOTICE.txt ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/main/resources/META-INF/NOTICE.txt b/components/camel-thrift/src/main/resources/META-INF/NOTICE.txt new file mode 100644 index 0000000..d92f2e3 --- /dev/null +++ b/components/camel-thrift/src/main/resources/META-INF/NOTICE.txt @@ -0,0 +1,14 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Camel distribution. == + ========================================================================= + + This product includes software developed by + The Apache Software Foundation (http://www.apache.org/). + + This product includes software developed by + The HAPI Project (http://hl7api.sourceforge.net/). + + Please read the different LICENSE files present in the licenses directory of + this distribution. http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/main/resources/META-INF/services/org/apache/camel/dataformat/thrift ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/main/resources/META-INF/services/org/apache/camel/dataformat/thrift b/components/camel-thrift/src/main/resources/META-INF/services/org/apache/camel/dataformat/thrift new file mode 100644 index 0000000..1af7578 --- /dev/null +++ b/components/camel-thrift/src/main/resources/META-INF/services/org/apache/camel/dataformat/thrift @@ -0,0 +1,18 @@ +# +# 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. +# + +class=org.apache.camel.dataformat.thrift.ThriftDataFormat http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/test/java/META-INF/MANIFEST.MF ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/test/java/META-INF/MANIFEST.MF b/components/camel-thrift/src/test/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000..254272e --- /dev/null +++ b/components/camel-thrift/src/test/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalJsonTest.java ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalJsonTest.java b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalJsonTest.java new file mode 100644 index 0000000..22d0c0f --- /dev/null +++ b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalJsonTest.java @@ -0,0 +1,106 @@ +/** + * 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.dataformat.thrift; + +import com.google.gson.Gson; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.dataformat.thrift.generated.Operation; +import org.apache.camel.dataformat.thrift.generated.Work; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class ThriftMarshalAndUnmarshalJsonTest extends CamelTestSupport { + + private static final String WORK_JSON_TEST = "{\"1\":{\"i32\":1},\"2\":{\"i32\":100},\"3\":{\"i32\":3},\"4\":{\"str\":\"This is a test thrift data\"}}"; + private static final String WORK_TEST_COMMENT = "This is a test thrift data"; + private static final int WORK_TEST_NUM1 = 1; + private static final int WORK_TEST_NUM2 = 100; + private static final Operation WORK_TEST_OPERATION = Operation.MULTIPLY; + + @Test + public void testMarshalAndUnmarshal() throws Exception { + marshalAndUnmarshal("direct:in", "direct:back"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalA"); + } + + @Test + public void testMarshalSimpleJson() throws Exception { + Gson gson = new Gson(); + Work input = new Work(); + + MockEndpoint mock = getMockEndpoint("mock:reverse-sjson"); + mock.expectedMessageCount(1); + + input.num1 = WORK_TEST_NUM1; + input.num2 = WORK_TEST_NUM2; + input.op = WORK_TEST_OPERATION; + input.comment = WORK_TEST_COMMENT; + + template.requestBody("direct:marshal-sjson", input); + mock.assertIsSatisfied(); + + String body = mock.getReceivedExchanges().get(0).getIn().getBody(String.class); + Work output = gson.fromJson(body, Work.class); + + assertEquals(WORK_TEST_NUM1, output.getNum1()); + assertEquals(WORK_TEST_NUM2, output.getNum2()); + assertEquals(WORK_TEST_COMMENT, output.getComment()); + } + + private void marshalAndUnmarshal(String inURI, String outURI) throws Exception { + MockEndpoint mock = getMockEndpoint("mock:reverse"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(Work.class); + + Object marshalled = template.requestBody(inURI, WORK_JSON_TEST); + + template.sendBody(outURI, marshalled); + + mock.assertIsSatisfied(); + + Work output = mock.getReceivedExchanges().get(0).getIn().getBody(Work.class); + + assertEquals(WORK_TEST_NUM1, output.getNum1()); + assertEquals(WORK_TEST_NUM2, output.getNum2()); + assertEquals(WORK_TEST_OPERATION, output.getOp()); + assertEquals(WORK_TEST_COMMENT, output.getComment()); + } + + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + ThriftDataFormat format = new ThriftDataFormat(new Work(), ThriftDataFormat.CONTENT_TYPE_FORMAT_JSON); + + from("direct:in").unmarshal(format).to("mock:reverse"); + from("direct:back").marshal(format); + + from("direct:marshal").unmarshal().thrift("org.apache.camel.dataformat.thrift.generated.Work", "json").to("mock:reverse"); + from("direct:unmarshalA").marshal().thrift(); + + from("direct:marshal-sjson").marshal().thrift("org.apache.camel.dataformat.thrift.generated.Work", "sjson").convertBodyTo(String.class).to("mock:reverse-sjson"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalSpringTest.java ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalSpringTest.java b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalSpringTest.java new file mode 100644 index 0000000..c4ca65b --- /dev/null +++ b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalSpringTest.java @@ -0,0 +1,95 @@ +/** + * 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.dataformat.thrift; + +import org.apache.camel.CamelException; +import org.apache.camel.FailedToCreateRouteException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.dataformat.thrift.generated.Operation; +import org.apache.camel.dataformat.thrift.generated.Work; +import org.apache.camel.test.spring.CamelSpringTestSupport; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class ThriftMarshalAndUnmarshalSpringTest extends CamelSpringTestSupport { + private static final String WORK_TEST_COMMENT = "This is a test thrift data"; + private static final int WORK_TEST_NUM1 = 1; + private static final int WORK_TEST_NUM2 = 100; + private static final Operation WORK_TEST_OPERATION = Operation.MULTIPLY; + + @Override + protected ClassPathXmlApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/dataformat/thrift/springDataFormat.xml"); + } + + @Test + public void testMarshalAndUnmarshalWithDataFormat() throws Exception { + marshalAndUnmarshal("direct:in", "direct:back"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL1() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalA"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL2() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalB"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL3() throws Exception { + try { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:unmarshalC").unmarshal().thrift(new CamelException("wrong instance")).to("mock:reverse"); + } + }); + fail("Expect the exception here"); + } catch (Exception ex) { + assertTrue("Expect FailedToCreateRouteException", ex instanceof FailedToCreateRouteException); + assertTrue("Get a wrong reason", ex.getCause() instanceof IllegalArgumentException); + } + } + + private void marshalAndUnmarshal(String inURI, String outURI) throws Exception { + Work input = new Work(); + + input.num1 = WORK_TEST_NUM1; + input.num2 = WORK_TEST_NUM2; + input.op = WORK_TEST_OPERATION; + input.comment = WORK_TEST_COMMENT; + + MockEndpoint mock = getMockEndpoint("mock:reverse"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(Work.class); + mock.message(0).body().isEqualTo(input); + + Object marshalled = template.requestBody(inURI, input); + + template.sendBody(outURI, marshalled); + + mock.assertIsSatisfied(); + + Work output = mock.getReceivedExchanges().get(0).getIn().getBody(Work.class); + assertEquals(WORK_TEST_COMMENT, output.getComment()); + assertEquals(WORK_TEST_OPERATION, output.getOp()); + assertEquals(WORK_TEST_NUM2, output.getNum2()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalTest.java ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalTest.java b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalTest.java new file mode 100644 index 0000000..6443432 --- /dev/null +++ b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/ThriftMarshalAndUnmarshalTest.java @@ -0,0 +1,108 @@ +/** + * 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.dataformat.thrift; + +import org.apache.camel.CamelException; +import org.apache.camel.FailedToCreateRouteException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.dataformat.thrift.generated.Operation; +import org.apache.camel.dataformat.thrift.generated.Work; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class ThriftMarshalAndUnmarshalTest extends CamelTestSupport { + private static final String WORK_TEST_COMMENT = "This is a test thrift data"; + private static final int WORK_TEST_NUM1 = 1; + private static final int WORK_TEST_NUM2 = 100; + private static final Operation WORK_TEST_OPERATION = Operation.MULTIPLY; + + @Test + public void testMarshalAndUnmarshalWithDataFormat() throws Exception { + marshalAndUnmarshal("direct:in", "direct:back"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL1() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalA"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL2() throws Exception { + marshalAndUnmarshal("direct:marshal", "direct:unmarshalB"); + } + + @Test + public void testMarshalAndUnmarshalWithDSL3() throws Exception { + try { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:unmarshalC").unmarshal().thrift(new CamelException("wrong instance")).to("mock:reverse"); + } + }); + fail("Expect the exception here"); + } catch (Exception ex) { + assertTrue("Expect FailedToCreateRouteException", ex instanceof FailedToCreateRouteException); + assertTrue("Get a wrong reason", ex.getCause() instanceof IllegalArgumentException); + } + } + + private void marshalAndUnmarshal(String inURI, String outURI) throws Exception { + Work input = new Work(); + + input.num1 = WORK_TEST_NUM1; + input.num2 = WORK_TEST_NUM2; + input.op = WORK_TEST_OPERATION; + input.comment = WORK_TEST_COMMENT; + + MockEndpoint mock = getMockEndpoint("mock:reverse"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(Work.class); + mock.message(0).body().isEqualTo(input); + + Object marshalled = template.requestBody(inURI, input); + + template.sendBody(outURI, marshalled); + + mock.assertIsSatisfied(); + + Work output = mock.getReceivedExchanges().get(0).getIn().getBody(Work.class); + assertEquals(WORK_TEST_COMMENT, output.getComment()); + assertEquals(WORK_TEST_OPERATION, output.getOp()); + assertEquals(WORK_TEST_NUM2, output.getNum2()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + ThriftDataFormat format = new ThriftDataFormat(new Work()); + + from("direct:in").marshal(format); + from("direct:back").unmarshal(format).to("mock:reverse"); + + from("direct:marshal").marshal().thrift(); + from("direct:unmarshalA").unmarshal().thrift("org.apache.camel.dataformat.thrift.generated.Work").to("mock:reverse"); + + from("direct:unmarshalB").unmarshal().thrift(new Work()).to("mock:reverse"); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/362a8943/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/generated/Operation.java ---------------------------------------------------------------------- diff --git a/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/generated/Operation.java b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/generated/Operation.java new file mode 100644 index 0000000..cb98641 --- /dev/null +++ b/components/camel-thrift/src/test/java/org/apache/camel/dataformat/thrift/generated/Operation.java @@ -0,0 +1,55 @@ +/** + * Autogenerated by Thrift Compiler (0.9.3) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package org.apache.camel.dataformat.thrift.generated; + + +import java.util.Map; +import java.util.HashMap; +import org.apache.thrift.TEnum; + +/** + * You can define enums, which are just 32 bit integers. Values are optional + * and start at 1 if not supplied, C style again. + */ +public enum Operation implements org.apache.thrift.TEnum { + ADD(1), + SUBTRACT(2), + MULTIPLY(3), + DIVIDE(4); + + private final int value; + + private Operation(int value) { + this.value = value; + } + + /** + * Get the integer value of this enum value, as defined in the Thrift IDL. + */ + public int getValue() { + return value; + } + + /** + * Find a the enum type by its integer value, as defined in the Thrift IDL. + * @return null if the value is not found. + */ + public static Operation findByValue(int value) { + switch (value) { + case 1: + return ADD; + case 2: + return SUBTRACT; + case 3: + return MULTIPLY; + case 4: + return DIVIDE; + default: + return null; + } + } +}