Updated Branches: refs/heads/master 720e09dc9 -> 6c3f812a5
[CAMEL-6389] Add a mvel templating component along with the mvel expression language Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/6c3f812a Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/6c3f812a Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/6c3f812a Branch: refs/heads/master Commit: 6c3f812a5ee5f7751695cdac3d6ea2bafab35da3 Parents: 720e09d Author: Guillaume Nodet <gno...@gmail.com> Authored: Thu May 23 11:31:02 2013 +0200 Committer: Guillaume Nodet <gno...@gmail.com> Committed: Thu May 23 11:33:13 2013 +0200 ---------------------------------------------------------------------- .../apache/camel/language/mvel/MvelComponent.java | 51 ++++++ .../apache/camel/language/mvel/MvelConstants.java | 31 ++++ .../apache/camel/language/mvel/MvelEndpoint.java | 130 +++++++++++++++ .../services/org/apache/camel/component/mvel | 18 ++ .../camel/language/mvel/MvelComponentTest.java | 78 +++++++++ .../camel-mvel/src/test/resources/template.mvel | 1 + .../camel-mvel/src/test/resources/template2.mvel | 1 + 7 files changed, 310 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelComponent.java b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelComponent.java new file mode 100644 index 0000000..02ae9cd --- /dev/null +++ b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelComponent.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.language.mvel; + +import org.apache.camel.Endpoint; +import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ResourceHelper; + +import java.util.Map; + +/** + * An <a href="http://camel.apache.org/mvel.html">Mvel Component</a> + * for performing transforming messages + */ +public class MvelComponent extends DefaultComponent { + + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + String encoding = getAndRemoveParameter(parameters, "encoding", String.class); + boolean cache = getAndRemoveParameter(parameters, "contentCache", Boolean.class, Boolean.TRUE); + + MvelEndpoint answer = new MvelEndpoint(uri, this, remaining); + answer.setContentCache(cache); + if (ObjectHelper.isNotEmpty(encoding)) { + answer.setEncoding(encoding); + } + + // if its a http resource then append any remaining parameters and update the resource uri + if (ResourceHelper.isHttpUri(remaining)) { + remaining = ResourceHelper.appendParameters(remaining, parameters); + answer.setResourceUri(remaining); + } + + return answer; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelConstants.java ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelConstants.java b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelConstants.java new file mode 100644 index 0000000..acb0dde --- /dev/null +++ b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelConstants.java @@ -0,0 +1,31 @@ +/** + * 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.language.mvel; + +/** + * Mvel constants + */ +public final class MvelConstants { + + public static final String MVEL_RESOURCE_URI = "CamelMvelResourceUri"; + + public static final String MVEL_TEMPLATE = "CamelMvelTemplate"; + + private MvelConstants() { + // Utility class + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelEndpoint.java b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelEndpoint.java new file mode 100644 index 0000000..defd2e6 --- /dev/null +++ b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelEndpoint.java @@ -0,0 +1,130 @@ +/** + * 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.language.mvel; + +import org.apache.camel.Exchange; +import org.apache.camel.ExchangePattern; +import org.apache.camel.Message; +import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.converter.IOConverter; +import org.apache.camel.util.ExchangeHelper; +import org.apache.camel.util.ObjectHelper; +import org.mvel2.ParserContext; +import org.mvel2.templates.CompiledTemplate; +import org.mvel2.templates.TemplateCompiler; +import org.mvel2.templates.TemplateRuntime; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +public class MvelEndpoint extends ResourceEndpoint { + + private String encoding; + private String template; + private CompiledTemplate compiled; + + public MvelEndpoint(String uri, MvelComponent component, String resourceUri) { + super(uri, component, resourceUri); + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public ExchangePattern getExchangePattern() { + return ExchangePattern.InOut; + } + + @Override + protected String createEndpointUri() { + return "mvel:" + getResourceUri(); + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + @Override + protected void onExchange(Exchange exchange) throws Exception { + String path = getResourceUri(); + ObjectHelper.notNull(path, "resourceUri"); + + String newResourceUri = exchange.getIn().getHeader(MvelConstants.MVEL_RESOURCE_URI, String.class); + if (newResourceUri != null) { + exchange.getIn().removeHeader(MvelConstants.MVEL_RESOURCE_URI); + + log.debug("{} set to {} creating new endpoint to handle exchange", MvelConstants.MVEL_RESOURCE_URI, newResourceUri); + MvelEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri); + newEndpoint.onExchange(exchange); + return; + } + + CompiledTemplate compiled; + ParserContext mvelContext = ParserContext.create(); + Map<String, Object> variableMap = ExchangeHelper.createVariableMap(exchange); + + String content = exchange.getIn().getHeader(MvelConstants.MVEL_TEMPLATE, String.class); + if (content != null) { + // use content from header + if (log.isDebugEnabled()) { + log.debug("Mvel content read from header {} for endpoint {}", MvelConstants.MVEL_TEMPLATE, getEndpointUri()); + } + // remove the header to avoid it being propagated in the routing + exchange.getIn().removeHeader(MvelConstants.MVEL_TEMPLATE); + compiled = TemplateCompiler.compileTemplate(content, mvelContext); + } else { + if (log.isDebugEnabled()) { + log.debug("Mvel content read from resource {} with resourceUri: {} for endpoint {}", new Object[]{getResourceUri(), path, getEndpointUri()}); + } + // getResourceAsInputStream also considers the content cache + Reader reader = getEncoding() != null ? new InputStreamReader(getResourceAsInputStream(), getEncoding()) : new InputStreamReader(getResourceAsInputStream()); + String template = IOConverter.toString(reader); + if (!template.equals(this.template)) { + this.template = template; + this.compiled = TemplateCompiler.compileTemplate(template, mvelContext); + } + compiled = this.compiled; + } + + // let mvel parse and execute the template + log.debug("Mvel is evaluating using mvel context: {}", variableMap); + Object result = TemplateRuntime.execute(compiled, mvelContext, variableMap); + + // now lets output the results to the exchange + Message out = exchange.getOut(); + out.setBody(result.toString()); + out.setHeaders(exchange.getIn().getHeaders()); + out.setAttachments(exchange.getIn().getAttachments()); + } + + public MvelEndpoint findOrCreateEndpoint(String uri, String newResourceUri) { + String newUri = uri.replace(getResourceUri(), newResourceUri); + log.debug("Getting endpoint with URI: {}", newUri); + return getCamelContext().getEndpoint(newUri, MvelEndpoint.class); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/main/resources/META-INF/services/org/apache/camel/component/mvel ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/main/resources/META-INF/services/org/apache/camel/component/mvel b/components/camel-mvel/src/main/resources/META-INF/services/org/apache/camel/component/mvel new file mode 100644 index 0000000..027426c --- /dev/null +++ b/components/camel-mvel/src/main/resources/META-INF/services/org/apache/camel/component/mvel @@ -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.language.mvel.MvelComponent \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/test/java/org/apache/camel/language/mvel/MvelComponentTest.java ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/test/java/org/apache/camel/language/mvel/MvelComponentTest.java b/components/camel-mvel/src/test/java/org/apache/camel/language/mvel/MvelComponentTest.java new file mode 100644 index 0000000..996ae6f --- /dev/null +++ b/components/camel-mvel/src/test/java/org/apache/camel/language/mvel/MvelComponentTest.java @@ -0,0 +1,78 @@ +/** + * 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.language.mvel; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +/** + * + */ +public class MvelComponentTest extends CamelTestSupport { + + @Test + public void testMvel() throws Exception { + Exchange exchange = template.request("direct:a", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody(7); + } + }); + + assertEquals("{ \"text\": \"The result is 14\" }", exchange.getOut().getBody()); + } + + @Test + public void testMvelTemplate() throws Exception { + Exchange exchange = template.request("direct:a", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody(7); + exchange.getIn().setHeader(MvelConstants.MVEL_TEMPLATE, "{ \"text\": \"@{\"The result is \" + request.body * 3}\" }"); + } + }); + + assertEquals("{ \"text\": \"The result is 21\" }", exchange.getOut().getBody()); + } + + @Test + public void testMvelUri() throws Exception { + Exchange exchange = template.request("direct:a", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setBody(7); + exchange.getIn().setHeader(MvelConstants.MVEL_RESOURCE_URI, getClass().getClassLoader().getResource("template2.mvel").toURI().toString()); + } + }); + + assertEquals("{ \"text\": \"The result is 28\" }", exchange.getOut().getBody()); + } + + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + // START SNIPPET: example + from("direct:a"). + to("mvel:template.mvel"); + // END SNIPPET: example + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/test/resources/template.mvel ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/test/resources/template.mvel b/components/camel-mvel/src/test/resources/template.mvel new file mode 100644 index 0000000..84be224 --- /dev/null +++ b/components/camel-mvel/src/test/resources/template.mvel @@ -0,0 +1 @@ +{ "text": "@{"The result is " + request.body * 2}" } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/6c3f812a/components/camel-mvel/src/test/resources/template2.mvel ---------------------------------------------------------------------- diff --git a/components/camel-mvel/src/test/resources/template2.mvel b/components/camel-mvel/src/test/resources/template2.mvel new file mode 100644 index 0000000..fd89eeb --- /dev/null +++ b/components/camel-mvel/src/test/resources/template2.mvel @@ -0,0 +1 @@ +{ "text": "@{"The result is " + request.body * 4}" } \ No newline at end of file