Author: davsclaus
Date: Wed Nov 28 17:42:35 2012
New Revision: 1414836
URL: http://svn.apache.org/viewvc?rev=1414836&view=rev
Log:
CAMEL-5826: Fixed issue with XML streaming tokenizer dealing with inheriting
namespaces from parent tag. Thanks to Rich Newcomb for the patch.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
(with props)
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java?rev=1414836&r1=1414835&r2=1414836&view=diff
==============================================================================
---
camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
(original)
+++
camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java
Wed Nov 28 17:42:35 2012
@@ -41,6 +41,7 @@ public class TokenXMLPairExpressionItera
private static final Pattern NAMESPACE_PATTERN =
Pattern.compile("xmlns(:\\w+|)=\\\"(.*?)\\\"");
private static final String SCAN_TOKEN_REGEX = "(\\s+.*?|)>";
+ private static final String SCAN_TOKEN_NS_PREFIX_REGEX = "(.{1,15}?:|)";
protected final String inheritNamespaceToken;
public TokenXMLPairExpressionIterator(String startToken, String endToken,
String inheritNamespaceToken) {
@@ -81,15 +82,22 @@ public class TokenXMLPairExpressionItera
XMLTokenPairIterator(String startToken, String endToken, String
inheritNamespaceToken, InputStream in, String charset) {
super(startToken, endToken, true, in, charset);
- // remove any ending > as we need to support attributes on the
tags, so we need to use a reg exp pattern
- String token = startToken.substring(0, startToken.length() - 1) +
SCAN_TOKEN_REGEX;
- this.startTokenPattern = Pattern.compile(token);
- this.scanEndToken = endToken.substring(0, endToken.length() - 1) +
SCAN_TOKEN_REGEX;
+ // remove any beginning < and ending > as we need to support ns
prefixes and attributes, so we use a reg exp patterns
+ StringBuilder tokenSb = new
StringBuilder("<").append(SCAN_TOKEN_NS_PREFIX_REGEX).
+ append(startToken.substring(1,
startToken.length() - 1)).append(SCAN_TOKEN_REGEX);
+ this.startTokenPattern = Pattern.compile(tokenSb.toString());
+
+ tokenSb = new
StringBuilder("</").append(SCAN_TOKEN_NS_PREFIX_REGEX).
+ append(endToken.substring(2, endToken.length()
- 1)).append(SCAN_TOKEN_REGEX);
+ this.scanEndToken = tokenSb.toString();
+
this.inheritNamespaceToken = inheritNamespaceToken;
if (inheritNamespaceToken != null) {
- token = inheritNamespaceToken.substring(0,
inheritNamespaceToken.length() - 1) + SCAN_TOKEN_REGEX;
+ // the inherit namespace token may itself have a namespace
prefix
+ tokenSb = new
StringBuilder("<").append(SCAN_TOKEN_NS_PREFIX_REGEX).
+ append(inheritNamespaceToken.substring(1,
inheritNamespaceToken.length() - 1)).append(SCAN_TOKEN_REGEX);
// the namespaces on the parent tag can be in multi line, so
we need to instruct the dot to support multilines
- this.inheritNamespaceTokenPattern = Pattern.compile(token,
Pattern.MULTILINE | Pattern.DOTALL);
+ this.inheritNamespaceTokenPattern =
Pattern.compile(tokenSb.toString(), Pattern.MULTILINE | Pattern.DOTALL);
}
}
@@ -125,17 +133,26 @@ public class TokenXMLPairExpressionItera
next = next.substring(index);
}
+ // make sure the end tag matches the begin tag if the tag has a
namespace prefix
+ String tag = ObjectHelper.before(next, ">");
+ StringBuilder endTagSb = new StringBuilder("</");
+ int firstSpaceIndex = tag.indexOf(" ");
+ if (firstSpaceIndex > 0) {
+ endTagSb.append(tag.substring(1, firstSpaceIndex)).append(">");
+ } else {
+ endTagSb.append(tag.substring(1, tag.length())).append(">");
+ }
+
// build answer accordingly to whether namespaces should be
inherited or not
StringBuilder sb = new StringBuilder();
if (inheritNamespaceToken != null && rootTokenNamespaces != null) {
// append root namespaces to local start token
- String tag = ObjectHelper.before(next, ">");
// grab the text
String text = ObjectHelper.after(next, ">");
// build result with inherited namespaces
- next =
sb.append(tag).append(rootTokenNamespaces).append(">").append(text).append(endToken).toString();
+ next =
sb.append(tag).append(rootTokenNamespaces).append(">").append(text).append(endTagSb.toString()).toString();
} else {
- next = sb.append(next).append(endToken).toString();
+ next = sb.append(next).append(endTagSb.toString()).toString();
}
return next;
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java?rev=1414836&view=auto
==============================================================================
---
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
(added)
+++
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
Wed Nov 28 17:42:35 2012
@@ -0,0 +1,84 @@
+/**
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class SplitTokenizerNamespaceTest extends ContextTestSupport {
+
+ public void testSplitTokenizerWithImplicitNamespaces() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:split");
+
+ // we expect to receive results that have namespace definitions on
each token
+ // we could receive nodes from multiple namespaces since we did not
specify a namespace prefix,
+ mock.expectedBodiesReceived(
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">Claus</ns1:person>",
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">James</ns1:person>",
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">Willem</ns1:person>",
+ "<ns2:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">Rich</ns2:person>");
+
+ template.sendBody("direct:noPrefix", getXmlBody());
+
+ assertMockEndpointsSatisfied();
+ }
+
+ public void testSplitTokenizerWithExplicitNamespaces() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:split");
+
+ // we expect to receive results that have namespace definitions on
each token
+ // we provided an explicit namespace prefix value in the route, so we
will only receive nodes that have a matching prefix value
+ mock.expectedBodiesReceived(
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">Claus</ns1:person>",
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">James</ns1:person>",
+ "<ns1:person xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">Willem</ns1:person>");
+
+ template.sendBody("direct:explicitPrefix", getXmlBody());
+
+ assertMockEndpointsSatisfied();
+ }
+
+ protected String getXmlBody() {
+ StringBuilder sb = new StringBuilder("<?xml version=\"1.0\"?>\n");
+ sb.append("<ns1:persons xmlns:ns1=\"urn:org.apache.camel\"
xmlns:ns2=\"urn:org.apache.cameltoo\">\n");
+ sb.append(" <ns1:person>Claus</ns1:person>\n");
+ sb.append(" <ns1:person>James</ns1:person>\n");
+ sb.append(" <ns1:person>Willem</ns1:person>\n");
+ sb.append(" <ns2:person>Rich</ns2:person>\n");
+ sb.append("</ns1:persons>");
+ return sb.toString();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+
+ from("direct:noPrefix")
+ .split().tokenizeXML("person", "persons")
+ .to("mock:split");
+
+ from("direct:explicitPrefix")
+ .split().tokenizeXML("ns1:person", "ns1:persons")
+ .to("mock:split");
+ }
+ };
+ }
+
+}
\ No newline at end of file
Propchange:
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/SplitTokenizerNamespaceTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date