CAMEL-10930: Move groovy dsl into camel-groovy-dsl
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/2a198c2f Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/2a198c2f Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/2a198c2f Branch: refs/heads/master Commit: 2a198c2f5db7f92df7c96774c907b69dd0114b65 Parents: 8a77898 Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Mar 3 09:56:14 2017 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Mar 3 09:56:14 2017 +0100 ---------------------------------------------------------------------- components/camel-groovy-dsl/pom.xml | 202 ++++++++++ .../src/main/docs/groovy-dsl.adoc | 402 +++++++++++++++++++ .../groovy/converter/GPathResultConverter.java | 51 +++ .../camel/groovy/converter/TypeConverter.java | 83 ++++ .../dataformat/AbstractXmlDataFormat.java | 102 +++++ .../groovy/dataformat/XmlParserDataFormat.java | 65 +++ .../groovy/dataformat/XmlSlurperDataFormat.java | 55 +++ .../camel/groovy/extend/CamelGroovyMethods.java | 383 ++++++++++++++++++ .../extend/ClosureAggregationStrategy.java | 37 ++ .../camel/groovy/extend/ClosureExpression.java | 46 +++ .../camel/groovy/extend/ClosureProcessor.java | 40 ++ .../camel/groovy/extend/ClosureSupport.java | 39 ++ .../src/main/resources/META-INF/LICENSE.txt | 203 ++++++++++ .../src/main/resources/META-INF/NOTICE.txt | 11 + .../META-INF/services/camel/TypeConverter | 18 + .../META-INF/services/groovy/groovyMethods | 18 + .../org.codehaus.groovy.runtime.ExtensionModule | 20 + .../main/resources/dsld/CamelGroovyMethods.dsld | 110 +++++ .../main/resources/gdsl/CamelGroovyMethods.gdsl | 110 +++++ .../camel/language/groovy/ConfigureCamel.groovy | 48 +++ .../groovy/extend/CamelGroovyMethodsTest.groovy | 244 +++++++++++ .../ClosureAggregationStrategyTest.groovy | 55 +++ .../groovy/extend/ClosureExpressionTest.groovy | 72 ++++ .../groovy/extend/ClosureProcessorTest.groovy | 57 +++ .../src/test/resources/log4j2.properties | 30 ++ .../src/test/resources/mygroovy.groovy | 2 + components/pom.xml | 1 + .../maven/packaging/SpringBootStarterMojo.java | 3 +- 28 files changed, 2505 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/pom.xml b/components/camel-groovy-dsl/pom.xml new file mode 100644 index 0000000..e7e460d --- /dev/null +++ b/components/camel-groovy-dsl/pom.xml @@ -0,0 +1,202 @@ +<?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.19.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-groovy-dsl</artifactId> + <packaging>jar</packaging> + <name>Camel :: Groovy DSL (deprecated)</name> + <description>Camel Groovy DSL support</description> + + <properties> + <camel.osgi.import.pkg> + org.codehaus.groovy.runtime.callsite, + org.apache.camel.*;${camel.osgi.import.camel.version}, + ${camel.osgi.import.defaults}, + * + </camel.osgi.import.pkg> + <camel.osgi.export.pkg> + org.apache.camel.groovy.converter.*, + org.apache.camel.groovy.dataformat.*, + org.apache.camel.groovy.extend.* + </camel.osgi.export.pkg> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</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>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <pluginManagement> + <plugins> + <!-- Eclipse m2e Lifecycle Management --> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>${lifecycle-mapping-version}</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <versionRange>${maven-compiler-plugin-version}</versionRange> + <goals> + <goal>compile</goal> + <goal>testCompile</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerId>groovy-eclipse-compiler</compilerId> + <!-- set verbose to be true if you want lots of uninteresting messages --> + <!-- <verbose>true</verbose> --> + </configuration> + <dependencies> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-compiler</artifactId> + <version>2.9.2-01</version> + <exclusions> + <exclusion> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-batch</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-batch</artifactId> + <version>2.4.3-01</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-eclipse-plugin</artifactId> + <configuration> + <additionalProjectnatures> + <projectnature>org.eclipse.jdt.groovy.core.groovyNature</projectnature> + </additionalProjectnatures> + <classpathContainers> + <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer> + <classpathContainer>GROOVY_DSL_SUPPORT</classpathContainer> + </classpathContainers> + </configuration> + </plugin> + </plugins> + <!-- Need to explicitly specify test resources, otherwise maven eclipse plugin + does not include src/test/groovy as source folder --> + <testResources> + <testResource> + <directory>src/test/groovy</directory> + </testResource> + <testResource> + <directory>src/test/resources</directory> + </testResource> + </testResources> + </build> + + <profiles> + <profile> + <id>jdk9-build</id> + <activation> + <jdk>9</jdk> + </activation> + <build> + <plugins> + <plugin> + <!--Skip compile on Java 9 https://issues.apache.org/jira/browse/CAMEL-10905 --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>default-compile</id> + <phase>none</phase> + </execution> + <execution> + <id>default-testCompile</id> + <phase>none</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc b/components/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc new file mode 100644 index 0000000..8f3c126 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/docs/groovy-dsl.adoc @@ -0,0 +1,402 @@ +[[GroovyDSL-AbouttheGroovyDSL]] +About the Groovy DSL +^^^^^^^^^^^^^^^^^^^^ + +The Groovy DSL implementation is built on top of the existing Java-based +link:dsl.html[DSL], but it additionally allows to use Groovy language +features in your routes, particularly +http://www.groovy-lang.org/closures.html[Closures] acting as +link:processor.html[Processor], link:expression.html[Expression], +link:predicate.html[Predicate], or link:aggregator.html[Aggregation +Strategy]. + + With the Groovy DSL you write your RouteBuilder classes entirely in +Groovy, while the link:scripting-languages.html[scripting component] +allows to embed small scripts into Java routes. The Groovy DSL requires +Groovy 2.0 or newer and is available as of *Camel 2.11*. + +[[GroovyDSL-Introduction]] +Introduction +^^^^^^^^^^^^ + +Because Groovy is syntactically very similar to Java, you can write your +Groovy routes just like Java routes. The same Java DSL classes are being +used, with the exception that some of the DSL classes get extended with +a bunch of new methods at runtime. This is achieved by turning +camel-groovy into a Groovy +http://docs.codehaus.org/display/GROOVY/Creating+an+extension+module[Extension +Module] that defines extension methods on existing classes. + +The majority of the extension methods allow +http://www.groovy-lang.org/closures.html[Closures] to be used as +parameters e.g. for expressions, predicates, processors. The following +example reverses a string in the message body and then prints the value +to System.out: + +*MyRouteBuilder.groovy* + +[source,java] +----------------------------------------- +... + from('direct:test') + .transform { it.in.body.reverse() } + .process { println it.in.body } +... +----------------------------------------- + +The corresponding route in Java would look something like this: + +*MyRouteBuilder.java* + +[source,java] +----------------------------------------------------------------------------------------- +... + from("direct:test") + .transform(new Expression() { + @Override + public Object evaluate(Exchange e) { + return new StringBuffer(e.getIn().getBody().toString()).reverse().toString(); + } + }) + .process(new Processor() { + @Override + public void process(Exchange e) { + System.out.println(e.getIn().getBody()); + } + }); +... +----------------------------------------------------------------------------------------- + +[[GroovyDSL-DevelopingwiththeGroovyDSL]] +Developing with the Groovy DSL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To be able to use the Groovy DSL in your camel routes you need to add +the a dependency on *camel-groovy* which implements the Groovy DSL. + +If you use Maven you can just add the following to your pom.xml, +substituting the version number for the latest & greatest release (see +the download page for the latest versions). + +[source,xml] +--------------------------------------- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-groovy</artifactId> + <version>2.11.0</version> +</dependency> +--------------------------------------- + +Additionally you need to make sure that the Groovy classes will be +compiled. You can either use gmaven for this or, particularly with mixed +projects containing Java and Groovy code, you might want to use the +http://groovy.codehaus.org/Groovy-Eclipse+compiler+plugin+for+Maven[Groovy +Eclipse compiler]: + +[source,xml] +-------------------------------------------------------- + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerId>groovy-eclipse-compiler</compilerId> + </configuration> + <dependencies> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-compiler</artifactId> + <version>2.7.0-01</version> + </dependency> + </dependencies> + </plugin> +-------------------------------------------------------- + +As Eclipse user, you might want to configure the Maven Eclipse plugin in +a way so that your project is set up correctly for using +http://groovy.codehaus.org/Eclipse+Plugin[Eclipse Plugin for Groovy] +when `mvn eclipse:eclipse` is executed: + +[source,xml] +---------------------------------------------------------------------------------------- + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-eclipse-plugin</artifactId> + <configuration> + <additionalProjectnatures> + <projectnature>org.eclipse.jdt.groovy.core.groovyNature</projectnature> + </additionalProjectnatures> + <classpathContainers> + <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer> + <classpathContainer>GROOVY_DSL_SUPPORT</classpathContainer> + </classpathContainers> + </configuration> + </plugin> +---------------------------------------------------------------------------------------- + +[[GroovyDSL-UsingClosuresinyourroutes]] +Using Closures in your routes ++++++++++++++++++++++++++++++ + +Groovy closures can be used to write concise implementations of Camel +processors, expressions, predicates, and aggregation strategies. It is +recommended to keep more complicated implementations of these objects in +their own classes, e.g. to be able to test them more easily and not to +clutter up your routes with business logic. + +[[GroovyDSL-ProcessorClosures]] +Processor Closures + +All Java DSL parameters of type `org.apache.camel.Processor` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is disregarded. All closures may also refer to variables not +listed in their parameter list. Example: + +[source,java] +------------------------------------------------------------------------------ +... + private String someValue +... + from('direct:test') + .process { Exchange exchange -> println (exchange.in.body + someValue) } + .process { println (it.in.body + someValue) } // equivalent +... +------------------------------------------------------------------------------ + +[[GroovyDSL-ExpressionClosures]] +Expression Closures + +All Java DSL parameters of type `org.apache.camel.Expression` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is the result of the expression. Example: + +[source,java] +----------------------------------------------------- +... + private String someValue +... + from('direct:test') + .transform { it.in.body.reverse() + someValue } + .setHeader("myHeader") { someValue.reverse() } +... +----------------------------------------------------- + +[[GroovyDSL-PredicateClosures]] +Predicate Closures + +All Java DSL parameters of type `org.apache.camel.Predicate` can be +replaced by a closure that accepts an object of type +`org.apache.camel.Exchange` as only parameter. The return value of the +closure is translated into a boolean value representing the result of +the predicate. Example: + +[source,java] +------------------------------------------------------ +... + private String someValue + + // This time, the closure is stored in a variable + def pred = { Exchange e -> e.in.body != someValue } +... + from('direct:test') + .filter(pred) +... +------------------------------------------------------ + +[[GroovyDSL-AggregationStrategyClosures]] +Aggregation Strategy Closures + +Java DSL parameters of type +`org.apache.camel.processor.aggregate.AggregationStrategy` can be +replaced by a closure that accepts two objects of type +`org.apache.camel.Exchange` representing the two Exchanges to be +aggregated. The return value of the closure must be the aggregated +Exchange. Example: + +[source,java] +------------------------------------------------------------------------- +... + private String separator +... + from('direct:test1') + .enrich('direct:enrich') { Exchange original, Exchange resource -> + original.in.body += resource.in.body + separator + original // don't forget to return resulting exchange + } +... +------------------------------------------------------------------------- + +[[GroovyDSL-Genericclosurebridges]] +Generic closure bridges + +In addition to the above-mentioned DSL extensions, you can use closures +even if no DSL method signature with closure parameters is available. +Assuming there's no `filter(Closure)` method, you could instead write: + +[source,java] +--------------------------------------------------------- +... + private String someValue + + // This time, the closure is stored in a variable + def pred = { Exchange e -> e.in.body != someValue } +... + from('direct:test') + // predicate(Closure) -> org.apache.camel.Predicate + .filter(predicate(pred)) +... +--------------------------------------------------------- + +Similarly, `expression(Closure)` returns a Camel expression, +`processor(Closure)` returns a Processor, and `aggregator(Closure)` +returns an AggregationStrategy. + +[[GroovyDSL-UsingGroovyXMLprocessing]] +Using Groovy XML processing ++++++++++++++++++++++++++++ + +Groovy provides special http://groovy-lang.org/processing-xml.html[XML +processing support] through its `XmlParser`, `XmlNodePrinter` and +`XmlSlurper` classes. camel-groovy provides two +link:data-format.html[data formats] to use these classes directly in +your routes. + +*Unmarshal XML with XmlParser* + +[source,java] +----------------------------------------------------- +... + from('direct:test1') + .unmarshal().gnode() + // message body is now of type groovy.util.Node +... +----------------------------------------------------- + +By default, XML processing is _namespace-aware_. You can change this by +providing a boolean `false` parameter. + +*Unmarshal XML with XmlSlurper* + +[source,java] +--------------------------------------------------------------------------- +... + from('direct:test1') + .unmarshal().gpath(false) // explicitly namespace-unaware + // message body is now of type groovy.util.slurpersupport.GPathResult +... +--------------------------------------------------------------------------- + +Currently, marshalling is only supported for `groovy.util.Node` objects. + +*Marshal XML with XmlNodePrinter* + +[source,java] +------------------------------------------------------ +... + from('direct:test1') + // message body must be of type groovy.util.Node + .marshal().gnode() +... +------------------------------------------------------ + +[[GroovyDSL-UsingGroovyGStrings]] +Using Groovy GStrings ++++++++++++++++++++++ + +Groovy +http://docs.groovy-lang.org/latest/html/documentation/index.html#all-strings[GStrings] +are declared inside double-quotes and can contain arbitrary Groovy +expressions like accessing properties or calling methods, e.g. + +[source,java] +----------------------------------------- +def x = "It is currently ${ new Date() }" +----------------------------------------- + +Because GStrings aren't Strings, camel-groovy adds the necessary +link:type-converter.html[TypeConverter] to automatically turn them into +the required type. + +[[GroovyDSL-CustomDSLextensions]] +Custom DSL extensions ++++++++++++++++++++++ + +You can easily define your custom extensions - be it as a Java DSL +extension for your Groovy routes or for any other class unrelated to +Camel. All you have to do is to write your extension methods and provide +a extension module descriptor - the details are described in the +http://www.groovy-lang.org/metaprogramming.html#_extension_modules[Groovy +documentation]. And as long as you don't require other extension +methods, you can even use plain Java code to achieve this! + + As an example, let's write two DSL extensions to make commonly used DSL +methods more concise: + +*MyExtension.java* + +[source,java] +------------------------------------------------------------------------------------------------------------------------------- +import org.apache.camel.Endpoint; +import org.apache.camel.Predicate; + +public final class MyExtension { + private MyExtension() { + // Utility Class + } + + // Set the id of a route to its consumer URI + public static RouteDefinition fromId(RouteDefinition delegate, String uri) { + return delegate.from(uri).routeId(uri); + } + + public static RouteDefinition fromId(RouteDefinition delegate, Endpoint endpoint) { + return delegate.from(endpoint).routeId(endpoint.getEndpointUri()); + } + + // Make common choice pattern more concise + + public static ProcessorDefinition<?> fork(ProcessorDefinition<?> delegate, String uri1, String uri2, Predicate predicate) { + return delegate.choice().when(predicate).to(uri1).otherwise().to(uri2); + } + +} +------------------------------------------------------------------------------------------------------------------------------- + +Add a corresponding extension module descriptor to `META-INF/services`: + +*META-INF/services/org.codehaus.groovy.runtime.ExtensionModule* + +[source,java] +---------------------------- +moduleName=my-extension +moduleVersion=2.11 +extensionClasses=MyExtension +staticExtensionClasses= +---------------------------- + +And now your Groovy route can look like this: + +*MyRoute.groovy* + +[source,java] +------------------------------------------------------------ +... + fromId('direct:test1') + .fork('direct:null','direct:not-null',body().isNull()) +... +------------------------------------------------------------ + +Using the plain Java DSL, the route would look something like this: + +*MyRoute.java* + +[source,java] +----------------------------------- +... + from("direct:test1") + .routeId("direct:test1") + .choice() + .when(body().isNull()) + .to("direct:null") + .otherwise() + .to("direct:not-null"); +... +----------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/GPathResultConverter.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/GPathResultConverter.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/GPathResultConverter.java new file mode 100644 index 0000000..fdf4971 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/GPathResultConverter.java @@ -0,0 +1,51 @@ +/** + * 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.groovy.converter; + +import java.io.IOException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import groovy.util.XmlSlurper; +import groovy.util.slurpersupport.GPathResult; +import org.apache.camel.Converter; +import org.apache.camel.Exchange; +import org.apache.camel.StringSource; +import org.apache.camel.converter.jaxp.XmlConverter; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +@Converter +public class GPathResultConverter { + + private final XmlConverter xmlConverter = new XmlConverter(); + + @Converter + public GPathResult fromString(String input) throws ParserConfigurationException, SAXException, IOException { + return new XmlSlurper().parseText(input); + } + + @Converter + public GPathResult fromStringSource(StringSource input) throws IOException, SAXException, ParserConfigurationException { + return fromString(input.getText()); + } + + @Converter + public GPathResult fromNode(Node input, Exchange exchange) throws IOException, SAXException, ParserConfigurationException, TransformerException { + return fromString(xmlConverter.toString(input, exchange)); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/TypeConverter.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/TypeConverter.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/TypeConverter.java new file mode 100644 index 0000000..d0bb945 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/converter/TypeConverter.java @@ -0,0 +1,83 @@ +/** + * 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.groovy.converter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; + +import groovy.lang.GString; +import org.apache.camel.Converter; +import org.apache.camel.Exchange; +import org.apache.camel.converter.IOConverter; +import org.apache.camel.converter.ObjectConverter; + +/** + * TypeConverter for Groovy GStrings. + */ +@Converter +public final class TypeConverter { + + private TypeConverter() { + + } + + @Converter + public static InputStream toInputStream(GString value, Exchange exchange) throws IOException { + return IOConverter.toInputStream(value.toString(), exchange); + } + + @Converter + public static byte[] toByteArray(GString value, Exchange exchange) throws IOException { + return IOConverter.toByteArray(value.toString(), exchange); + } + + @Converter + public static StringReader toReader(GString value) { + return IOConverter.toReader(value.toString()); + } + + @Converter + public static char toChar(GString value) { + return ObjectConverter.toChar(value.toString()); + } + + @Converter + public static Integer toInteger(GString value) { + return ObjectConverter.toInteger(value.toString()); + } + + @Converter + public static Long toLong(GString value) { + return ObjectConverter.toLong(value.toString()); + } + + @Converter + public static Float toFloat(GString value) { + return ObjectConverter.toFloat(value.toString()); + } + + @Converter + public static Double toDouble(GString value) { + return ObjectConverter.toDouble(value.toString()); + } + + @Converter + public static Boolean toBoolean(GString value) { + return ObjectConverter.toBoolean(value.toString()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/AbstractXmlDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/AbstractXmlDataFormat.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/AbstractXmlDataFormat.java new file mode 100644 index 0000000..b2b921e --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/AbstractXmlDataFormat.java @@ -0,0 +1,102 @@ +/** + * 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.groovy.dataformat; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import groovy.xml.FactorySupport; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.support.ServiceSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * Common attributes and methods for XmlParser and XmlSlurper usage. + */ +public abstract class AbstractXmlDataFormat extends ServiceSupport implements DataFormat { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractXmlDataFormat.class); + private static final ErrorHandler DEFAULT_HANDLER = new DefaultErrorHandler(); + + private boolean namespaceAware = true; + private boolean keepWhitespace; + private ErrorHandler errorHandler = DEFAULT_HANDLER; + + public AbstractXmlDataFormat(boolean namespaceAware) { + this.namespaceAware = namespaceAware; + } + + protected SAXParser newSaxParser() throws Exception { + SAXParserFactory factory = FactorySupport.createSaxParserFactory(); + factory.setNamespaceAware(namespaceAware); + factory.setValidating(false); + return factory.newSAXParser(); + } + + public ErrorHandler getErrorHandler() { + return errorHandler; + } + + public boolean isNamespaceAware() { + return namespaceAware; + } + + public void setNamespaceAware(boolean namespaceAware) { + this.namespaceAware = namespaceAware; + } + + public boolean isKeepWhitespace() { + return keepWhitespace; + } + + public void setKeepWhitespace(boolean keepWhitespace) { + this.keepWhitespace = keepWhitespace; + } + + private static class DefaultErrorHandler implements ErrorHandler { + + @Override + public void warning(SAXParseException exception) throws SAXException { + LOG.warn("Warning occured during parsing", exception); + } + + @Override + public void error(SAXParseException exception) throws SAXException { + throw new SAXException(exception); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + throw new SAXException(exception); + } + + } + + @Override + protected void doStart() throws Exception { + // noop + } + + @Override + protected void doStop() throws Exception { + // noop + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlParserDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlParserDataFormat.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlParserDataFormat.java new file mode 100644 index 0000000..44bf294 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlParserDataFormat.java @@ -0,0 +1,65 @@ +/** + * 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.groovy.dataformat; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; + +import groovy.util.Node; +import groovy.util.XmlNodePrinter; +import groovy.util.XmlParser; +import org.apache.camel.Exchange; + +/** + * DataFormat for using groovy.util.XmlParser as parser and renderer for XML + * data + */ +public class XmlParserDataFormat extends AbstractXmlDataFormat { + + public XmlParserDataFormat() { + this(true); + } + + public XmlParserDataFormat(boolean namespaceAware) { + super(namespaceAware); + } + + @Override + public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception { + newPrinter(stream).print((Node) graph); + } + + @Override + public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { + return newParser().parse(stream); + } + + private XmlParser newParser() throws Exception { + XmlParser xmlParser = new XmlParser(newSaxParser()); + xmlParser.setErrorHandler(getErrorHandler()); + xmlParser.setTrimWhitespace(!isKeepWhitespace()); + return xmlParser; + } + + private XmlNodePrinter newPrinter(OutputStream stream) { + XmlNodePrinter xmlNodePrinter = new XmlNodePrinter(new PrintWriter(stream)); + xmlNodePrinter.setNamespaceAware(isNamespaceAware()); + return xmlNodePrinter; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlSlurperDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlSlurperDataFormat.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlSlurperDataFormat.java new file mode 100644 index 0000000..6b8bb68 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/dataformat/XmlSlurperDataFormat.java @@ -0,0 +1,55 @@ +/** + * 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.groovy.dataformat; + +import java.io.InputStream; +import java.io.OutputStream; + +import groovy.util.XmlSlurper; +import org.apache.camel.Exchange; + +/** + * DataFormat for using groovy.util.XmlSlurper as parser for XML data + */ +public class XmlSlurperDataFormat extends AbstractXmlDataFormat { + + public XmlSlurperDataFormat() { + this(true); + } + + public XmlSlurperDataFormat(boolean namespaceAware) { + super(namespaceAware); + } + + @Override + public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception { + throw new UnsupportedOperationException("XmlSlurper does not support marshalling"); + } + + @Override + public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { + return newSlurper().parse(stream); + } + + private XmlSlurper newSlurper() throws Exception { + XmlSlurper slurper = new XmlSlurper(newSaxParser()); + slurper.setErrorHandler(getErrorHandler()); + slurper.setKeepWhitespace(isKeepWhitespace()); + return slurper; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/CamelGroovyMethods.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/CamelGroovyMethods.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/CamelGroovyMethods.java new file mode 100644 index 0000000..79e84ee --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/CamelGroovyMethods.java @@ -0,0 +1,383 @@ +/** + * 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.groovy.extend; + +import java.lang.reflect.Method; + +import groovy.lang.Closure; +import org.apache.camel.Exchange; +import org.apache.camel.Expression; +import org.apache.camel.Predicate; +import org.apache.camel.Processor; +import org.apache.camel.builder.DataFormatClause; +import org.apache.camel.builder.ExpressionClause; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.groovy.dataformat.XmlParserDataFormat; +import org.apache.camel.groovy.dataformat.XmlSlurperDataFormat; +import org.apache.camel.model.AggregateDefinition; +import org.apache.camel.model.CatchDefinition; +import org.apache.camel.model.ChoiceDefinition; +import org.apache.camel.model.DataFormatDefinition; +import org.apache.camel.model.DelayDefinition; +import org.apache.camel.model.DynamicRouterDefinition; +import org.apache.camel.model.FilterDefinition; +import org.apache.camel.model.IdempotentConsumerDefinition; +import org.apache.camel.model.InterceptDefinition; +import org.apache.camel.model.InterceptSendToEndpointDefinition; +import org.apache.camel.model.LoopDefinition; +import org.apache.camel.model.MulticastDefinition; +import org.apache.camel.model.OnCompletionDefinition; +import org.apache.camel.model.OnExceptionDefinition; +import org.apache.camel.model.ProcessorDefinition; +import org.apache.camel.model.RecipientListDefinition; +import org.apache.camel.model.ResequenceDefinition; +import org.apache.camel.model.RoutingSlipDefinition; +import org.apache.camel.model.SplitDefinition; +import org.apache.camel.model.ThrottleDefinition; +import org.apache.camel.model.TryDefinition; +import org.apache.camel.model.WireTapDefinition; +import org.apache.camel.processor.aggregate.AggregationStrategy; +import org.apache.camel.spi.IdempotentRepository; +import org.apache.camel.support.ExpressionSupport; + +/** + * Extension class containing static methods that mainly allow to use Closures + * instead of Predicates, Expressions, Processors, or AggregationStrategies + */ +public final class CamelGroovyMethods { + + private CamelGroovyMethods() { + // Utility Class + } + + // Extension Methods that use Closures to encapsulate logic + + public static ProcessorDefinition<?> process(ProcessorDefinition<?> self, + Closure<?> processorLogic) { + return self.process(toProcessor(processorLogic)); + } + + public WireTapDefinition<?> newExchange(WireTapDefinition<?> self, + Closure<?> processorLogic) { + return self.newExchange(toProcessor(processorLogic)); + } + + public static OnExceptionDefinition onRedelivery(OnExceptionDefinition self, + Closure<Exchange> processorLogic) { + return self.onRedelivery(toProcessor(processorLogic)); + } + + public static ProcessorDefinition<?> enrich(ProcessorDefinition<?> self, String resourceUri, + Closure<Exchange> aggregationLogic) { + return self.enrich(resourceUri, toAggregationStrategy(aggregationLogic)); + } + + public static ProcessorDefinition<?> pollEnrich(ProcessorDefinition<?> self, + String resourceUri, Closure<Exchange> aggregationLogic) { + return self.pollEnrich(resourceUri, toAggregationStrategy(aggregationLogic)); + } + + public static ProcessorDefinition<?> pollEnrich(ProcessorDefinition<?> self, + String resourceUri, long timeout, Closure<Exchange> aggregationLogic) { + return self.pollEnrich(resourceUri, timeout, toAggregationStrategy(aggregationLogic)); + } + + public static MulticastDefinition aggregationStrategy(MulticastDefinition self, + Closure<Exchange> aggregationLogic) { + return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); + } + + public static RecipientListDefinition<?> aggregationStrategy(RecipientListDefinition<?> self, + Closure<Exchange> aggregationLogic) { + return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); + } + + public static SplitDefinition aggregationStrategy(SplitDefinition self, + Closure<Exchange> aggregationLogic) { + return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); + } + + public static AggregateDefinition aggregationStrategy(AggregateDefinition self, + Closure<Exchange> aggregationLogic) { + return self.aggregationStrategy(toAggregationStrategy(aggregationLogic)); + } + + public static MulticastDefinition onPrepare(MulticastDefinition self, + Closure<Exchange> processorLogic) { + return self.onPrepare(toProcessor(processorLogic)); + } + + public static RecipientListDefinition<?> onPrepare(RecipientListDefinition<?> self, + Closure<Exchange> processorLogic) { + return self.onPrepare(toProcessor(processorLogic)); + } + + public static SplitDefinition onPrepare(SplitDefinition self, Closure<Exchange> processorLogic) { + return self.onPrepare(toProcessor(processorLogic)); + } + + public static WireTapDefinition<?> onPrepare(WireTapDefinition<?> self, + Closure<Exchange> processorLogic) { + return self.onPrepare(toProcessor(processorLogic)); + } + + // Extension Methods that use Closures as expressions + + public static ProcessorDefinition<?> script(ProcessorDefinition<?> self, + Closure<?> expression) { + return self.script(toExpression(expression)); + } + + public static ProcessorDefinition<?> transform(ProcessorDefinition<?> self, + Closure<?> expression) { + return self.transform(toExpression(expression)); + } + + public static ProcessorDefinition<?> setProperty(ProcessorDefinition<?> self, String name, + Closure<?> expression) { + return self.setProperty(name, toExpression(expression)); + } + + public static ProcessorDefinition<?> setHeader(ProcessorDefinition<?> self, String name, + Closure<?> expression) { + return self.setHeader(name, toExpression(expression)); + } + + public static ProcessorDefinition<?> setBody(ProcessorDefinition<?> self, Closure<?> expression) { + return self.setBody(toExpression(expression)); + } + + public static ProcessorDefinition<?> setFaultBody(ProcessorDefinition<?> self, + Closure<?> expression) { + return self.setFaultBody(toExpression(expression)); + } + + public static ProcessorDefinition<?> sort(ProcessorDefinition<?> self, Closure<?> expression) { + return self.sort(toExpression(expression)); + } + + public static IdempotentConsumerDefinition idempotentConsumer(ProcessorDefinition<?> self, + Closure<?> expression) { + return self.idempotentConsumer(toExpression(expression)); + } + + public static IdempotentConsumerDefinition idempotentConsumer(ProcessorDefinition<?> self, + IdempotentRepository<?> rep, Closure<?> expression) { + return self.idempotentConsumer(toExpression(expression), rep); + } + + public static RecipientListDefinition<?> recipientList(ProcessorDefinition<?> self, + Closure<?> recipients) { + return self.recipientList(toExpression(recipients)); + } + + public static RecipientListDefinition<?> recipientList(ProcessorDefinition<?> self, + String delimiter, Closure<?> recipients) { + return self.recipientList(toExpression(recipients), delimiter); + } + + public static RoutingSlipDefinition<?> routingSlip(ProcessorDefinition<?> self, + Closure<?> recipients) { + return self.routingSlip(toExpression(recipients)); + } + + public static RoutingSlipDefinition<?> routingSlip(ProcessorDefinition<?> self, + String delimiter, Closure<?> recipients) { + return self.routingSlip(toExpression(recipients), delimiter); + } + + public static DynamicRouterDefinition<?> dynamicRouter(ProcessorDefinition<?> self, + Closure<?> expression) { + return self.dynamicRouter(toExpression(expression)); + } + + public static SplitDefinition split(ProcessorDefinition<?> self, Closure<?> expression) { + return self.split(toExpression(expression)); + } + + public static ResequenceDefinition resequence(ProcessorDefinition<?> self, Closure<?> expression) { + return self.resequence(toExpression(expression)); + } + + public static AggregateDefinition aggregate(ProcessorDefinition<?> self, + Closure<?> correlationExpression) { + return self.aggregate(toExpression(correlationExpression)); + } + + public static AggregateDefinition completionSize(AggregateDefinition self, Closure<?> expression) { + return self.completionSize(toExpression(expression)); + } + + public static AggregateDefinition completionTimeout(AggregateDefinition self, + Closure<?> expression) { + return self.completionTimeout(toExpression(expression)); + } + + public static DelayDefinition delay(ProcessorDefinition<?> self, Closure<?> expression) { + return self.delay(toExpression(expression)); + } + + public static ThrottleDefinition throttle(ProcessorDefinition<?> self, Closure<?> expression) { + return self.throttle(toExpression(expression)); + } + + public static LoopDefinition loop(ProcessorDefinition<?> self, Closure<?> expression) { + return self.loop(toExpression(expression)); + } + + public static WireTapDefinition<?> newExchangeBody(WireTapDefinition<?> self, + Closure<?> expression) { + return self.newExchangeBody(toExpression(expression)); + } + + public static WireTapDefinition<?> newExchangeHeader(WireTapDefinition<?> self, String header, + Closure<?> expression) { + return self.newExchangeHeader(header, toExpression(expression)); + } + + // Extension Methods that use Closures as predicates + + public static FilterDefinition filter(ProcessorDefinition<?> self, Closure<?> predicate) { + return self.filter(toExpression(predicate)); + } + + public static ProcessorDefinition<?> validate(ProcessorDefinition<?> self, Closure<?> predicate) { + return self.validate((Predicate) toExpression(predicate)); + } + + public static ChoiceDefinition when(ChoiceDefinition self, Closure<?> predicate) { + return self.when(toExpression(predicate)); + } + + public static TryDefinition onWhen(TryDefinition self, Closure<?> predicate) { + return self.onWhen(toExpression(predicate)); + } + + public static OnExceptionDefinition onWhen(OnExceptionDefinition self, Closure<?> predicate) { + return self.onWhen(toExpression(predicate)); + } + + public static OnExceptionDefinition handled(OnExceptionDefinition self, Closure<?> predicate) { + return self.handled((Predicate) toExpression(predicate)); + } + + public static OnExceptionDefinition continued(OnExceptionDefinition self, Closure<?> predicate) { + return self.continued((Predicate) toExpression(predicate)); + } + + public static OnExceptionDefinition retryWhile(OnExceptionDefinition self, Closure<?> predicate) { + return self.retryWhile(toExpression(predicate)); + } + + public static OnCompletionDefinition onWhen(OnCompletionDefinition self, Closure<?> predicate) { + return self.onWhen(toExpression(predicate)); + } + + public static CatchDefinition onWhen(CatchDefinition self, Closure<?> predicate) { + return self.onWhen(toExpression(predicate)); + } + + public static AggregateDefinition completionPredicate(AggregateDefinition self, + Closure<?> predicate) { + return self.completionPredicate(toExpression(predicate)); + } + + public static InterceptDefinition when(InterceptDefinition self, Closure<?> predicate) { + return self.when(toExpression(predicate)); + } + + public static InterceptSendToEndpointDefinition when(InterceptSendToEndpointDefinition self, + Closure<?> predicate) { + return self.when(toExpression(predicate)); + } + + // Bridging generic attribution of expressions, predicates etc. + + public static AggregationStrategy aggregator(RouteBuilder self, + Closure<Exchange> aggregationLogic) { + return toAggregationStrategy(aggregationLogic); + } + + public static Expression expression(RouteBuilder self, Closure<?> expression) { + return toExpression(expression); + } + + public static Predicate predicate(RouteBuilder self, Closure<?> predicate) { + return toExpression(predicate); + } + + public static Processor processor(RouteBuilder self, Closure<Exchange> processor) { + return toProcessor(processor); + } + + public static <T> T expression(ExpressionClause<T> self, Closure<?> expression) { + return self.expression(toExpression(expression)); + } + + // Private Helpers + + static ExpressionSupport toExpression(final Closure<?> closure) { + return new ClosureExpression(closure); + } + + static Processor toProcessor(final Closure<?> closure) { + return new ClosureProcessor(closure); + } + + static AggregationStrategy toAggregationStrategy(final Closure<Exchange> closure) { + return new ClosureAggregationStrategy(closure); + } + + // Groovy-specific data formats + + public static ProcessorDefinition<?> gnode(DataFormatClause<?> self, boolean namespaceAware) { + return dataFormat(self, parser(namespaceAware)); + } + + public static ProcessorDefinition<?> gnode(DataFormatClause<?> self) { + return gnode(self, true); + } + + public static ProcessorDefinition<?> gpath(DataFormatClause<?> self, boolean namespaceAware) { + return dataFormat(self, slurper(namespaceAware)); + } + + public static ProcessorDefinition<?> gpath(DataFormatClause<?> self) { + return gpath(self, true); + } + + private static DataFormatDefinition slurper(boolean namespaceAware) { + return new DataFormatDefinition(new XmlSlurperDataFormat(namespaceAware)); + } + + private static DataFormatDefinition parser(boolean namespaceAware) { + return new DataFormatDefinition(new XmlParserDataFormat(namespaceAware)); + } + + // DataFormatClause.dataFormat(DataFormatDefinition) is private... + private static ProcessorDefinition<?> dataFormat(DataFormatClause<?> self, + DataFormatDefinition format) { + try { + Method m = self.getClass().getDeclaredMethod("dataFormat", DataFormatDefinition.class); + m.setAccessible(true); + return (ProcessorDefinition<?>) m.invoke(self, format); + } catch (Exception e) { + throw new IllegalArgumentException("Unknown DataFormat operation", e); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureAggregationStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureAggregationStrategy.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureAggregationStrategy.java new file mode 100644 index 0000000..c290db8 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureAggregationStrategy.java @@ -0,0 +1,37 @@ +/** + * 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.groovy.extend; + +import groovy.lang.Closure; + +import org.apache.camel.Exchange; +import org.apache.camel.processor.aggregate.AggregationStrategy; + +class ClosureAggregationStrategy implements AggregationStrategy { + + private final Closure<Exchange> closure; + + ClosureAggregationStrategy(Closure<Exchange> closure) { + this.closure = closure; + } + + @Override + public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { + return ClosureSupport.call(closure, oldExchange, newExchange); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureExpression.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureExpression.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureExpression.java new file mode 100644 index 0000000..1309b7c --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureExpression.java @@ -0,0 +1,46 @@ +/** + * 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.groovy.extend; + +import groovy.lang.Closure; + +import org.apache.camel.Exchange; +import org.apache.camel.support.ExpressionSupport; + +/** + * Bridges a closure to ExpressionSupport + */ +class ClosureExpression extends ExpressionSupport { + + private final Closure<?> closure; + + ClosureExpression(Closure<?> closure) { + this.closure = closure; + } + + @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + Object result = ClosureSupport.call(closure, exchange); + return exchange.getContext().getTypeConverter().convertTo(type, result); + } + + @Override + protected String assertionFailureMessage(Exchange exchange) { + return closure.toString(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureProcessor.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureProcessor.java new file mode 100644 index 0000000..415543f --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureProcessor.java @@ -0,0 +1,40 @@ +/** + * 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.groovy.extend; + +import groovy.lang.Closure; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +/** + * Bridges a Closure to a Processor + */ +class ClosureProcessor implements Processor { + + private final Closure<?> closure; + + ClosureProcessor(Closure<?> closure) { + this.closure = closure; + } + + @Override + public void process(Exchange exchange) throws Exception { + ClosureSupport.call(closure, exchange); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureSupport.java b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureSupport.java new file mode 100644 index 0000000..be60ed2 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/java/org/apache/camel/groovy/extend/ClosureSupport.java @@ -0,0 +1,39 @@ +/** + * 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.groovy.extend; + +import groovy.lang.Closure; + +import org.codehaus.groovy.runtime.InvokerInvocationException; + +final class ClosureSupport { + + private ClosureSupport() { + } + + static <T> T call(Closure<T> closure, Object... args) { + try { + return closure.call(args); + } catch (InvokerInvocationException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } else { + throw e; + } + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/resources/META-INF/LICENSE.txt ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/resources/META-INF/LICENSE.txt b/components/camel-groovy-dsl/src/main/resources/META-INF/LICENSE.txt new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/components/camel-groovy-dsl/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/2a198c2f/components/camel-groovy-dsl/src/main/resources/META-INF/NOTICE.txt ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/resources/META-INF/NOTICE.txt b/components/camel-groovy-dsl/src/main/resources/META-INF/NOTICE.txt new file mode 100644 index 0000000..2e215bf --- /dev/null +++ b/components/camel-groovy-dsl/src/main/resources/META-INF/NOTICE.txt @@ -0,0 +1,11 @@ + ========================================================================= + == 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/). + + Please read the different LICENSE files present in the licenses directory of + this distribution. http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/resources/META-INF/services/camel/TypeConverter ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/resources/META-INF/services/camel/TypeConverter b/components/camel-groovy-dsl/src/main/resources/META-INF/services/camel/TypeConverter new file mode 100644 index 0000000..8a0e315 --- /dev/null +++ b/components/camel-groovy-dsl/src/main/resources/META-INF/services/camel/TypeConverter @@ -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. +# +org.apache.camel.groovy.converter.TypeConverter +org.apache.camel.groovy.converter.GPathResultConverter \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/resources/META-INF/services/groovy/groovyMethods ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/resources/META-INF/services/groovy/groovyMethods b/components/camel-groovy-dsl/src/main/resources/META-INF/services/groovy/groovyMethods new file mode 100644 index 0000000..7043aed --- /dev/null +++ b/components/camel-groovy-dsl/src/main/resources/META-INF/services/groovy/groovyMethods @@ -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. +# + +org.apache.camel.language.groovy.CamelGroovyMethods \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/2a198c2f/components/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule ---------------------------------------------------------------------- diff --git a/components/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule b/components/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule new file mode 100644 index 0000000..10db1bc --- /dev/null +++ b/components/camel-groovy-dsl/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule @@ -0,0 +1,20 @@ +# +# 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. +# +moduleName=camel-groovy +moduleVersion=2.15 +extensionClasses=org.apache.camel.groovy.extend.CamelGroovyMethods +staticExtensionClasses= \ No newline at end of file