Repository: camel Updated Branches: refs/heads/CAMEL-10509 [created] 4ccf30dd5
CAMEL-10509: dump model to xml should include namespaces. Work in progress. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/4ccf30dd Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/4ccf30dd Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/4ccf30dd Branch: refs/heads/CAMEL-10509 Commit: 4ccf30dd59ff54ee15c3292aefa6456046a38691 Parents: 74a6d41 Author: Claus Ibsen <davscl...@apache.org> Authored: Wed Nov 23 14:22:52 2016 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Wed Nov 23 14:22:52 2016 +0100 ---------------------------------------------------------------------- .../builder/xml/DefaultNamespaceContext.java | 4 ++ .../apache/camel/builder/xml/XPathBuilder.java | 4 ++ .../org/apache/camel/model/ModelHelper.java | 58 ++++++++++++++++++++ .../model/dataformat/XMLSecurityDataFormat.java | 6 +- .../org/apache/camel/spi/NamespaceAware.java | 5 ++ .../support/XMLTokenExpressionIterator.java | 5 ++ .../util/DumpModelAsXmlAggregateRouteTest.java | 2 +- .../camel/util/DumpModelAsXmlNamespaceTest.java | 46 ++++++++++++++++ .../camel/component/xquery/XQueryBuilder.java | 4 ++ 9 files changed, 132 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java b/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java index 63cedd2..8555e1c 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java +++ b/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java @@ -99,6 +99,10 @@ public class DefaultNamespaceContext implements NamespaceContext, NamespaceAware map.putAll(namespaces); } + public Map<String, String> getNamespaces() { + return map; + } + /** * toString() implementation that outputs the namespace mappings with the following format: "[me: {prefix -> value}, {prefix -> value}], [parent: {prefix -> value}, {prefix -> value}]. * Recurses up the parent's chain. http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java index 932d1ce..dc7ffb3 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java @@ -524,6 +524,10 @@ public class XPathBuilder extends ServiceSupport implements Expression, Predicat this.namespaces.putAll(namespaces); } + public Map<String, String> getNamespaces() { + return namespaces; + } + /** * Gets the {@link XPathFunction} for getting the input message body. * <p/> http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java b/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java index 801d2a0..3a1aa68 100644 --- a/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java +++ b/camel-core/src/main/java/org/apache/camel/model/ModelHelper.java @@ -19,15 +19,24 @@ package org.apache.camel.model; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.apache.camel.CamelContext; +import org.apache.camel.Expression; import org.apache.camel.NamedNode; +import org.apache.camel.model.language.ExpressionDefinition; +import org.apache.camel.spi.NamespaceAware; import org.apache.camel.util.IOHelper; +import static org.apache.camel.model.ProcessorDefinitionHelper.filterTypeInOutputs; + /** * Helper for the Camel {@link org.apache.camel.model model} classes. */ @@ -53,6 +62,21 @@ public final class ModelHelper { jaxbContext = context.getModelJAXBContextFactory().newJAXBContext(); } + final Map<String, String> namespaces = new LinkedHashMap<>(); + + // gather all namespaces from the routes or route which is stored on the expression nodes + if (definition instanceof RoutesDefinition) { + List<RouteDefinition> routes = ((RoutesDefinition) definition).getRoutes(); + for (RouteDefinition route : routes) { + extractNamespaces(route, namespaces); + } + } else if (definition instanceof RouteDefinition) { + RouteDefinition route = (RouteDefinition) definition; + extractNamespaces(route, namespaces); + } + + // TODO: add all namespaces to the root node so the xml output includes those + Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); StringWriter buffer = new StringWriter(); @@ -71,6 +95,8 @@ public final class ModelHelper { * @throws javax.xml.bind.JAXBException is thrown if error unmarshalling from xml to model */ public static <T extends NamedNode> T createModelFromXml(CamelContext context, String xml, Class<T> type) throws JAXBException { + // TODO: support injecting namespaces into each namespace aware node + JAXBContext jaxbContext; if (context == null) { jaxbContext = createJAXBContext(); @@ -103,6 +129,8 @@ public final class ModelHelper { * @throws javax.xml.bind.JAXBException is thrown if error unmarshalling from xml to model */ public static <T extends NamedNode> T createModelFromXml(CamelContext context, InputStream stream, Class<T> type) throws JAXBException { + // TODO: support injecting namespaces into each namespace aware node + JAXBContext jaxbContext; if (context == null) { jaxbContext = createJAXBContext(); @@ -119,4 +147,34 @@ public final class ModelHelper { // must use classloader from CamelContext to have JAXB working return JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader()); } + + /** + * Extract all XML namespaces from the expressions in the route + * + * @param route the route + * @param namespaces the map of namespace to add new found XML namespaces + */ + private static void extractNamespaces(RouteDefinition route, Map<String, String> namespaces) { + Iterator<ExpressionNode> it = filterTypeInOutputs(route.getOutputs(), ExpressionNode.class); + while (it.hasNext()) { + ExpressionNode en = it.next(); + ExpressionDefinition ed = en.getExpression(); + + // java-dsl sets directly expression so try this first + NamespaceAware na = null; + Expression exp = ed.getExpressionValue(); + if (exp != null && exp instanceof NamespaceAware) { + na = (NamespaceAware) exp; + } else if (ed instanceof NamespaceAware) { + na = (NamespaceAware) ed; + } + + if (na != null) { + Map<String, String> map = na.getNamespaces(); + if (map != null && !map.isEmpty()) { + namespaces.putAll(map); + } + } + } + } } http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/model/dataformat/XMLSecurityDataFormat.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/XMLSecurityDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/XMLSecurityDataFormat.java index 78f6b8b..33d2994 100644 --- a/camel-core/src/main/java/org/apache/camel/model/dataformat/XMLSecurityDataFormat.java +++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/XMLSecurityDataFormat.java @@ -475,5 +475,9 @@ public class XMLSecurityDataFormat extends DataFormatDefinition implements Names } this.namespaces.putAll(nspaces); } - + + @Override + public Map<String, String> getNamespaces() { + return namespaces; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/spi/NamespaceAware.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/NamespaceAware.java b/camel-core/src/main/java/org/apache/camel/spi/NamespaceAware.java index 3e79e1f..f3f2f46 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/NamespaceAware.java +++ b/camel-core/src/main/java/org/apache/camel/spi/NamespaceAware.java @@ -32,4 +32,9 @@ public interface NamespaceAware { * @param namespaces the XML namespaces with the key of prefixes and the value the URIs */ void setNamespaces(Map<String, String> namespaces); + + /** + * Gets the XML Namespaces + */ + Map<String, String> getNamespaces(); } http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/main/java/org/apache/camel/support/XMLTokenExpressionIterator.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/support/XMLTokenExpressionIterator.java b/camel-core/src/main/java/org/apache/camel/support/XMLTokenExpressionIterator.java index 725ee6b..45f9293 100644 --- a/camel-core/src/main/java/org/apache/camel/support/XMLTokenExpressionIterator.java +++ b/camel-core/src/main/java/org/apache/camel/support/XMLTokenExpressionIterator.java @@ -72,6 +72,11 @@ public class XMLTokenExpressionIterator extends ExpressionAdapter implements Nam this.nsmap = nsmap; } + @Override + public Map<String, String> getNamespaces() { + return nsmap; + } + public void setMode(char mode) { this.mode = mode; } http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlAggregateRouteTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlAggregateRouteTest.java b/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlAggregateRouteTest.java index f172942..3369443 100644 --- a/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlAggregateRouteTest.java +++ b/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlAggregateRouteTest.java @@ -44,7 +44,7 @@ public class DumpModelAsXmlAggregateRouteTest extends ContextTestSupport { from("direct:start").routeId("myRoute") .to("log:input") .aggregate(header("userId"), new GroupedExchangeAggregationStrategy()).completionSize(3) - .to("mock:aggregate") + .to("mock:aggregate") .end() .to("mock:result"); } http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlNamespaceTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlNamespaceTest.java b/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlNamespaceTest.java new file mode 100644 index 0000000..3216da37 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/util/DumpModelAsXmlNamespaceTest.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.util; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.ModelHelper; + +/** + * + */ +public class DumpModelAsXmlNamespaceTest extends ContextTestSupport { + + public void testDumpModelAsXml() throws Exception { + String xml = ModelHelper.dumpModelAsXml(context, context.getRouteDefinition("myRoute")); + assertNotNull(xml); + log.info(xml); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start").routeId("myRoute") + .choice() + .when(xpath("/foo:customer").namespace("foo", "http://foo.com")).to("mock:foo") + .when(xpath("/bar:customer").namespace("bar", "http://bar.com")).to("mock:bar"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/4ccf30dd/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java ---------------------------------------------------------------------- diff --git a/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java b/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java index 0f9eff1..29ed896 100644 --- a/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java +++ b/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java @@ -367,6 +367,10 @@ public abstract class XQueryBuilder implements Expression, Predicate, NamespaceA initialized.set(false); } + public Map<String, String> getNamespaces() { + return namespacePrefixes; + } + public XQueryExpression getExpression() throws IOException, XPathException { return expression; }