You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/01/15 16:12:11 UTC
[camel] 05/07: [CAMEL-14404] Provide a lightweight xml parser
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8a8431c5d832d76698e0ad56abdb4daa6839bc67
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Jan 15 14:50:35 2020 +0100
[CAMEL-14404] Provide a lightweight xml parser
---
core/camel-xml-io/pom.xml | 73 +
.../java/org/apache/camel/xml/in/BaseParser.java | 245 ++
.../java/org/apache/camel/xml/in/ModelParser.java | 3033 ++++++++++++++++++
.../java/org/apache/camel/xml/io/MXParser.java | 3243 ++++++++++++++++++++
.../org/apache/camel/xml/io/XmlPullParser.java | 964 ++++++
.../camel/xml/io/XmlPullParserException.java | 55 +
.../org/apache/camel/xml/io/XmlStreamReader.java | 747 +++++
.../camel/xml/io/XmlStreamReaderException.java | 150 +
.../org/apache/camel/xml/in/ModelParserTest.java | 77 +
.../src/test/resources/barInterceptorRoute.xml | 31 +
.../src/test/resources/barOnExceptionRoute.xml | 37 +
.../src/test/resources/barPolicyRoute.xml | 37 +
core/camel-xml-io/src/test/resources/barRest.xml | 26 +
core/camel-xml-io/src/test/resources/barRoute.xml | 31 +
.../src/test/resources/barUpdatedRoute.xml | 34 +
.../src/test/resources/convertBody.xml | 25 +
.../src/test/resources/dynamicRecipientList.xml | 27 +
core/camel-xml-io/src/test/resources/loop.xml | 27 +
core/camel-xml-io/src/test/resources/processor.xml | 25 +
.../src/test/resources/processorWithFilter.xml | 28 +
.../test/resources/processorWithGroovyFilter.xml | 28 +
.../test/resources/processorWithHeaderFilter.xml | 28 +
.../test/resources/processorWithSimpleFilter.xml | 28 +
.../src/test/resources/resequencerBatch.xml | 32 +
.../src/test/resources/resequencerStream.xml | 29 +
.../camel-xml-io/src/test/resources/routeGroup.xml | 31 +
.../src/test/resources/routeProperties.xml | 34 +
.../test/resources/routeWithBindyDataFormat.xml | 30 +
.../src/test/resources/routeWithChoice.xml | 37 +
.../routeWithCircuitBreakerLoadBalance.xml | 33 +
.../src/test/resources/routeWithCvsDataFormat.xml | 30 +
.../resources/routeWithFailoverLoadBalance.xml | 33 +
.../test/resources/routeWithFlatpackDataFormat.xml | 30 +
.../src/test/resources/routeWithHL7DataFormat.xml | 30 +
.../src/test/resources/routeWithJSonDataFormat.xml | 30 +
.../src/test/resources/routeWithJaxbDataFormat.xml | 30 +
.../src/test/resources/routeWithLoadBalance.xml | 30 +
.../src/test/resources/routeWithNamespace.xml | 34 +
.../src/test/resources/routeWithRSSDataFormat.xml | 30 +
.../test/resources/routeWithRandomLoadBalance.xml | 30 +
.../test/resources/routeWithStickyLoadBalance.xml | 34 +
.../resources/routeWithTidyMarkupDataFormat.xml | 30 +
.../test/resources/routeWithTopicLoadBalance.xml | 30 +
.../resources/routeWithXMLSecurityDataFormat.xml | 30 +
.../test/resources/routeWithXStreamDataFormat.xml | 30 +
.../test/resources/routeWithZipFileDataFormat.xml | 30 +
.../src/test/resources/routingSlip.xml | 27 +
.../resources/routingSlipHeaderAndDelimiterSet.xml | 27 +
.../src/test/resources/routingSlipHeaderSet.xml | 27 +
core/camel-xml-io/src/test/resources/saga.xml | 31 +
.../camel-xml-io/src/test/resources/scan-route.xml | 29 +
core/camel-xml-io/src/test/resources/script.xml | 28 +
core/camel-xml-io/src/test/resources/setBody.xml | 28 +
core/camel-xml-io/src/test/resources/setHeader.xml | 28 +
.../src/test/resources/setHeaderToConstant.xml | 28 +
.../camel-xml-io/src/test/resources/simpleRest.xml | 29 +
.../src/test/resources/simpleRestToD.xml | 29 +
.../src/test/resources/simpleRoute.xml | 31 +
core/camel-xml-io/src/test/resources/splitter.xml | 28 +
.../src/test/resources/staticRecipientList.xml | 27 +
core/camel-xml-io/src/test/resources/transform.xml | 28 +
core/pom.xml | 1 +
.../apache/camel/tooling/util/srcgen/Method.java | 5 +-
.../camel/maven/packaging/EndpointDslMojo.java | 2 +-
.../packaging/ModelXmlParserGeneratorMojo.java | 717 +++++
65 files changed, 10864 insertions(+), 2 deletions(-)
diff --git a/core/camel-xml-io/pom.xml b/core/camel-xml-io/pom.xml
new file mode 100644
index 0000000..f38185f
--- /dev/null
+++ b/core/camel-xml-io/pom.xml
@@ -0,0 +1,73 @@
+<?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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>core</artifactId>
+ <version>3.1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-xml-io</artifactId>
+
+ <name>Camel :: XML IO</name>
+ <description>Camel XML IO</description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-engine</artifactId>
+ </dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-package-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <id>generate</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>generate-xml-parser</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
new file mode 100644
index 0000000..b081e4a
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
@@ -0,0 +1,245 @@
+/*
+ * 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.xml.in;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.namespace.QName;
+
+import org.apache.camel.model.OtherAttributesAware;
+import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.xml.io.MXParser;
+import org.apache.camel.xml.io.XmlPullParser;
+import org.apache.camel.xml.io.XmlPullParserException;
+
+public class BaseParser {
+
+ protected final MXParser parser;
+ protected String namespace;
+
+ public BaseParser(InputStream input) throws IOException, XmlPullParserException {
+ this(input, null);
+ }
+
+ public BaseParser(Reader reader) throws IOException, XmlPullParserException {
+ this(reader, null);
+ }
+
+ public BaseParser(InputStream input, String namespace) throws IOException, XmlPullParserException {
+ this.parser = new MXParser();
+ this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ this.parser.setInput(input, null);
+ this.namespace = namespace != null ? namespace : "";
+ }
+
+ public BaseParser(Reader reader, String namespace) throws IOException, XmlPullParserException {
+ this.parser = new MXParser();
+ this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ this.parser.setInput(reader);
+ this.namespace = namespace != null ? namespace : "";
+ }
+
+ protected <T> T doParse(T definition,
+ AttributeHandler<T> attributeHandler,
+ ElementHandler<T> elementHandler,
+ ValueHandler<T> valueHandler)
+ throws IOException, XmlPullParserException {
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ String name = parser.getAttributeName(i);
+ String ns = parser.getAttributeNamespace(i);
+ String val = parser.getAttributeValue(i);
+ if (Objects.equals(ns, "") || Objects.equals(ns, namespace)) {
+ if (attributeHandler == null || !attributeHandler.accept(definition, name, val)) {
+ handleUnexpectedAttribute(namespace, name);
+ }
+ } else {
+ handleOtherAttribute(definition, name, ns, val);
+ }
+ }
+ while (true) {
+ int event = parser.next();
+ if (event == XmlPullParser.TEXT) {
+ if (!parser.isWhitespace()) {
+ valueHandler.accept(definition, parser.getText());
+ }
+ } else if (event == XmlPullParser.START_TAG) {
+ String ns = parser.getNamespace();
+ String name = parser.getName();
+ if (Objects.equals(ns, namespace)) {
+ if (elementHandler == null || !elementHandler.accept(definition, name)) {
+ handleUnexpectedElement(namespace, name);
+ }
+ } else {
+ handleUnexpectedElement(ns, name);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ return definition;
+ } else {
+ throw new XmlPullParserException("expected START_TAG or END_TAG not "
+ + XmlPullParser.TYPES[ event ], parser, null);
+ }
+ }
+ }
+
+ protected Class<?> asClass(String val) throws XmlPullParserException {
+ try {
+ return Class.forName(val);
+ } catch (ClassNotFoundException e) {
+ throw new XmlPullParserException("Unable to load class " + val, parser, e);
+ }
+ }
+
+ protected Class<?>[] asClassArray(String val) throws XmlPullParserException {
+ String[] vals = val.split(" ");
+ Class<?>[] cls = new Class<?>[vals.length];
+ for (int i = 0; i < vals.length; i++) {
+ cls[i] = asClass(vals[i]);
+ }
+ return cls;
+ }
+
+ protected byte[] asByteArray(String val) {
+ return Base64.getDecoder().decode(val);
+ }
+
+ protected List<String> asStringList(String val) {
+ return new ArrayList<>(Arrays.asList(val.split(" ")));
+ }
+
+ protected Set<String> asStringSet(String val) {
+ return new LinkedHashSet<>(Arrays.asList(val.split(" ")));
+ }
+
+ protected <T> void doAdd(T element, List<T> existing, Consumer<List<T>> setter) {
+ if (existing == null) {
+ existing = new ArrayList<>();
+ setter.accept(existing);
+ }
+ existing.add(element);
+ }
+
+ protected <V, B> B unmarshal(XmlAdapter<V,B> adapter, V value) throws XmlPullParserException {
+ try {
+ return adapter.unmarshal(value);
+ } catch (Exception e) {
+ throw new XmlPullParserException("Unable to unmarshal value", parser, e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> void doAdd(T element, T[] existing, Consumer<T[]> setter) {
+ int len = existing != null ? existing.length : 0;
+ T[] newArray = (T[]) Array.newInstance(element.getClass(), len + 1);
+ if (len > 0) {
+ System.arraycopy(existing, 0, newArray, 0, len);
+ }
+ newArray[len] = element;
+ setter.accept(newArray);
+ }
+
+ protected String doParseText() throws IOException, XmlPullParserException {
+ String s = "";
+ int e = parser.next();
+ if (e == XmlPullParser.TEXT) {
+ s = parser.getText();
+ e = parser.next();
+ }
+ if (e != XmlPullParser.END_TAG) {
+ throw new XmlPullParserException("Expected text element");
+ }
+ return s;
+ }
+
+ protected boolean handleUnexpectedAttribute(String namespace, String name) throws XmlPullParserException {
+ throw new XmlPullParserException("Unexpected attribute '{" + namespace + "}" + name + "'");
+ }
+
+ protected boolean handleUnexpectedElement(String namespace, String name) throws XmlPullParserException {
+ throw new XmlPullParserException("Unexpected element '{" + namespace + "}" + name + "'");
+ }
+
+ protected void handleUnexpectedText(String text) throws XmlPullParserException {
+ throw new XmlPullParserException("Unexpected text '" + text + "'");
+ }
+
+ protected void expectTag(String name) throws XmlPullParserException, IOException {
+ if (parser.nextTag() != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("Expected starting tag '{" + namespace + "}" + name + "', read ending tag '{" +
+ parser.getNamespace() + "}" + parser.getName() + "' instead");
+ }
+ if (!Objects.equals(name, parser.getName())
+ || !Objects.equals(namespace, parser.getNamespace())) {
+ throw new XmlPullParserException("Expected starting tag '{" + namespace + "}" + name + "', read starting tag '{" +
+ parser.getNamespace() + "}" + parser.getName() + "' instead");
+ }
+ }
+
+ protected void handleOtherAttribute(Object definition, String name, String ns, String val) throws XmlPullParserException {
+ if (definition instanceof OtherAttributesAware) {
+ Map<QName, Object> others = ((OtherAttributesAware) definition).getOtherAttributes();
+ if (others == null) {
+ others = new LinkedHashMap<>();
+ ((OtherAttributesAware) definition).setOtherAttributes(others);
+ }
+ others.put(new QName(ns, name), val);
+ } else {
+ throw new XmlPullParserException("Unsupported attribute '{" + ns + "}" + name + "'");
+ }
+ }
+
+ protected <T> AttributeHandler<T> noAttributeHandler() {
+ return null;
+ }
+
+ protected <T> ElementHandler<T> noElementHandler() {
+ return (def, name) -> handleUnexpectedElement(namespace, name);
+ }
+
+ protected <T> ValueHandler<T> noValueHandler() {
+ return (def, text) -> handleUnexpectedText(text);
+ }
+
+ protected <T extends ExpressionDefinition> ValueHandler<T> expressionDefinitionValueHandler() {
+ return ExpressionDefinition::setExpression;
+ }
+
+ interface AttributeHandler<T> {
+ boolean accept(T definition, String name, String value) throws IOException, XmlPullParserException;
+ }
+
+ interface ElementHandler<T> {
+ boolean accept(T definition, String name) throws IOException, XmlPullParserException;
+ }
+
+ interface ValueHandler<T> {
+ void accept(T definition, String value) throws IOException, XmlPullParserException;
+ }
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java
new file mode 100644
index 0000000..1b4ed77
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java
@@ -0,0 +1,3033 @@
+/*
+ * 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.xml.in;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Generated;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ShutdownRoute;
+import org.apache.camel.ShutdownRunningTask;
+import org.apache.camel.model.*;
+import org.apache.camel.model.cloud.*;
+import org.apache.camel.model.config.BatchResequencerConfig;
+import org.apache.camel.model.config.ResequencerConfig;
+import org.apache.camel.model.config.StreamResequencerConfig;
+import org.apache.camel.model.dataformat.*;
+import org.apache.camel.model.language.*;
+import org.apache.camel.model.loadbalancer.*;
+import org.apache.camel.model.rest.*;
+import org.apache.camel.model.transformer.*;
+import org.apache.camel.model.validator.*;
+import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
+import org.apache.camel.xml.io.XmlPullParserException;
+
+@SuppressWarnings("unused")
+@Generated("org.apache.camel.maven.packaging.ModelXmlParserGeneratorMojo")
+public class ModelParser extends BaseParser {
+
+ public ModelParser(
+ InputStream input)
+ throws IOException, XmlPullParserException {
+ super(input);
+ }
+ public ModelParser(Reader reader) throws IOException, XmlPullParserException {
+ super(reader);
+ }
+ public ModelParser(
+ InputStream input,
+ String namespace)
+ throws IOException, XmlPullParserException {
+ super(input, namespace);
+ }
+ public ModelParser(
+ Reader reader,
+ String namespace)
+ throws IOException, XmlPullParserException {
+ super(reader, namespace);
+ }
+ protected AggregateDefinition doParseAggregateDefinition() throws IOException, XmlPullParserException {
+ return doParse(new AggregateDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "aggregateControllerRef": def.setAggregateControllerRef(val); break;
+ case "aggregationRepositoryRef": def.setAggregationRepositoryRef(val); break;
+ case "closeCorrelationKeyOnCompletion": def.setCloseCorrelationKeyOnCompletion(val); break;
+ case "completeAllOnStop": def.setCompleteAllOnStop(val); break;
+ case "completionFromBatchConsumer": def.setCompletionFromBatchConsumer(val); break;
+ case "completionInterval": def.setCompletionInterval(val); break;
+ case "completionOnNewCorrelationGroup": def.setCompletionOnNewCorrelationGroup(val); break;
+ case "completionSize": def.setCompletionSize(val); break;
+ case "completionTimeout": def.setCompletionTimeout(val); break;
+ case "completionTimeoutCheckerInterval": def.setCompletionTimeoutCheckerInterval(val); break;
+ case "discardOnAggregationFailure": def.setDiscardOnAggregationFailure(val); break;
+ case "discardOnCompletionTimeout": def.setDiscardOnCompletionTimeout(val); break;
+ case "eagerCheckCompletion": def.setEagerCheckCompletion(val); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "forceCompletionOnStop": def.setForceCompletionOnStop(val); break;
+ case "ignoreInvalidCorrelationKeys": def.setIgnoreInvalidCorrelationKeys(val); break;
+ case "optimisticLocking": def.setOptimisticLocking(val); break;
+ case "parallelProcessing": def.setParallelProcessing(val); break;
+ case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+ case "strategyMethodName": def.setStrategyMethodName(val); break;
+ case "strategyRef": def.setStrategyRef(val); break;
+ case "timeoutCheckerExecutorServiceRef": def.setTimeoutCheckerExecutorServiceRef(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "completionPredicate": def.setCompletionPredicate(doParseExpressionSubElementDefinition()); break;
+ case "completionSizeExpression": def.setCompletionSizeExpression(doParseExpressionSubElementDefinition()); break;
+ case "completionTimeoutExpression": def.setCompletionTimeoutExpression(doParseExpressionSubElementDefinition()); break;
+ case "correlationExpression": def.setCorrelationExpression(doParseExpressionSubElementDefinition()); break;
+ case "optimisticLockRetryPolicy": def.setOptimisticLockRetryPolicyDefinition(doParseOptimisticLockRetryPolicyDefinition()); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ExpressionSubElementDefinition doParseExpressionSubElementDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ExpressionSubElementDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpressionType(v);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected OptimisticLockRetryPolicyDefinition doParseOptimisticLockRetryPolicyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OptimisticLockRetryPolicyDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "exponentialBackOff": def.setExponentialBackOff(val); break;
+ case "maximumRetries": def.setMaximumRetries(val); break;
+ case "maximumRetryDelay": def.setMaximumRetryDelay(val); break;
+ case "randomBackOff": def.setRandomBackOff(val); break;
+ case "retryDelay": def.setRetryDelay(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected <T extends OutputDefinition> ElementHandler<T> outputDefinitionElementHandler() {
+ return (def, key) -> {
+ ProcessorDefinition v = doParseProcessorDefinitionRef(key);
+ if (v != null) {
+ doAdd(v, def.getOutputs(), def::setOutputs);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ };
+ }
+ protected OutputDefinition doParseOutputDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OutputDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected <T extends ProcessorDefinition> AttributeHandler<T> processorDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ if ("inheritErrorHandler".equals(key)) {
+ def.setInheritErrorHandler(Boolean.valueOf(val));
+ return true;
+ }
+ return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ };
+ }
+ protected <T extends OptionalIdentifiedDefinition> AttributeHandler<T> optionalIdentifiedDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "customId": def.setCustomId(Boolean.valueOf(val)); break;
+ case "id": def.setId(val); break;
+ default: return false;
+ }
+ return true;
+ };
+ }
+ protected <T extends OptionalIdentifiedDefinition> ElementHandler<T> optionalIdentifiedDefinitionElementHandler() {
+ return (def, key) -> {
+ if ("description".equals(key)) {
+ def.setDescription(doParseDescriptionDefinition());
+ return true;
+ }
+ return false;
+ };
+ }
+ protected DescriptionDefinition doParseDescriptionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DescriptionDefinition(), (def, key, val) -> {
+ if ("lang".equals(key)) {
+ def.setLang(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), (def, val) -> def.setText(val));
+ }
+ protected BeanDefinition doParseBeanDefinition() throws IOException, XmlPullParserException {
+ return doParse(new BeanDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "beanType": def.setBeanType(val); break;
+ case "cache": def.setCache(val); break;
+ case "method": def.setMethod(val); break;
+ case "ref": def.setRef(val); break;
+ case "scope": def.setScope(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected CatchDefinition doParseCatchDefinition() throws IOException, XmlPullParserException {
+ return doParse(new CatchDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "exception": doAdd(doParseText(), def.getExceptions(), def::setExceptions); break;
+ case "onWhen": def.setOnWhen(doParseWhenDefinition()); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected WhenDefinition doParseWhenDefinition() throws IOException, XmlPullParserException {
+ return doParse(new WhenDefinition(),
+ processorDefinitionAttributeHandler(), outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected ChoiceDefinition doParseChoiceDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ChoiceDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "when": doAdd(doParseWhenDefinition(), def.getWhenClauses(), def::setWhenClauses); break;
+ case "whenSkipSendToEndpoint": doAdd(doParseWhenSkipSendToEndpointDefinition(), def.getWhenClauses(), def::setWhenClauses); break;
+ case "otherwise": def.setOtherwise(doParseOtherwiseDefinition()); break;
+ default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected OtherwiseDefinition doParseOtherwiseDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OtherwiseDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected CircuitBreakerDefinition doParseCircuitBreakerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new CircuitBreakerDefinition(), (def, key, val) -> {
+ if ("configurationRef".equals(key)) {
+ def.setConfigurationRef(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, (def, key) -> {
+ switch (key) {
+ case "hystrixConfiguration": def.setHystrixConfiguration(doParseHystrixConfigurationDefinition()); break;
+ case "resilience4jConfiguration": def.setResilience4jConfiguration(doParseResilience4jConfigurationDefinition()); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected HystrixConfigurationDefinition doParseHystrixConfigurationDefinition() throws IOException, XmlPullParserException {
+ return doParse(new HystrixConfigurationDefinition(),
+ hystrixConfigurationCommonAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected Resilience4jConfigurationDefinition doParseResilience4jConfigurationDefinition() throws IOException, XmlPullParserException {
+ return doParse(new Resilience4jConfigurationDefinition(),
+ resilience4jConfigurationCommonAttributeHandler(), resilience4jConfigurationCommonElementHandler(), noValueHandler());
+ }
+ protected ClaimCheckDefinition doParseClaimCheckDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ClaimCheckDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "filter": def.setFilter(val); break;
+ case "key": def.setKey(val); break;
+ case "operation": def.setOperation(val); break;
+ case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+ case "strategyRef": def.setAggregationStrategyRef(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ContextScanDefinition doParseContextScanDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ContextScanDefinition(), (def, key, val) -> {
+ if ("includeNonSingletons".equals(key)) {
+ def.setIncludeNonSingletons(val);
+ return true;
+ }
+ return false;
+ }, (def, key) -> {
+ switch (key) {
+ case "excludes": doAdd(doParseText(), def.getExcludes(), def::setExcludes); break;
+ case "includes": doAdd(doParseText(), def.getIncludes(), def::setIncludes); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ConvertBodyDefinition doParseConvertBodyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ConvertBodyDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "charset": def.setCharset(val); break;
+ case "type": def.setType(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected <T extends DataFormatDefinition> AttributeHandler<T> dataFormatDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ if ("contentTypeHeader".equals(key)) {
+ def.setContentTypeHeader(val);
+ return true;
+ }
+ return identifiedTypeAttributeHandler().accept(def, key, val);
+ };
+ }
+ protected DataFormatDefinition doParseDataFormatDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DataFormatDefinition(), dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected <T extends IdentifiedType> AttributeHandler<T> identifiedTypeAttributeHandler() {
+ return (def, key, val) -> {
+ if ("id".equals(key)) {
+ def.setId(val);
+ return true;
+ }
+ return false;
+ };
+ }
+ protected DelayDefinition doParseDelayDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DelayDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "asyncDelayed": def.setAsyncDelayed(val); break;
+ case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
+ return (def, key) -> {
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpression(v);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ };
+ }
+ protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "id": def.setId(val); break;
+ case "trim": def.setTrim(val); break;
+ default: return false;
+ }
+ return true;
+ };
+ }
+ protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected DynamicRouterDefinition doParseDynamicRouterDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DynamicRouterDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "cacheSize": def.setCacheSize(val); break;
+ case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+ case "uriDelimiter": def.setUriDelimiter(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected EnrichDefinition doParseEnrichDefinition() throws IOException, XmlPullParserException {
+ return doParse(new EnrichDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "aggregateOnException": def.setAggregateOnException(val); break;
+ case "cacheSize": def.setCacheSize(val); break;
+ case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+ case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+ case "strategyMethodAllowNull": def.setAggregationStrategyMethodAllowNull(val); break;
+ case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+ case "strategyRef": def.setAggregationStrategyRef(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected FilterDefinition doParseFilterDefinition() throws IOException, XmlPullParserException {
+ return doParse(new FilterDefinition(),
+ processorDefinitionAttributeHandler(), outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected <T extends OutputExpressionNode> ElementHandler<T> outputExpressionNodeElementHandler() {
+ return (def, key) -> {
+ ProcessorDefinition v = doParseProcessorDefinitionRef(key);
+ if (v != null) {
+ doAdd(v, def.getOutputs(), def::setOutputs);
+ return true;
+ }
+ return expressionNodeElementHandler().accept(def, key);
+ };
+ }
+ protected FinallyDefinition doParseFinallyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new FinallyDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected FromDefinition doParseFromDefinition() throws IOException, XmlPullParserException {
+ return doParse(new FromDefinition(), (def, key, val) -> {
+ if ("uri".equals(key)) {
+ def.setUri(val);
+ return true;
+ }
+ return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected GlobalOptionDefinition doParseGlobalOptionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new GlobalOptionDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "key": def.setKey(val); break;
+ case "value": def.setValue(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected GlobalOptionsDefinition doParseGlobalOptionsDefinition() throws IOException, XmlPullParserException {
+ return doParse(new GlobalOptionsDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ if ("globalOption".equals(key)) {
+ doAdd(doParseGlobalOptionDefinition(), def.getGlobalOptions(), def::setGlobalOptions);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected <T extends HystrixConfigurationCommon> AttributeHandler<T> hystrixConfigurationCommonAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "allowMaximumSizeToDivergeFromCoreSize": def.setAllowMaximumSizeToDivergeFromCoreSize(val); break;
+ case "circuitBreakerEnabled": def.setCircuitBreakerEnabled(val); break;
+ case "circuitBreakerErrorThresholdPercentage": def.setCircuitBreakerErrorThresholdPercentage(val); break;
+ case "circuitBreakerForceClosed": def.setCircuitBreakerForceClosed(val); break;
+ case "circuitBreakerForceOpen": def.setCircuitBreakerForceOpen(val); break;
+ case "circuitBreakerRequestVolumeThreshold": def.setCircuitBreakerRequestVolumeThreshold(val); break;
+ case "circuitBreakerSleepWindowInMilliseconds": def.setCircuitBreakerSleepWindowInMilliseconds(val); break;
+ case "corePoolSize": def.setCorePoolSize(val); break;
+ case "executionIsolationSemaphoreMaxConcurrentRequests": def.setExecutionIsolationSemaphoreMaxConcurrentRequests(val); break;
+ case "executionIsolationStrategy": def.setExecutionIsolationStrategy(val); break;
+ case "executionIsolationThreadInterruptOnTimeout": def.setExecutionIsolationThreadInterruptOnTimeout(val); break;
+ case "executionTimeoutEnabled": def.setExecutionTimeoutEnabled(val); break;
+ case "executionTimeoutInMilliseconds": def.setExecutionTimeoutInMilliseconds(val); break;
+ case "fallbackEnabled": def.setFallbackEnabled(val); break;
+ case "fallbackIsolationSemaphoreMaxConcurrentRequests": def.setFallbackIsolationSemaphoreMaxConcurrentRequests(val); break;
+ case "groupKey": def.setGroupKey(val); break;
+ case "keepAliveTime": def.setKeepAliveTime(val); break;
+ case "maxQueueSize": def.setMaxQueueSize(val); break;
+ case "maximumSize": def.setMaximumSize(val); break;
+ case "metricsHealthSnapshotIntervalInMilliseconds": def.setMetricsHealthSnapshotIntervalInMilliseconds(val); break;
+ case "metricsRollingPercentileBucketSize": def.setMetricsRollingPercentileBucketSize(val); break;
+ case "metricsRollingPercentileEnabled": def.setMetricsRollingPercentileEnabled(val); break;
+ case "metricsRollingPercentileWindowBuckets": def.setMetricsRollingPercentileWindowBuckets(val); break;
+ case "metricsRollingPercentileWindowInMilliseconds": def.setMetricsRollingPercentileWindowInMilliseconds(val); break;
+ case "metricsRollingStatisticalWindowBuckets": def.setMetricsRollingStatisticalWindowBuckets(val); break;
+ case "metricsRollingStatisticalWindowInMilliseconds": def.setMetricsRollingStatisticalWindowInMilliseconds(val); break;
+ case "queueSizeRejectionThreshold": def.setQueueSizeRejectionThreshold(val); break;
+ case "requestLogEnabled": def.setRequestLogEnabled(val); break;
+ case "threadPoolKey": def.setThreadPoolKey(val); break;
+ case "threadPoolRollingNumberStatisticalWindowBuckets": def.setThreadPoolRollingNumberStatisticalWindowBuckets(val); break;
+ case "threadPoolRollingNumberStatisticalWindowInMilliseconds": def.setThreadPoolRollingNumberStatisticalWindowInMilliseconds(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected HystrixConfigurationCommon doParseHystrixConfigurationCommon() throws IOException, XmlPullParserException {
+ return doParse(new HystrixConfigurationCommon(), hystrixConfigurationCommonAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected IdempotentConsumerDefinition doParseIdempotentConsumerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new IdempotentConsumerDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "completionEager": def.setCompletionEager(val); break;
+ case "eager": def.setEager(val); break;
+ case "messageIdRepositoryRef": def.setMessageIdRepositoryRef(val); break;
+ case "removeOnFailure": def.setRemoveOnFailure(val); break;
+ case "skipDuplicate": def.setSkipDuplicate(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected InOnlyDefinition doParseInOnlyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InOnlyDefinition(),
+ sendDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected <T extends SendDefinition> AttributeHandler<T> sendDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ if ("uri".equals(key)) {
+ def.setUri(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ };
+ }
+ protected InOutDefinition doParseInOutDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InOutDefinition(),
+ sendDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected InputTypeDefinition doParseInputTypeDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InputTypeDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "urn": def.setUrn(val); break;
+ case "validate": def.setValidate(val); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected InterceptDefinition doParseInterceptDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InterceptDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected InterceptFromDefinition doParseInterceptFromDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InterceptFromDefinition(), (def, key, val) -> {
+ if ("uri".equals(key)) {
+ def.setUri(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected InterceptSendToEndpointDefinition doParseInterceptSendToEndpointDefinition() throws IOException, XmlPullParserException {
+ return doParse(new InterceptSendToEndpointDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "afterUri": def.setAfterUri(val); break;
+ case "skipSendToOriginalEndpoint": def.setSkipSendToOriginalEndpoint(val); break;
+ case "uri": def.setUri(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected LoadBalanceDefinition doParseLoadBalanceDefinition() throws IOException, XmlPullParserException {
+ return doParse(new LoadBalanceDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "failover": def.setLoadBalancerType(doParseFailoverLoadBalancerDefinition()); break;
+ case "random": def.setLoadBalancerType(doParseRandomLoadBalancerDefinition()); break;
+ case "customLoadBalancer": def.setLoadBalancerType(doParseCustomLoadBalancerDefinition()); break;
+ case "roundRobin": def.setLoadBalancerType(doParseRoundRobinLoadBalancerDefinition()); break;
+ case "sticky": def.setLoadBalancerType(doParseStickyLoadBalancerDefinition()); break;
+ case "topic": def.setLoadBalancerType(doParseTopicLoadBalancerDefinition()); break;
+ case "weighted": def.setLoadBalancerType(doParseWeightedLoadBalancerDefinition()); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected LoadBalancerDefinition doParseLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new LoadBalancerDefinition(),
+ identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected LogDefinition doParseLogDefinition() throws IOException, XmlPullParserException {
+ return doParse(new LogDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "logName": def.setLogName(val); break;
+ case "loggerRef": def.setLoggerRef(val); break;
+ case "loggingLevel": def.setLoggingLevel(val); break;
+ case "marker": def.setMarker(val); break;
+ case "message": def.setMessage(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected LoopDefinition doParseLoopDefinition() throws IOException, XmlPullParserException {
+ return doParse(new LoopDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "copy": def.setCopy(val); break;
+ case "doWhile": def.setDoWhile(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected MarshalDefinition doParseMarshalDefinition() throws IOException, XmlPullParserException {
+ return doParse(new MarshalDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+ if (v != null) {
+ def.setDataFormatType(v);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected MulticastDefinition doParseMulticastDefinition() throws IOException, XmlPullParserException {
+ return doParse(new MulticastDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "onPrepareRef": def.setOnPrepareRef(val); break;
+ case "parallelAggregate": def.setParallelAggregate(val); break;
+ case "parallelProcessing": def.setParallelProcessing(val); break;
+ case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+ case "stopOnAggregateException": def.setStopOnAggregateException(val); break;
+ case "stopOnException": def.setStopOnException(val); break;
+ case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+ case "strategyMethodName": def.setStrategyMethodName(val); break;
+ case "strategyRef": def.setStrategyRef(val); break;
+ case "streaming": def.setStreaming(val); break;
+ case "timeout": def.setTimeout(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected OnCompletionDefinition doParseOnCompletionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OnCompletionDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "mode": def.setMode(OnCompletionMode.valueOf(val)); break;
+ case "onCompleteOnly": def.setOnCompleteOnly(val); break;
+ case "onFailureOnly": def.setOnFailureOnly(val); break;
+ case "parallelProcessing": def.setParallelProcessing(val); break;
+ case "useOriginalMessage": def.setUseOriginalMessage(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("onWhen".equals(key)) {
+ def.setOnWhen(doParseWhenDefinition());
+ return true;
+ }
+ return outputDefinitionElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected OnExceptionDefinition doParseOnExceptionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OnExceptionDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "onExceptionOccurredRef": def.setOnExceptionOccurredRef(val); break;
+ case "onRedeliveryRef": def.setOnRedeliveryRef(val); break;
+ case "redeliveryPolicyRef": def.setRedeliveryPolicyRef(val); break;
+ case "useOriginalBody": def.setUseOriginalBody(val); break;
+ case "useOriginalMessage": def.setUseOriginalMessage(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "continued": def.setContinued(doParseExpressionSubElementDefinition()); break;
+ case "exception": doAdd(doParseText(), def.getExceptions(), def::setExceptions); break;
+ case "handled": def.setHandled(doParseExpressionSubElementDefinition()); break;
+ case "onWhen": def.setOnWhen(doParseWhenDefinition()); break;
+ case "redeliveryPolicy": def.setRedeliveryPolicyType(doParseRedeliveryPolicyDefinition()); break;
+ case "retryWhile": def.setRetryWhile(doParseExpressionSubElementDefinition()); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RedeliveryPolicyDefinition doParseRedeliveryPolicyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RedeliveryPolicyDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "allowRedeliveryWhileStopping": def.setAllowRedeliveryWhileStopping(val); break;
+ case "asyncDelayedRedelivery": def.setAsyncDelayedRedelivery(val); break;
+ case "backOffMultiplier": def.setBackOffMultiplier(val); break;
+ case "collisionAvoidanceFactor": def.setCollisionAvoidanceFactor(val); break;
+ case "delayPattern": def.setDelayPattern(val); break;
+ case "disableRedelivery": def.setDisableRedelivery(val); break;
+ case "exchangeFormatterRef": def.setExchangeFormatterRef(val); break;
+ case "logContinued": def.setLogContinued(val); break;
+ case "logExhausted": def.setLogExhausted(val); break;
+ case "logExhaustedMessageBody": def.setLogExhaustedMessageBody(val); break;
+ case "logExhaustedMessageHistory": def.setLogExhaustedMessageHistory(val); break;
+ case "logHandled": def.setLogHandled(val); break;
+ case "logNewException": def.setLogNewException(val); break;
+ case "logRetryAttempted": def.setLogRetryAttempted(val); break;
+ case "logRetryStackTrace": def.setLogRetryStackTrace(val); break;
+ case "logStackTrace": def.setLogStackTrace(val); break;
+ case "maximumRedeliveries": def.setMaximumRedeliveries(val); break;
+ case "maximumRedeliveryDelay": def.setMaximumRedeliveryDelay(val); break;
+ case "redeliveryDelay": def.setRedeliveryDelay(val); break;
+ case "retriesExhaustedLogLevel": def.setRetriesExhaustedLogLevel(val); break;
+ case "retryAttemptedLogInterval": def.setRetryAttemptedLogInterval(val); break;
+ case "retryAttemptedLogLevel": def.setRetryAttemptedLogLevel(val); break;
+ case "useCollisionAvoidance": def.setUseCollisionAvoidance(val); break;
+ case "useExponentialBackOff": def.setUseExponentialBackOff(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected OnFallbackDefinition doParseOnFallbackDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OnFallbackDefinition(), (def, key, val) -> {
+ if ("fallbackViaNetwork".equals(key)) {
+ def.setFallbackViaNetwork(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected OutputTypeDefinition doParseOutputTypeDefinition() throws IOException, XmlPullParserException {
+ return doParse(new OutputTypeDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "urn": def.setUrn(val); break;
+ case "validate": def.setValidate(val); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected PackageScanDefinition doParsePackageScanDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PackageScanDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "excludes": doAdd(doParseText(), def.getExcludes(), def::setExcludes); break;
+ case "includes": doAdd(doParseText(), def.getIncludes(), def::setIncludes); break;
+ case "package": doAdd(doParseText(), def.getPackages(), def::setPackages); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected PipelineDefinition doParsePipelineDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PipelineDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected PolicyDefinition doParsePolicyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PolicyDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected PollEnrichDefinition doParsePollEnrichDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PollEnrichDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "aggregateOnException": def.setAggregateOnException(val); break;
+ case "cacheSize": def.setCacheSize(val); break;
+ case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+ case "strategyMethodAllowNull": def.setAggregationStrategyMethodAllowNull(val); break;
+ case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+ case "strategyRef": def.setAggregationStrategyRef(val); break;
+ case "timeout": def.setTimeout(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected ProcessDefinition doParseProcessDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ProcessDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected PropertyDefinition doParsePropertyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PropertyDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "key": def.setKey(val); break;
+ case "value": def.setValue(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected PropertyDefinitions doParsePropertyDefinitions() throws IOException, XmlPullParserException {
+ return doParse(new PropertyDefinitions(),
+ noAttributeHandler(), (def, key) -> {
+ if ("properties".equals(key)) {
+ doAdd(doParsePropertyDefinition(), def.getProperties(), def::setProperties);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected RecipientListDefinition doParseRecipientListDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RecipientListDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "cacheSize": def.setCacheSize(val); break;
+ case "delimiter": def.setDelimiter(val); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+ case "onPrepareRef": def.setOnPrepareRef(val); break;
+ case "parallelAggregate": def.setParallelAggregate(val); break;
+ case "parallelProcessing": def.setParallelProcessing(val); break;
+ case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+ case "stopOnAggregateException": def.setStopOnAggregateException(val); break;
+ case "stopOnException": def.setStopOnException(val); break;
+ case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+ case "strategyMethodName": def.setStrategyMethodName(val); break;
+ case "strategyRef": def.setStrategyRef(val); break;
+ case "streaming": def.setStreaming(val); break;
+ case "timeout": def.setTimeout(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected RemoveHeaderDefinition doParseRemoveHeaderDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RemoveHeaderDefinition(), (def, key, val) -> {
+ if ("headerName".equals(key)) {
+ def.setHeaderName(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected RemoveHeadersDefinition doParseRemoveHeadersDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RemoveHeadersDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "excludePattern": def.setExcludePattern(val); break;
+ case "pattern": def.setPattern(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected RemovePropertiesDefinition doParseRemovePropertiesDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RemovePropertiesDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "excludePattern": def.setExcludePattern(val); break;
+ case "pattern": def.setPattern(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected RemovePropertyDefinition doParseRemovePropertyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RemovePropertyDefinition(), (def, key, val) -> {
+ if ("propertyName".equals(key)) {
+ def.setPropertyName(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ResequenceDefinition doParseResequenceDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ResequenceDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "batch-config": def.setResequencerConfig(doParseBatchResequencerConfig()); break;
+ case "stream-config": def.setResequencerConfig(doParseStreamResequencerConfig()); break;
+ default:
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpression(v);
+ return true;
+ }
+ return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected <T extends Resilience4jConfigurationCommon> AttributeHandler<T> resilience4jConfigurationCommonAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "automaticTransitionFromOpenToHalfOpenEnabled": def.setAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean.valueOf(val)); break;
+ case "circuitBreakerRef": def.setCircuitBreakerRef(val); break;
+ case "configRef": def.setConfigRef(val); break;
+ case "failureRateThreshold": def.setFailureRateThreshold(Float.valueOf(val)); break;
+ case "minimumNumberOfCalls": def.setMinimumNumberOfCalls(Integer.valueOf(val)); break;
+ case "permittedNumberOfCallsInHalfOpenState": def.setPermittedNumberOfCallsInHalfOpenState(Integer.valueOf(val)); break;
+ case "slidingWindowSize": def.setSlidingWindowSize(Integer.valueOf(val)); break;
+ case "slidingWindowType": def.setSlidingWindowType(val); break;
+ case "slowCallDurationThreshold": def.setSlowCallDurationThreshold(Integer.valueOf(val)); break;
+ case "slowCallRateThreshold": def.setSlowCallRateThreshold(Float.valueOf(val)); break;
+ case "waitDurationInOpenState": def.setWaitDurationInOpenState(Integer.valueOf(val)); break;
+ case "writableStackTraceEnabled": def.setWritableStackTraceEnabled(Boolean.valueOf(val)); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected <T extends Resilience4jConfigurationCommon> ElementHandler<T> resilience4jConfigurationCommonElementHandler() {
+ return (def, key) -> {
+ switch (key) {
+ case "bulkheadEnabled": def.setBulkheadEnabled(Boolean.valueOf(doParseText())); break;
+ case "bulkheadMaxConcurrentCalls": def.setBulkheadMaxConcurrentCalls(Integer.valueOf(doParseText())); break;
+ case "bulkheadMaxWaitDuration": def.setBulkheadMaxWaitDuration(Integer.valueOf(doParseText())); break;
+ case "timeoutCancelRunningFuture": def.setTimeoutCancelRunningFuture(Boolean.valueOf(doParseText())); break;
+ case "timeoutDuration": def.setTimeoutDuration(Integer.valueOf(doParseText())); break;
+ case "timeoutEnabled": def.setTimeoutEnabled(Boolean.valueOf(doParseText())); break;
+ case "timeoutExecutorServiceRef": def.setTimeoutExecutorServiceRef(doParseText()); break;
+ default: return false;
+ }
+ return true;
+ };
+ }
+ protected Resilience4jConfigurationCommon doParseResilience4jConfigurationCommon() throws IOException, XmlPullParserException {
+ return doParse(new Resilience4jConfigurationCommon(), resilience4jConfigurationCommonAttributeHandler(), resilience4jConfigurationCommonElementHandler(), noValueHandler());
+ }
+ protected RestContextRefDefinition doParseRestContextRefDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestContextRefDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RollbackDefinition doParseRollbackDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RollbackDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "markRollbackOnly": def.setMarkRollbackOnly(val); break;
+ case "markRollbackOnlyLast": def.setMarkRollbackOnlyLast(val); break;
+ case "message": def.setMessage(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected RouteBuilderDefinition doParseRouteBuilderDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RouteBuilderDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return identifiedTypeAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RouteContextRefDefinition doParseRouteContextRefDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RouteContextRefDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RouteDefinition doParseRouteDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RouteDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "autoStartup": def.setAutoStartup(val); break;
+ case "delayer": def.setDelayer(val); break;
+ case "errorHandlerRef": def.setErrorHandlerRef(val); break;
+ case "group": def.setGroup(val); break;
+ case "logMask": def.setLogMask(val); break;
+ case "messageHistory": def.setMessageHistory(val); break;
+ case "routePolicyRef": def.setRoutePolicyRef(val); break;
+ case "shutdownRoute": def.setShutdownRoute(ShutdownRoute.valueOf(val)); break;
+ case "shutdownRunningTask": def.setShutdownRunningTask(ShutdownRunningTask.valueOf(val)); break;
+ case "startupOrder": def.setStartupOrder(Integer.valueOf(val)); break;
+ case "streamCache": def.setStreamCache(val); break;
+ case "trace": def.setTrace(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "from": def.setInput(doParseFromDefinition()); break;
+ case "inputType": def.setInputType(doParseInputTypeDefinition()); break;
+ case "outputType": def.setOutputType(doParseOutputTypeDefinition()); break;
+ case "routeProperty": doAdd(doParsePropertyDefinition(), def.getRouteProperties(), def::setRouteProperties); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RestDefinition doParseRestDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "apiDocs": def.setApiDocs(val); break;
+ case "bindingMode": def.setBindingMode(val); break;
+ case "clientRequestValidation": def.setClientRequestValidation(val); break;
+ case "consumes": def.setConsumes(val); break;
+ case "enableCORS": def.setEnableCORS(val); break;
+ case "path": def.setPath(val); break;
+ case "produces": def.setProduces(val); break;
+ case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+ case "tag": def.setTag(val); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "delete": doAdd(doParseDeleteVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "verb": doAdd(doParseVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "get": doAdd(doParseGetVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "head": doAdd(doParseHeadVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "patch": doAdd(doParsePatchVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "post": doAdd(doParsePostVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "put": doAdd(doParsePutVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+ case "securityDefinitions": def.setSecurityDefinitions(doParseRestSecuritiesDefinition()); break;
+ default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RestBindingDefinition doParseRestBindingDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestBindingDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "bindingMode": def.setBindingMode(val); break;
+ case "clientRequestValidation": def.setClientRequestValidation(val); break;
+ case "component": def.setComponent(val); break;
+ case "consumes": def.setConsumes(val); break;
+ case "enableCORS": def.setEnableCORS(val); break;
+ case "outType": def.setOutType(val); break;
+ case "produces": def.setProduces(val); break;
+ case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+ case "type": def.setType(val); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ public RoutesDefinition parseRoutesDefinition()
+ throws IOException, XmlPullParserException {
+ expectTag("routes");
+ return doParseRoutesDefinition();
+ }
+ protected RoutesDefinition doParseRoutesDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RoutesDefinition(),
+ optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+ if ("route".equals(key)) {
+ doAdd(doParseRouteDefinition(), def.getRoutes(), def::setRoutes);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected RoutingSlipDefinition doParseRoutingSlipDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RoutingSlipDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "cacheSize": def.setCacheSize(val); break;
+ case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+ case "uriDelimiter": def.setUriDelimiter(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SagaDefinition doParseSagaDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SagaDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "completionMode": def.setCompletionMode(SagaCompletionMode.valueOf(val)); break;
+ case "propagation": def.setPropagation(SagaPropagation.valueOf(val)); break;
+ case "sagaServiceRef": def.setSagaServiceRef(val); break;
+ case "timeoutInMilliseconds": def.setTimeoutInMilliseconds(Long.valueOf(val)); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "compensation": def.setCompensation(doParseSagaActionUriDefinition()); break;
+ case "completion": def.setCompletion(doParseSagaActionUriDefinition()); break;
+ case "option": doAdd(doParseSagaOptionDefinition(), def.getOptions(), def::setOptions); break;
+ default: return outputDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected SagaActionUriDefinition doParseSagaActionUriDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SagaActionUriDefinition(), (def, key, val) -> {
+ if ("uri".equals(key)) {
+ def.setUri(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected SagaOptionDefinition doParseSagaOptionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SagaOptionDefinition(), (def, key, val) -> {
+ if ("optionName".equals(key)) {
+ def.setOptionName(val);
+ return true;
+ }
+ return false;
+ }, (def, key) -> {
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpression(v);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected SamplingDefinition doParseSamplingDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SamplingDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "messageFrequency": def.setMessageFrequency(Long.valueOf(val)); break;
+ case "samplePeriod": def.setSamplePeriod(Long.valueOf(val)); break;
+ case "units": def.setUnits(TimeUnit.valueOf(val)); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ScriptDefinition doParseScriptDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ScriptDefinition(),
+ processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SetBodyDefinition doParseSetBodyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SetBodyDefinition(),
+ processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SetExchangePatternDefinition doParseSetExchangePatternDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SetExchangePatternDefinition(), (def, key, val) -> {
+ if ("pattern".equals(key)) {
+ def.setPattern(ExchangePattern.valueOf(val));
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected SetHeaderDefinition doParseSetHeaderDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SetHeaderDefinition(), (def, key, val) -> {
+ if ("name".equals(key)) {
+ def.setName(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SetPropertyDefinition doParseSetPropertyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SetPropertyDefinition(), (def, key, val) -> {
+ if ("name".equals(key)) {
+ def.setName(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SortDefinition doParseSortDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SortDefinition(), (def, key, val) -> {
+ if ("comparatorRef".equals(key)) {
+ def.setComparatorRef(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, expressionNodeElementHandler(), noValueHandler());
+ }
+ protected SplitDefinition doParseSplitDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SplitDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "onPrepareRef": def.setOnPrepareRef(val); break;
+ case "parallelAggregate": def.setParallelAggregate(Boolean.valueOf(val)); break;
+ case "parallelProcessing": def.setParallelProcessing(Boolean.valueOf(val)); break;
+ case "shareUnitOfWork": def.setShareUnitOfWork(Boolean.valueOf(val)); break;
+ case "stopOnAggregateException": def.setStopOnAggregateException(Boolean.valueOf(val)); break;
+ case "stopOnException": def.setStopOnException(Boolean.valueOf(val)); break;
+ case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(Boolean.valueOf(val)); break;
+ case "strategyMethodName": def.setStrategyMethodName(val); break;
+ case "strategyRef": def.setStrategyRef(val); break;
+ case "streaming": def.setStreaming(Boolean.valueOf(val)); break;
+ case "timeout": def.setTimeout(Long.valueOf(val)); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected StepDefinition doParseStepDefinition() throws IOException, XmlPullParserException {
+ return doParse(new StepDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected StopDefinition doParseStopDefinition() throws IOException, XmlPullParserException {
+ return doParse(new StopDefinition(),
+ processorDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ThreadPoolProfileDefinition doParseThreadPoolProfileDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ThreadPoolProfileDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "allowCoreThreadTimeOut": def.setAllowCoreThreadTimeOut(val); break;
+ case "defaultProfile": def.setDefaultProfile(Boolean.valueOf(val)); break;
+ case "keepAliveTime": def.setKeepAliveTime(val); break;
+ case "maxPoolSize": def.setMaxPoolSize(val); break;
+ case "maxQueueSize": def.setMaxQueueSize(val); break;
+ case "poolSize": def.setPoolSize(val); break;
+ case "rejectedPolicy": def.setRejectedPolicy(val); break;
+ case "timeUnit": def.setTimeUnit(TimeUnit.valueOf(val)); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ThreadsDefinition doParseThreadsDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ThreadsDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "allowCoreThreadTimeOut": def.setAllowCoreThreadTimeOut(val); break;
+ case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "keepAliveTime": def.setKeepAliveTime(val); break;
+ case "maxPoolSize": def.setMaxPoolSize(val); break;
+ case "maxQueueSize": def.setMaxQueueSize(val); break;
+ case "poolSize": def.setPoolSize(val); break;
+ case "rejectedPolicy": def.setRejectedPolicy(ThreadPoolRejectedPolicy.valueOf(val)); break;
+ case "threadName": def.setThreadName(val); break;
+ case "timeUnit": def.setTimeUnit(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ThrottleDefinition doParseThrottleDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ThrottleDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "asyncDelayed": def.setAsyncDelayed(Boolean.valueOf(val)); break;
+ case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(Boolean.valueOf(val)); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "rejectExecution": def.setRejectExecution(Boolean.valueOf(val)); break;
+ case "timePeriodMillis": def.setTimePeriodMillis(Long.valueOf(val)); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("correlationExpression".equals(key)) {
+ def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+ return true;
+ }
+ return expressionNodeElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected ThrowExceptionDefinition doParseThrowExceptionDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ThrowExceptionDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "exceptionType": def.setExceptionType(val); break;
+ case "message": def.setMessage(val); break;
+ case "ref": def.setRef(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected ToDefinition doParseToDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ToDefinition(), (def, key, val) -> {
+ if ("pattern".equals(key)) {
+ def.setPattern(val);
+ return true;
+ }
+ return sendDefinitionAttributeHandler().accept(def, key, val);
+ }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected <T extends ToDynamicDefinition> AttributeHandler<T> toDynamicDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "allowOptimisedComponents": def.setAllowOptimisedComponents(val); break;
+ case "cacheSize": def.setCacheSize(val); break;
+ case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+ case "pattern": def.setPattern(val); break;
+ case "uri": def.setUri(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected ToDynamicDefinition doParseToDynamicDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ToDynamicDefinition(), toDynamicDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+ }
+ protected TransactedDefinition doParseTransactedDefinition() throws IOException, XmlPullParserException {
+ return doParse(new TransactedDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return processorDefinitionAttributeHandler().accept(def, key, val);
+ }, outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected TransformDefinition doParseTransformDefinition() throws IOException, XmlPullParserException {
+ return doParse(new TransformDefinition(),
+ processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+ }
+ protected TryDefinition doParseTryDefinition() throws IOException, XmlPullParserException {
+ return doParse(new TryDefinition(),
+ processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+ }
+ protected UnmarshalDefinition doParseUnmarshalDefinition() throws IOException, XmlPullParserException {
+ return doParse(new UnmarshalDefinition(),
+ processorDefinitionAttributeHandler(), (def, key) -> {
+ DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+ if (v != null) {
+ def.setDataFormatType(v);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected ValidateDefinition doParseValidateDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ValidateDefinition(),
+ processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+ }
+ protected WhenSkipSendToEndpointDefinition doParseWhenSkipSendToEndpointDefinition() throws IOException, XmlPullParserException {
+ return doParse(new WhenSkipSendToEndpointDefinition(),
+ processorDefinitionAttributeHandler(), outputExpressionNodeElementHandler(), noValueHandler());
+ }
+ protected WireTapDefinition doParseWireTapDefinition() throws IOException, XmlPullParserException {
+ return doParse(new WireTapDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "copy": def.setCopy(val); break;
+ case "dynamicUri": def.setDynamicUri(val); break;
+ case "executorServiceRef": def.setExecutorServiceRef(val); break;
+ case "onPrepareRef": def.setOnPrepareRef(val); break;
+ case "processorRef": def.setNewExchangeProcessorRef(val); break;
+ default: return toDynamicDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "setHeader": doAdd(doParseSetHeaderDefinition(), def.getHeaders(), def::setHeaders); break;
+ case "body": def.setNewExchangeExpression(doParseExpressionSubElementDefinition()); break;
+ default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected BlacklistServiceCallServiceFilterConfiguration doParseBlacklistServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new BlacklistServiceCallServiceFilterConfiguration(),
+ identifiedTypeAttributeHandler(), (def, key) -> {
+ if ("servers".equals(key)) {
+ doAdd(doParseText(), def.getServers(), def::setServers);
+ return true;
+ }
+ return serviceCallConfigurationElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected ServiceCallServiceFilterConfiguration doParseServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallServiceFilterConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected <T extends ServiceCallConfiguration> ElementHandler<T> serviceCallConfigurationElementHandler() {
+ return (def, key) -> {
+ if ("properties".equals(key)) {
+ doAdd(doParsePropertyDefinition(), def.getProperties(), def::setProperties);
+ return true;
+ }
+ return false;
+ };
+ }
+ protected CachingServiceCallServiceDiscoveryConfiguration doParseCachingServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new CachingServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "timeout": def.setTimeout(val); break;
+ case "units": def.setUnits(TimeUnit.valueOf(val)); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+ case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+ case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+ case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+ case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+ case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+ default: return serviceCallConfigurationElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ServiceCallServiceDiscoveryConfiguration doParseServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallServiceDiscoveryConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected CombinedServiceCallServiceDiscoveryConfiguration doParseCombinedServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new CombinedServiceCallServiceDiscoveryConfiguration(),
+ identifiedTypeAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "consulServiceDiscovery": doAdd(doParseConsulServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ case "dnsServiceDiscovery": doAdd(doParseDnsServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ case "etcdServiceDiscovery": doAdd(doParseEtcdServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ case "kubernetesServiceDiscovery": doAdd(doParseKubernetesServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ case "staticServiceDiscovery": doAdd(doParseStaticServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ case "cachingServiceDiscovery": doAdd(doParseCachingServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+ default: return serviceCallConfigurationElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected CombinedServiceCallServiceFilterConfiguration doParseCombinedServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new CombinedServiceCallServiceFilterConfiguration(),
+ identifiedTypeAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "blacklistServiceFilter": doAdd(doParseBlacklistServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+ case "customServiceFilter": doAdd(doParseCustomServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+ case "healthyServiceFilter": doAdd(doParseHealthyServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+ case "passThroughServiceFilter": doAdd(doParsePassThroughServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+ default: return serviceCallConfigurationElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ConsulServiceCallServiceDiscoveryConfiguration doParseConsulServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ConsulServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "aclToken": def.setAclToken(val); break;
+ case "blockSeconds": def.setBlockSeconds(Integer.valueOf(val)); break;
+ case "connectTimeoutMillis": def.setConnectTimeoutMillis(Long.valueOf(val)); break;
+ case "datacenter": def.setDatacenter(val); break;
+ case "password": def.setPassword(val); break;
+ case "readTimeoutMillis": def.setReadTimeoutMillis(Long.valueOf(val)); break;
+ case "url": def.setUrl(val); break;
+ case "userName": def.setUserName(val); break;
+ case "writeTimeoutMillis": def.setWriteTimeoutMillis(Long.valueOf(val)); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected CustomServiceCallServiceFilterConfiguration doParseCustomServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new CustomServiceCallServiceFilterConfiguration(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setServiceFilterRef(val);
+ return true;
+ }
+ return identifiedTypeAttributeHandler().accept(def, key, val);
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected DefaultServiceCallServiceLoadBalancerConfiguration doParseDefaultServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new DefaultServiceCallServiceLoadBalancerConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected ServiceCallServiceLoadBalancerConfiguration doParseServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallServiceLoadBalancerConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected DnsServiceCallServiceDiscoveryConfiguration doParseDnsServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new DnsServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "domain": def.setDomain(val); break;
+ case "proto": def.setProto(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected EtcdServiceCallServiceDiscoveryConfiguration doParseEtcdServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new EtcdServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "password": def.setPassword(val); break;
+ case "servicePath": def.setServicePath(val); break;
+ case "timeout": def.setTimeout(Long.valueOf(val)); break;
+ case "type": def.setType(val); break;
+ case "uris": def.setUris(val); break;
+ case "userName": def.setUserName(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected HealthyServiceCallServiceFilterConfiguration doParseHealthyServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new HealthyServiceCallServiceFilterConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected KubernetesServiceCallServiceDiscoveryConfiguration doParseKubernetesServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new KubernetesServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "apiVersion": def.setApiVersion(val); break;
+ case "caCertData": def.setCaCertData(val); break;
+ case "caCertFile": def.setCaCertFile(val); break;
+ case "clientCertData": def.setClientCertData(val); break;
+ case "clientCertFile": def.setClientCertFile(val); break;
+ case "clientKeyAlgo": def.setClientKeyAlgo(val); break;
+ case "clientKeyData": def.setClientKeyData(val); break;
+ case "clientKeyFile": def.setClientKeyFile(val); break;
+ case "clientKeyPassphrase": def.setClientKeyPassphrase(val); break;
+ case "dnsDomain": def.setDnsDomain(val); break;
+ case "lookup": def.setLookup(val); break;
+ case "masterUrl": def.setMasterUrl(val); break;
+ case "namespace": def.setNamespace(val); break;
+ case "oauthToken": def.setOauthToken(val); break;
+ case "password": def.setPassword(val); break;
+ case "portName": def.setPortName(val); break;
+ case "portProtocol": def.setPortProtocol(val); break;
+ case "trustCerts": def.setTrustCerts(Boolean.valueOf(val)); break;
+ case "username": def.setUsername(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected PassThroughServiceCallServiceFilterConfiguration doParsePassThroughServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new PassThroughServiceCallServiceFilterConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected RibbonServiceCallServiceLoadBalancerConfiguration doParseRibbonServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new RibbonServiceCallServiceLoadBalancerConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "clientName": def.setClientName(val); break;
+ case "namespace": def.setNamespace(val); break;
+ case "password": def.setPassword(val); break;
+ case "username": def.setUsername(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected ServiceCallConfigurationDefinition doParseServiceCallConfigurationDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallConfigurationDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "component": def.setComponent(val); break;
+ case "expressionRef": def.setExpressionRef(val); break;
+ case "loadBalancerRef": def.setLoadBalancerRef(val); break;
+ case "pattern": def.setPattern(ExchangePattern.valueOf(val)); break;
+ case "serviceChooserRef": def.setServiceChooserRef(val); break;
+ case "serviceDiscoveryRef": def.setServiceDiscoveryRef(val); break;
+ case "serviceFilterRef": def.setServiceFilterRef(val); break;
+ case "uri": def.setUri(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "expression": def.setExpressionConfiguration(doParseServiceCallExpressionConfiguration()); break;
+ case "ribbonLoadBalancer": def.setLoadBalancerConfiguration(doParseRibbonServiceCallServiceLoadBalancerConfiguration()); break;
+ case "defaultLoadBalancer": def.setLoadBalancerConfiguration(doParseDefaultServiceCallServiceLoadBalancerConfiguration()); break;
+ case "cachingServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCachingServiceCallServiceDiscoveryConfiguration()); break;
+ case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+ case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+ case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+ case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+ case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+ case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+ case "zookeeperServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseZooKeeperServiceCallServiceDiscoveryConfiguration()); break;
+ case "blacklistServiceFilter": def.setServiceFilterConfiguration(doParseBlacklistServiceCallServiceFilterConfiguration()); break;
+ case "combinedServiceFilter": def.setServiceFilterConfiguration(doParseCombinedServiceCallServiceFilterConfiguration()); break;
+ case "customServiceFilter": def.setServiceFilterConfiguration(doParseCustomServiceCallServiceFilterConfiguration()); break;
+ case "healthyServiceFilter": def.setServiceFilterConfiguration(doParseHealthyServiceCallServiceFilterConfiguration()); break;
+ case "passThroughServiceFilter": def.setServiceFilterConfiguration(doParsePassThroughServiceCallServiceFilterConfiguration()); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ServiceCallExpressionConfiguration doParseServiceCallExpressionConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallExpressionConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "hostHeader": def.setHostHeader(val); break;
+ case "portHeader": def.setPortHeader(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpressionType(v);
+ return true;
+ }
+ return serviceCallConfigurationElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected ServiceCallDefinition doParseServiceCallDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "component": def.setComponent(val); break;
+ case "configurationRef": def.setConfigurationRef(val); break;
+ case "expressionRef": def.setExpressionRef(val); break;
+ case "loadBalancerRef": def.setLoadBalancerRef(val); break;
+ case "name": def.setName(val); break;
+ case "pattern": def.setPattern(ExchangePattern.valueOf(val)); break;
+ case "serviceChooserRef": def.setServiceChooserRef(val); break;
+ case "serviceDiscoveryRef": def.setServiceDiscoveryRef(val); break;
+ case "serviceFilterRef": def.setServiceFilterRef(val); break;
+ case "uri": def.setUri(val); break;
+ default: return processorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "expressionConfiguration": def.setExpressionConfiguration(doParseServiceCallExpressionConfiguration()); break;
+ case "ribbonLoadBalancer": def.setLoadBalancerConfiguration(doParseRibbonServiceCallServiceLoadBalancerConfiguration()); break;
+ case "defaultLoadBalancer": def.setLoadBalancerConfiguration(doParseDefaultServiceCallServiceLoadBalancerConfiguration()); break;
+ case "cachingServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCachingServiceCallServiceDiscoveryConfiguration()); break;
+ case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+ case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+ case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+ case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+ case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+ case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+ case "zookeeperServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseZooKeeperServiceCallServiceDiscoveryConfiguration()); break;
+ case "blacklistServiceFilter": def.setServiceFilterConfiguration(doParseBlacklistServiceCallServiceFilterConfiguration()); break;
+ case "combinedServiceFilter": def.setServiceFilterConfiguration(doParseCombinedServiceCallServiceFilterConfiguration()); break;
+ case "customServiceFilter": def.setServiceFilterConfiguration(doParseCustomServiceCallServiceFilterConfiguration()); break;
+ case "healthyServiceFilter": def.setServiceFilterConfiguration(doParseHealthyServiceCallServiceFilterConfiguration()); break;
+ case "passThroughServiceFilter": def.setServiceFilterConfiguration(doParsePassThroughServiceCallServiceFilterConfiguration()); break;
+ default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ServiceCallServiceChooserConfiguration doParseServiceCallServiceChooserConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ServiceCallServiceChooserConfiguration(),
+ identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected StaticServiceCallServiceDiscoveryConfiguration doParseStaticServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new StaticServiceCallServiceDiscoveryConfiguration(),
+ identifiedTypeAttributeHandler(), (def, key) -> {
+ if ("servers".equals(key)) {
+ doAdd(doParseText(), def.getServers(), def::setServers);
+ return true;
+ }
+ return serviceCallConfigurationElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected ZooKeeperServiceCallServiceDiscoveryConfiguration doParseZooKeeperServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+ return doParse(new ZooKeeperServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+ switch (key) {
+ case "basePath": def.setBasePath(val); break;
+ case "connectionTimeout": def.setConnectionTimeout(val); break;
+ case "namespace": def.setNamespace(val); break;
+ case "nodes": def.setNodes(val); break;
+ case "reconnectBaseSleepTime": def.setReconnectBaseSleepTime(val); break;
+ case "reconnectMaxRetries": def.setReconnectMaxRetries(val); break;
+ case "reconnectMaxSleepTime": def.setReconnectMaxSleepTime(val); break;
+ case "sessionTimeout": def.setSessionTimeout(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, serviceCallConfigurationElementHandler(), noValueHandler());
+ }
+ protected BatchResequencerConfig doParseBatchResequencerConfig() throws IOException, XmlPullParserException {
+ return doParse(new BatchResequencerConfig(), (def, key, val) -> {
+ switch (key) {
+ case "allowDuplicates": def.setAllowDuplicates(val); break;
+ case "batchSize": def.setBatchSize(val); break;
+ case "batchTimeout": def.setBatchTimeout(val); break;
+ case "ignoreInvalidExchanges": def.setIgnoreInvalidExchanges(val); break;
+ case "reverse": def.setReverse(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected StreamResequencerConfig doParseStreamResequencerConfig() throws IOException, XmlPullParserException {
+ return doParse(new StreamResequencerConfig(), (def, key, val) -> {
+ switch (key) {
+ case "capacity": def.setCapacity(val); break;
+ case "comparatorRef": def.setComparatorRef(val); break;
+ case "deliveryAttemptInterval": def.setDeliveryAttemptInterval(val); break;
+ case "ignoreInvalidExchanges": def.setIgnoreInvalidExchanges(val); break;
+ case "rejectOld": def.setRejectOld(val); break;
+ case "timeout": def.setTimeout(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ASN1DataFormat doParseASN1DataFormat() throws IOException, XmlPullParserException {
+ return doParse(new ASN1DataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "clazzName": def.setClazzName(val); break;
+ case "usingIterator": def.setUsingIterator(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected Any23DataFormat doParseAny23DataFormat() throws IOException, XmlPullParserException {
+ return doParse(new Any23DataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "baseURI": def.setBaseURI(val); break;
+ case "outputFormat": def.setOutputFormat(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "configuration": def.setConfiguration(unmarshal(new PropertyDescriptionsAdapter(), doParsePropertyDefinitions())); break;
+ case "extractors": doAdd(doParseText(), def.getExtractors(), def::setExtractors); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected AvroDataFormat doParseAvroDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new AvroDataFormat(), (def, key, val) -> {
+ if ("instanceClassName".equals(key)) {
+ def.setInstanceClassName(val);
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected BarcodeDataFormat doParseBarcodeDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new BarcodeDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "barcodeFormat": def.setBarcodeFormat(val); break;
+ case "height": def.setHeight(val); break;
+ case "imageType": def.setImageType(val); break;
+ case "width": def.setWidth(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected Base64DataFormat doParseBase64DataFormat() throws IOException, XmlPullParserException {
+ return doParse(new Base64DataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "lineLength": def.setLineLength(val); break;
+ case "lineSeparator": def.setLineSeparator(val); break;
+ case "urlSafe": def.setUrlSafe(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected BeanioDataFormat doParseBeanioDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new BeanioDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "beanReaderErrorHandlerType": def.setBeanReaderErrorHandlerType(val); break;
+ case "encoding": def.setEncoding(val); break;
+ case "ignoreInvalidRecords": def.setIgnoreInvalidRecords(val); break;
+ case "ignoreUnexpectedRecords": def.setIgnoreUnexpectedRecords(val); break;
+ case "ignoreUnidentifiedRecords": def.setIgnoreUnidentifiedRecords(val); break;
+ case "mapping": def.setMapping(val); break;
+ case "streamName": def.setStreamName(val); break;
+ case "unmarshalSingleObject": def.setUnmarshalSingleObject(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected BindyDataFormat doParseBindyDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new BindyDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowEmptyStream": def.setAllowEmptyStream(Boolean.valueOf(val)); break;
+ case "classType": def.setClassType(val); break;
+ case "locale": def.setLocale(val); break;
+ case "type": def.setType(BindyType.valueOf(val)); break;
+ case "unwrapSingleInstance": def.setUnwrapSingleInstance(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected CBORDataFormat doParseCBORDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new CBORDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowJmsType": def.setAllowJmsType(val); break;
+ case "allowUnmarshallType": def.setAllowUnmarshallType(val); break;
+ case "collectionTypeName": def.setCollectionTypeName(val); break;
+ case "disableFeatures": def.setDisableFeatures(val); break;
+ case "enableFeatures": def.setEnableFeatures(val); break;
+ case "objectMapper": def.setObjectMapper(val); break;
+ case "prettyPrint": def.setPrettyPrint(val); break;
+ case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+ case "useDefaultObjectMapper": def.setUseDefaultObjectMapper(val); break;
+ case "useList": def.setUseList(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected CryptoDataFormat doParseCryptoDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new CryptoDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "algorithm": def.setAlgorithm(val); break;
+ case "algorithmParameterRef": def.setAlgorithmParameterRef(val); break;
+ case "buffersize": def.setBuffersize(val); break;
+ case "cryptoProvider": def.setCryptoProvider(val); break;
+ case "initVectorRef": def.setInitVectorRef(val); break;
+ case "inline": def.setInline(val); break;
+ case "keyRef": def.setKeyRef(val); break;
+ case "macAlgorithm": def.setMacAlgorithm(val); break;
+ case "shouldAppendHMAC": def.setShouldAppendHMAC(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected CsvDataFormat doParseCsvDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new CsvDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowMissingColumnNames": def.setAllowMissingColumnNames(Boolean.valueOf(val)); break;
+ case "commentMarker": def.setCommentMarker(val); break;
+ case "commentMarkerDisabled": def.setCommentMarkerDisabled(Boolean.valueOf(val)); break;
+ case "delimiter": def.setDelimiter(val); break;
+ case "escape": def.setEscape(val); break;
+ case "escapeDisabled": def.setEscapeDisabled(Boolean.valueOf(val)); break;
+ case "formatName": def.setFormatName(val); break;
+ case "formatRef": def.setFormatRef(val); break;
+ case "headerDisabled": def.setHeaderDisabled(Boolean.valueOf(val)); break;
+ case "ignoreEmptyLines": def.setIgnoreEmptyLines(Boolean.valueOf(val)); break;
+ case "ignoreHeaderCase": def.setIgnoreHeaderCase(Boolean.valueOf(val)); break;
+ case "ignoreSurroundingSpaces": def.setIgnoreSurroundingSpaces(Boolean.valueOf(val)); break;
+ case "lazyLoad": def.setLazyLoad(Boolean.valueOf(val)); break;
+ case "marshallerFactoryRef": def.setMarshallerFactoryRef(val); break;
+ case "nullString": def.setNullString(val); break;
+ case "nullStringDisabled": def.setNullStringDisabled(Boolean.valueOf(val)); break;
+ case "quote": def.setQuote(val); break;
+ case "quoteDisabled": def.setQuoteDisabled(Boolean.valueOf(val)); break;
+ case "quoteMode": def.setQuoteMode(val); break;
+ case "recordConverterRef": def.setRecordConverterRef(val); break;
+ case "recordSeparator": def.setRecordSeparator(val); break;
+ case "recordSeparatorDisabled": def.setRecordSeparatorDisabled(val); break;
+ case "skipHeaderRecord": def.setSkipHeaderRecord(Boolean.valueOf(val)); break;
+ case "trailingDelimiter": def.setTrailingDelimiter(Boolean.valueOf(val)); break;
+ case "trim": def.setTrim(Boolean.valueOf(val)); break;
+ case "useMaps": def.setUseMaps(Boolean.valueOf(val)); break;
+ case "useOrderedMaps": def.setUseOrderedMaps(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("header".equals(key)) {
+ doAdd(doParseText(), def.getHeader(), def::setHeader);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected CustomDataFormat doParseCustomDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new CustomDataFormat(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected DataFormatsDefinition doParseDataFormatsDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DataFormatsDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+ if (v != null) {
+ doAdd(v, def.getDataFormats(), def::setDataFormats);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected FhirJsonDataFormat doParseFhirJsonDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new FhirJsonDataFormat(),
+ fhirDataformatAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected <T extends FhirDataformat> AttributeHandler<T> fhirDataformatAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "dontEncodeElements": def.setDontEncodeElements(asStringSet(val)); break;
+ case "dontStripVersionsFromReferencesAtPaths": def.setDontStripVersionsFromReferencesAtPaths(asStringList(val)); break;
+ case "encodeElements": def.setEncodeElements(asStringSet(val)); break;
+ case "encodeElementsAppliesToChildResourcesOnly": def.setEncodeElementsAppliesToChildResourcesOnly(Boolean.valueOf(val)); break;
+ case "fhirVersion": def.setFhirVersion(val); break;
+ case "omitResourceId": def.setOmitResourceId(Boolean.valueOf(val)); break;
+ case "overrideResourceIdWithBundleEntryFullUrl": def.setOverrideResourceIdWithBundleEntryFullUrl(Boolean.valueOf(val)); break;
+ case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+ case "serverBaseUrl": def.setServerBaseUrl(val); break;
+ case "stripVersionsFromReferences": def.setStripVersionsFromReferences(Boolean.valueOf(val)); break;
+ case "summaryMode": def.setSummaryMode(Boolean.valueOf(val)); break;
+ case "suppressNarratives": def.setSuppressNarratives(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected FhirXmlDataFormat doParseFhirXmlDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new FhirXmlDataFormat(),
+ fhirDataformatAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected FlatpackDataFormat doParseFlatpackDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new FlatpackDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowShortLines": def.setAllowShortLines(Boolean.valueOf(val)); break;
+ case "definition": def.setDefinition(val); break;
+ case "delimiter": def.setDelimiter(val); break;
+ case "fixed": def.setFixed(Boolean.valueOf(val)); break;
+ case "ignoreExtraColumns": def.setIgnoreExtraColumns(Boolean.valueOf(val)); break;
+ case "ignoreFirstRecord": def.setIgnoreFirstRecord(Boolean.valueOf(val)); break;
+ case "parserFactoryRef": def.setParserFactoryRef(val); break;
+ case "textQualifier": def.setTextQualifier(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected GrokDataFormat doParseGrokDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new GrokDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowMultipleMatchesPerLine": def.setAllowMultipleMatchesPerLine(Boolean.valueOf(val)); break;
+ case "flattened": def.setFlattened(Boolean.valueOf(val)); break;
+ case "namedOnly": def.setNamedOnly(Boolean.valueOf(val)); break;
+ case "pattern": def.setPattern(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected GzipDataFormat doParseGzipDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new GzipDataFormat(),
+ dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected HL7DataFormat doParseHL7DataFormat() throws IOException, XmlPullParserException {
+ return doParse(new HL7DataFormat(), (def, key, val) -> {
+ if ("validate".equals(key)) {
+ def.setValidate(Boolean.valueOf(val));
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected IcalDataFormat doParseIcalDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new IcalDataFormat(), (def, key, val) -> {
+ if ("validating".equals(key)) {
+ def.setValidating(Boolean.valueOf(val));
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected JacksonXMLDataFormat doParseJacksonXMLDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new JacksonXMLDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowJmsType": def.setAllowJmsType(val); break;
+ case "allowUnmarshallType": def.setAllowUnmarshallType(val); break;
+ case "collectionTypeName": def.setCollectionTypeName(val); break;
+ case "disableFeatures": def.setDisableFeatures(val); break;
+ case "enableFeatures": def.setEnableFeatures(val); break;
+ case "enableJaxbAnnotationModule": def.setEnableJaxbAnnotationModule(val); break;
+ case "include": def.setInclude(val); break;
+ case "jsonView": def.setJsonView(asClass(val)); break;
+ case "moduleClassNames": def.setModuleClassNames(val); break;
+ case "moduleRefs": def.setModuleRefs(val); break;
+ case "prettyPrint": def.setPrettyPrint(val); break;
+ case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+ case "useList": def.setUseList(val); break;
+ case "xmlMapper": def.setXmlMapper(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected JaxbDataFormat doParseJaxbDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new JaxbDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "contextPath": def.setContextPath(val); break;
+ case "encoding": def.setEncoding(val); break;
+ case "filterNonXmlChars": def.setFilterNonXmlChars(Boolean.valueOf(val)); break;
+ case "fragment": def.setFragment(Boolean.valueOf(val)); break;
+ case "ignoreJAXBElement": def.setIgnoreJAXBElement(Boolean.valueOf(val)); break;
+ case "jaxbProviderProperties": def.setJaxbProviderProperties(val); break;
+ case "mustBeJAXBElement": def.setMustBeJAXBElement(Boolean.valueOf(val)); break;
+ case "namespacePrefixRef": def.setNamespacePrefixRef(val); break;
+ case "noNamespaceSchemaLocation": def.setNoNamespaceSchemaLocation(val); break;
+ case "objectFactory": def.setObjectFactory(Boolean.valueOf(val)); break;
+ case "partClass": def.setPartClass(val); break;
+ case "partNamespace": def.setPartNamespace(val); break;
+ case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+ case "schema": def.setSchema(val); break;
+ case "schemaLocation": def.setSchemaLocation(val); break;
+ case "schemaSeverityLevel": def.setSchemaSeverityLevel(Integer.valueOf(val)); break;
+ case "xmlStreamWriterWrapper": def.setXmlStreamWriterWrapper(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected JsonApiDataFormat doParseJsonApiDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new JsonApiDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "dataFormatTypes": def.setDataFormatTypes(asClassArray(val)); break;
+ case "mainFormatType": def.setMainFormatType(asClass(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected JsonDataFormat doParseJsonDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new JsonDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowJmsType": def.setAllowJmsType(Boolean.valueOf(val)); break;
+ case "allowUnmarshallType": def.setAllowUnmarshallType(Boolean.valueOf(val)); break;
+ case "autoDiscoverObjectMapper": def.setAutoDiscoverObjectMapper(Boolean.valueOf(val)); break;
+ case "collectionTypeName": def.setCollectionTypeName(val); break;
+ case "disableFeatures": def.setDisableFeatures(val); break;
+ case "enableFeatures": def.setEnableFeatures(val); break;
+ case "enableJaxbAnnotationModule": def.setEnableJaxbAnnotationModule(Boolean.valueOf(val)); break;
+ case "include": def.setInclude(val); break;
+ case "jsonView": def.setJsonView(asClass(val)); break;
+ case "library": def.setLibrary(JsonLibrary.valueOf(val)); break;
+ case "moduleClassNames": def.setModuleClassNames(val); break;
+ case "moduleRefs": def.setModuleRefs(val); break;
+ case "objectMapper": def.setObjectMapper(val); break;
+ case "permissions": def.setPermissions(val); break;
+ case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+ case "timezone": def.setTimezone(val); break;
+ case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+ case "useDefaultObjectMapper": def.setUseDefaultObjectMapper(Boolean.valueOf(val)); break;
+ case "useList": def.setUseList(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected LZFDataFormat doParseLZFDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new LZFDataFormat(), (def, key, val) -> {
+ if ("usingParallelCompression".equals(key)) {
+ def.setUsingParallelCompression(Boolean.valueOf(val));
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected MimeMultipartDataFormat doParseMimeMultipartDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new MimeMultipartDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "binaryContent": def.setBinaryContent(Boolean.valueOf(val)); break;
+ case "headersInline": def.setHeadersInline(Boolean.valueOf(val)); break;
+ case "includeHeaders": def.setIncludeHeaders(val); break;
+ case "multipartSubType": def.setMultipartSubType(val); break;
+ case "multipartWithoutAttachment": def.setMultipartWithoutAttachment(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected PGPDataFormat doParsePGPDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new PGPDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "algorithm": def.setAlgorithm(val); break;
+ case "armored": def.setArmored(val); break;
+ case "compressionAlgorithm": def.setCompressionAlgorithm(val); break;
+ case "hashAlgorithm": def.setHashAlgorithm(val); break;
+ case "integrity": def.setIntegrity(val); break;
+ case "keyFileName": def.setKeyFileName(val); break;
+ case "keyUserid": def.setKeyUserid(val); break;
+ case "password": def.setPassword(val); break;
+ case "provider": def.setProvider(val); break;
+ case "signatureKeyFileName": def.setSignatureKeyFileName(val); break;
+ case "signatureKeyRing": def.setSignatureKeyRing(val); break;
+ case "signatureKeyUserid": def.setSignatureKeyUserid(val); break;
+ case "signaturePassword": def.setSignaturePassword(val); break;
+ case "signatureVerificationOption": def.setSignatureVerificationOption(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ProtobufDataFormat doParseProtobufDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new ProtobufDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "contentTypeFormat": def.setContentTypeFormat(val); break;
+ case "instanceClass": def.setInstanceClass(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RssDataFormat doParseRssDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new RssDataFormat(),
+ dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected SoapJaxbDataFormat doParseSoapJaxbDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new SoapJaxbDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "contextPath": def.setContextPath(val); break;
+ case "elementNameStrategyRef": def.setElementNameStrategyRef(val); break;
+ case "encoding": def.setEncoding(val); break;
+ case "namespacePrefixRef": def.setNamespacePrefixRef(val); break;
+ case "schema": def.setSchema(val); break;
+ case "version": def.setVersion(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected SyslogDataFormat doParseSyslogDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new SyslogDataFormat(),
+ dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected TarFileDataFormat doParseTarFileDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new TarFileDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowEmptyDirectory": def.setAllowEmptyDirectory(Boolean.valueOf(val)); break;
+ case "preservePathElements": def.setPreservePathElements(Boolean.valueOf(val)); break;
+ case "usingIterator": def.setUsingIterator(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ThriftDataFormat doParseThriftDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new ThriftDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "contentTypeFormat": def.setContentTypeFormat(val); break;
+ case "instanceClass": def.setInstanceClass(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected TidyMarkupDataFormat doParseTidyMarkupDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new TidyMarkupDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "dataObjectType": def.setDataObjectTypeName(val); break;
+ case "omitXmlDeclaration": def.setOmitXmlDeclaration(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected UniVocityCsvDataFormat doParseUniVocityCsvDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new UniVocityCsvDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "delimiter": def.setDelimiter(val); break;
+ case "quote": def.setQuote(val); break;
+ case "quoteAllFields": def.setQuoteAllFields(Boolean.valueOf(val)); break;
+ case "quoteEscape": def.setQuoteEscape(val); break;
+ default: return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+ }
+ protected <T extends UniVocityAbstractDataFormat> AttributeHandler<T> uniVocityAbstractDataFormatAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "asMap": def.setAsMap(Boolean.valueOf(val)); break;
+ case "comment": def.setComment(val); break;
+ case "emptyValue": def.setEmptyValue(val); break;
+ case "headerExtractionEnabled": def.setHeaderExtractionEnabled(Boolean.valueOf(val)); break;
+ case "headersDisabled": def.setHeadersDisabled(Boolean.valueOf(val)); break;
+ case "ignoreLeadingWhitespaces": def.setIgnoreLeadingWhitespaces(Boolean.valueOf(val)); break;
+ case "ignoreTrailingWhitespaces": def.setIgnoreTrailingWhitespaces(Boolean.valueOf(val)); break;
+ case "lazyLoad": def.setLazyLoad(Boolean.valueOf(val)); break;
+ case "lineSeparator": def.setLineSeparator(val); break;
+ case "normalizedLineSeparator": def.setNormalizedLineSeparator(val); break;
+ case "nullValue": def.setNullValue(val); break;
+ case "numberOfRecordsToRead": def.setNumberOfRecordsToRead(Integer.valueOf(val)); break;
+ case "skipEmptyLines": def.setSkipEmptyLines(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected <T extends UniVocityAbstractDataFormat> ElementHandler<T> uniVocityAbstractDataFormatElementHandler() {
+ return (def, key) -> {
+ if ("univocity-header".equals(key)) {
+ doAdd(doParseUniVocityHeader(), def.getHeaders(), def::setHeaders);
+ return true;
+ }
+ return false;
+ };
+ }
+ protected UniVocityHeader doParseUniVocityHeader() throws IOException, XmlPullParserException {
+ return doParse(new UniVocityHeader(), (def, key, val) -> {
+ if ("length".equals(key)) {
+ def.setLength(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), (def, val) -> def.setName(val));
+ }
+ protected UniVocityFixedWidthDataFormat doParseUniVocityFixedWidthDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new UniVocityFixedWidthDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "padding": def.setPadding(val); break;
+ case "recordEndsOnNewline": def.setRecordEndsOnNewline(Boolean.valueOf(val)); break;
+ case "skipTrailingCharsUntilNewline": def.setSkipTrailingCharsUntilNewline(Boolean.valueOf(val)); break;
+ default: return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+ }
+ protected UniVocityTsvDataFormat doParseUniVocityTsvDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new UniVocityTsvDataFormat(), (def, key, val) -> {
+ if ("escapeChar".equals(key)) {
+ def.setEscapeChar(val);
+ return true;
+ }
+ return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+ }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+ }
+ protected XMLSecurityDataFormat doParseXMLSecurityDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new XMLSecurityDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "addKeyValueForEncryptedKey": def.setAddKeyValueForEncryptedKey(Boolean.valueOf(val)); break;
+ case "digestAlgorithm": def.setDigestAlgorithm(val); break;
+ case "keyCipherAlgorithm": def.setKeyCipherAlgorithm(val); break;
+ case "keyOrTrustStoreParametersRef": def.setKeyOrTrustStoreParametersRef(val); break;
+ case "keyPassword": def.setKeyPassword(val); break;
+ case "mgfAlgorithm": def.setMgfAlgorithm(val); break;
+ case "passPhrase": def.setPassPhrase(val); break;
+ case "passPhraseByte": def.setPassPhraseByte(asByteArray(val)); break;
+ case "recipientKeyAlias": def.setRecipientKeyAlias(val); break;
+ case "secureTag": def.setSecureTag(val); break;
+ case "secureTagContents": def.setSecureTagContents(Boolean.valueOf(val)); break;
+ case "xmlCipherAlgorithm": def.setXmlCipherAlgorithm(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected XStreamDataFormat doParseXStreamDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "driver": def.setDriver(val); break;
+ case "driverRef": def.setDriverRef(val); break;
+ case "encoding": def.setEncoding(val); break;
+ case "mode": def.setMode(val); break;
+ case "permissions": def.setPermissions(val); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "aliases": def.setAliases(unmarshal(new XStreamDataFormat.AliasAdapter(), doParseAliasList())); break;
+ case "converters": def.setConverters(unmarshal(new XStreamDataFormat.ConvertersAdapter(), doParseConverterList())); break;
+ case "implicitCollections": def.setImplicitCollections(unmarshal(new XStreamDataFormat.ImplicitCollectionsAdapter(), doParseImplicitCollectionList())); break;
+ case "omitFields": def.setOmitFields(unmarshal(new XStreamDataFormat.OmitFieldsAdapter(), doParseOmitFieldList())); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.ConverterList doParseConverterList() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.ConverterList(),
+ noAttributeHandler(), (def, key) -> {
+ if ("converter".equals(key)) {
+ doAdd(doParseConverterEntry(), def.getList(), def::setList);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.AliasList doParseAliasList() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.AliasList(),
+ noAttributeHandler(), (def, key) -> {
+ if ("alias".equals(key)) {
+ doAdd(doParseAliasEntry(), def.getList(), def::setList);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.OmitFieldList doParseOmitFieldList() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.OmitFieldList(),
+ noAttributeHandler(), (def, key) -> {
+ if ("omitField".equals(key)) {
+ doAdd(doParseOmitFieldEntry(), def.getList(), def::setList);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.ImplicitCollectionList doParseImplicitCollectionList() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.ImplicitCollectionList(),
+ noAttributeHandler(), (def, key) -> {
+ if ("class".equals(key)) {
+ doAdd(doParseImplicitCollectionEntry(), def.getList(), def::setList);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.AliasEntry doParseAliasEntry() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.AliasEntry(), (def, key, val) -> {
+ switch (key) {
+ case "class": def.setClsName(val); break;
+ case "name": def.setName(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected XStreamDataFormat.ConverterEntry doParseConverterEntry() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.ConverterEntry(), (def, key, val) -> {
+ if ("class".equals(key)) {
+ def.setClsName(val);
+ return true;
+ }
+ return false;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected XStreamDataFormat.ImplicitCollectionEntry doParseImplicitCollectionEntry() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.ImplicitCollectionEntry(), (def, key, val) -> {
+ if ("name".equals(key)) {
+ def.setClsName(val);
+ return true;
+ }
+ return false;
+ }, (def, key) -> {
+ if ("field".equals(key)) {
+ doAdd(doParseText(), def.getFields(), def::setFields);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XStreamDataFormat.OmitFieldEntry doParseOmitFieldEntry() throws IOException, XmlPullParserException {
+ return doParse(new XStreamDataFormat.OmitFieldEntry(), (def, key, val) -> {
+ if ("class".equals(key)) {
+ def.setClsName(val);
+ return true;
+ }
+ return false;
+ }, (def, key) -> {
+ if ("field".equals(key)) {
+ doAdd(doParseText(), def.getFields(), def::setFields);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected XmlRpcDataFormat doParseXmlRpcDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new XmlRpcDataFormat(), (def, key, val) -> {
+ if ("request".equals(key)) {
+ def.setRequest(Boolean.valueOf(val));
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected YAMLDataFormat doParseYAMLDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new YAMLDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowAnyType": def.setAllowAnyType(Boolean.valueOf(val)); break;
+ case "constructor": def.setConstructor(val); break;
+ case "dumperOptions": def.setDumperOptions(val); break;
+ case "library": def.setLibrary(YAMLLibrary.valueOf(val)); break;
+ case "prettyFlow": def.setPrettyFlow(Boolean.valueOf(val)); break;
+ case "representer": def.setRepresenter(val); break;
+ case "resolver": def.setResolver(val); break;
+ case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+ case "useApplicationContextClassLoader": def.setUseApplicationContextClassLoader(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("typeFilter".equals(key)) {
+ doAdd(doParseYAMLTypeFilterDefinition(), def.getTypeFilters(), def::setTypeFilters);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected YAMLTypeFilterDefinition doParseYAMLTypeFilterDefinition() throws IOException, XmlPullParserException {
+ return doParse(new YAMLTypeFilterDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "type": def.setType(YAMLTypeFilterType.valueOf(val)); break;
+ case "value": def.setValue(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ZipDeflaterDataFormat doParseZipDeflaterDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new ZipDeflaterDataFormat(), (def, key, val) -> {
+ if ("compressionLevel".equals(key)) {
+ def.setCompressionLevel(Integer.valueOf(val));
+ return true;
+ }
+ return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ZipFileDataFormat doParseZipFileDataFormat() throws IOException, XmlPullParserException {
+ return doParse(new ZipFileDataFormat(), (def, key, val) -> {
+ switch (key) {
+ case "allowEmptyDirectory": def.setAllowEmptyDirectory(Boolean.valueOf(val)); break;
+ case "preservePathElements": def.setPreservePathElements(Boolean.valueOf(val)); break;
+ case "usingIterator": def.setUsingIterator(Boolean.valueOf(val)); break;
+ default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected ConstantExpression doParseConstantExpression() throws IOException, XmlPullParserException {
+ return doParse(new ConstantExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected ExchangePropertyExpression doParseExchangePropertyExpression() throws IOException, XmlPullParserException {
+ return doParse(new ExchangePropertyExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected GroovyExpression doParseGroovyExpression() throws IOException, XmlPullParserException {
+ return doParse(new GroovyExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected HeaderExpression doParseHeaderExpression() throws IOException, XmlPullParserException {
+ return doParse(new HeaderExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected Hl7TerserExpression doParseHl7TerserExpression() throws IOException, XmlPullParserException {
+ return doParse(new Hl7TerserExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected JsonPathExpression doParseJsonPathExpression() throws IOException, XmlPullParserException {
+ return doParse(new JsonPathExpression(), (def, key, val) -> {
+ switch (key) {
+ case "allowEasyPredicate": def.setAllowEasyPredicate(val); break;
+ case "allowSimple": def.setAllowSimple(val); break;
+ case "headerName": def.setHeaderName(val); break;
+ case "resultType": def.setResultTypeName(val); break;
+ case "suppressExceptions": def.setSuppressExceptions(val); break;
+ case "writeAsString": def.setWriteAsString(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected LanguageExpression doParseLanguageExpression() throws IOException, XmlPullParserException {
+ return doParse(new LanguageExpression(), (def, key, val) -> {
+ if ("language".equals(key)) {
+ def.setLanguage(val);
+ return true;
+ }
+ return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected MethodCallExpression doParseMethodCallExpression() throws IOException, XmlPullParserException {
+ return doParse(new MethodCallExpression(), (def, key, val) -> {
+ switch (key) {
+ case "beanType": def.setBeanTypeName(val); break;
+ case "method": def.setMethod(val); break;
+ case "ref": def.setRef(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected MvelExpression doParseMvelExpression() throws IOException, XmlPullParserException {
+ return doParse(new MvelExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected OgnlExpression doParseOgnlExpression() throws IOException, XmlPullParserException {
+ return doParse(new OgnlExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected RefExpression doParseRefExpression() throws IOException, XmlPullParserException {
+ return doParse(new RefExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected SimpleExpression doParseSimpleExpression() throws IOException, XmlPullParserException {
+ return doParse(new SimpleExpression(), (def, key, val) -> {
+ if ("resultType".equals(key)) {
+ def.setResultTypeName(val);
+ return true;
+ }
+ return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected SpELExpression doParseSpELExpression() throws IOException, XmlPullParserException {
+ return doParse(new SpELExpression(),
+ expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected TokenizerExpression doParseTokenizerExpression() throws IOException, XmlPullParserException {
+ return doParse(new TokenizerExpression(), (def, key, val) -> {
+ switch (key) {
+ case "endToken": def.setEndToken(val); break;
+ case "group": def.setGroup(val); break;
+ case "groupDelimiter": def.setGroupDelimiter(val); break;
+ case "headerName": def.setHeaderName(val); break;
+ case "includeTokens": def.setIncludeTokens(val); break;
+ case "inheritNamespaceTagName": def.setInheritNamespaceTagName(val); break;
+ case "regex": def.setRegex(val); break;
+ case "skipFirst": def.setSkipFirst(val); break;
+ case "token": def.setToken(val); break;
+ case "xml": def.setXml(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected XMLTokenizerExpression doParseXMLTokenizerExpression() throws IOException, XmlPullParserException {
+ return doParse(new XMLTokenizerExpression(), (def, key, val) -> {
+ switch (key) {
+ case "group": def.setGroup(val); break;
+ case "headerName": def.setHeaderName(val); break;
+ case "mode": def.setMode(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected XPathExpression doParseXPathExpression() throws IOException, XmlPullParserException {
+ return doParse(new XPathExpression(), (def, key, val) -> {
+ switch (key) {
+ case "documentType": def.setDocumentTypeName(val); break;
+ case "factoryRef": def.setFactoryRef(val); break;
+ case "headerName": def.setHeaderName(val); break;
+ case "logNamespaces": def.setLogNamespaces(val); break;
+ case "objectModel": def.setObjectModel(val); break;
+ case "resultType": def.setResultTypeName(val); break;
+ case "saxon": def.setSaxon(val); break;
+ case "threadSafety": def.setThreadSafety(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected XQueryExpression doParseXQueryExpression() throws IOException, XmlPullParserException {
+ return doParse(new XQueryExpression(), (def, key, val) -> {
+ switch (key) {
+ case "headerName": def.setHeaderName(val); break;
+ case "type": def.setType(val); break;
+ default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), expressionDefinitionValueHandler());
+ }
+ protected CustomLoadBalancerDefinition doParseCustomLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new CustomLoadBalancerDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return identifiedTypeAttributeHandler().accept(def, key, val);
+ }, noElementHandler(), noValueHandler());
+ }
+ protected FailoverLoadBalancerDefinition doParseFailoverLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new FailoverLoadBalancerDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "maximumFailoverAttempts": def.setMaximumFailoverAttempts(val); break;
+ case "roundRobin": def.setRoundRobin(val); break;
+ case "sticky": def.setSticky(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("exception".equals(key)) {
+ doAdd(doParseText(), def.getExceptions(), def::setExceptions);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected RandomLoadBalancerDefinition doParseRandomLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RandomLoadBalancerDefinition(),
+ identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected RoundRobinLoadBalancerDefinition doParseRoundRobinLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RoundRobinLoadBalancerDefinition(),
+ identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected StickyLoadBalancerDefinition doParseStickyLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new StickyLoadBalancerDefinition(),
+ identifiedTypeAttributeHandler(), (def, key) -> {
+ if ("correlationExpression".equals(key)) {
+ def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected TopicLoadBalancerDefinition doParseTopicLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new TopicLoadBalancerDefinition(),
+ identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected WeightedLoadBalancerDefinition doParseWeightedLoadBalancerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new WeightedLoadBalancerDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "distributionRatio": def.setDistributionRatio(val); break;
+ case "distributionRatioDelimiter": def.setDistributionRatioDelimiter(val); break;
+ case "roundRobin": def.setRoundRobin(val); break;
+ default: return identifiedTypeAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected DeleteVerbDefinition doParseDeleteVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DeleteVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected <T extends VerbDefinition> AttributeHandler<T> verbDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "apiDocs": def.setApiDocs(val); break;
+ case "bindingMode": def.setBindingMode(val); break;
+ case "clientRequestValidation": def.setClientRequestValidation(val); break;
+ case "consumes": def.setConsumes(val); break;
+ case "enableCORS": def.setEnableCORS(val); break;
+ case "method": def.setMethod(val); break;
+ case "outType": def.setOutType(val); break;
+ case "produces": def.setProduces(val); break;
+ case "routeId": def.setRouteId(val); break;
+ case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+ case "type": def.setType(val); break;
+ case "uri": def.setUri(val); break;
+ default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ };
+ }
+ protected <T extends VerbDefinition> ElementHandler<T> verbDefinitionElementHandler() {
+ return (def, key) -> {
+ switch (key) {
+ case "param": doAdd(doParseRestOperationParamDefinition(), def.getParams(), def::setParams); break;
+ case "responseMessage": doAdd(doParseRestOperationResponseMsgDefinition(), def.getResponseMsgs(), def::setResponseMsgs); break;
+ case "security": doAdd(doParseSecurityDefinition(), def.getSecurity(), def::setSecurity); break;
+ case "to": def.setToOrRoute(doParseToDefinition()); break;
+ case "toD": def.setToOrRoute(doParseToDynamicDefinition()); break;
+ case "route": def.setToOrRoute(doParseRouteDefinition()); break;
+ default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }
+ return true;
+ };
+ }
+ protected VerbDefinition doParseVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new VerbDefinition(), verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected RestOperationParamDefinition doParseRestOperationParamDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestOperationParamDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "arrayType": def.setArrayType(val); break;
+ case "collectionFormat": def.setCollectionFormat(CollectionFormat.valueOf(val)); break;
+ case "dataFormat": def.setDataFormat(val); break;
+ case "dataType": def.setDataType(val); break;
+ case "defaultValue": def.setDefaultValue(val); break;
+ case "description": def.setDescription(val); break;
+ case "name": def.setName(val); break;
+ case "required": def.setRequired(Boolean.valueOf(val)); break;
+ case "type": def.setType(RestParamType.valueOf(val)); break;
+ default: return false;
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "value": doAdd(doParseText(), def.getAllowableValues(), def::setAllowableValues); break;
+ case "examples": doAdd(doParseRestPropertyDefinition(), def.getExamples(), def::setExamples); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RestOperationResponseMsgDefinition doParseRestOperationResponseMsgDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestOperationResponseMsgDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "code": def.setCode(val); break;
+ case "message": def.setMessage(val); break;
+ case "responseModel": def.setResponseModel(val); break;
+ default: return false;
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "examples": doAdd(doParseRestPropertyDefinition(), def.getExamples(), def::setExamples); break;
+ case "header": doAdd(doParseRestOperationResponseHeaderDefinition(), def.getHeaders(), def::setHeaders); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected SecurityDefinition doParseSecurityDefinition() throws IOException, XmlPullParserException {
+ return doParse(new SecurityDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "key": def.setKey(val); break;
+ case "scopes": def.setScopes(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected GetVerbDefinition doParseGetVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new GetVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected HeadVerbDefinition doParseHeadVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new HeadVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected PatchVerbDefinition doParsePatchVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PatchVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected PostVerbDefinition doParsePostVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PostVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected PutVerbDefinition doParsePutVerbDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PutVerbDefinition(),
+ verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+ }
+ protected RestConfigurationDefinition doParseRestConfigurationDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestConfigurationDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "apiComponent": def.setApiComponent(val); break;
+ case "apiContextIdPattern": def.setApiContextIdPattern(val); break;
+ case "apiContextListing": def.setApiContextListing(Boolean.valueOf(val)); break;
+ case "apiContextPath": def.setApiContextPath(val); break;
+ case "apiContextRouteId": def.setApiContextRouteId(val); break;
+ case "apiHost": def.setApiHost(val); break;
+ case "apiVendorExtension": def.setApiVendorExtension(Boolean.valueOf(val)); break;
+ case "bindingMode": def.setBindingMode(RestBindingMode.valueOf(val)); break;
+ case "clientRequestValidation": def.setClientRequestValidation(Boolean.valueOf(val)); break;
+ case "component": def.setComponent(val); break;
+ case "contextPath": def.setContextPath(val); break;
+ case "enableCORS": def.setEnableCORS(Boolean.valueOf(val)); break;
+ case "host": def.setHost(val); break;
+ case "hostNameResolver": def.setHostNameResolver(RestHostNameResolver.valueOf(val)); break;
+ case "jsonDataFormat": def.setJsonDataFormat(val); break;
+ case "port": def.setPort(val); break;
+ case "producerApiDoc": def.setProducerApiDoc(val); break;
+ case "producerComponent": def.setProducerComponent(val); break;
+ case "scheme": def.setScheme(val); break;
+ case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(Boolean.valueOf(val)); break;
+ case "useXForwardHeaders": def.setUseXForwardHeaders(Boolean.valueOf(val)); break;
+ case "xmlDataFormat": def.setXmlDataFormat(val); break;
+ default: return false;
+ }
+ return true;
+ }, (def, key) -> {
+ switch (key) {
+ case "apiProperty": doAdd(doParseRestPropertyDefinition(), def.getApiProperties(), def::setApiProperties); break;
+ case "componentProperty": doAdd(doParseRestPropertyDefinition(), def.getComponentProperties(), def::setComponentProperties); break;
+ case "consumerProperty": doAdd(doParseRestPropertyDefinition(), def.getConsumerProperties(), def::setConsumerProperties); break;
+ case "corsHeaders": doAdd(doParseRestPropertyDefinition(), def.getCorsHeaders(), def::setCorsHeaders); break;
+ case "dataFormatProperty": doAdd(doParseRestPropertyDefinition(), def.getDataFormatProperties(), def::setDataFormatProperties); break;
+ case "endpointProperty": doAdd(doParseRestPropertyDefinition(), def.getEndpointProperties(), def::setEndpointProperties); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RestPropertyDefinition doParseRestPropertyDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestPropertyDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "key": def.setKey(val); break;
+ case "value": def.setValue(val); break;
+ default: return false;
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RestSecuritiesDefinition doParseRestSecuritiesDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestSecuritiesDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "apiKey": doAdd(doParseRestSecurityApiKey(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+ case "basicAuth": doAdd(doParseRestSecurityBasicAuth(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+ case "oauth2": doAdd(doParseRestSecurityOAuth2(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected RestOperationResponseHeaderDefinition doParseRestOperationResponseHeaderDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestOperationResponseHeaderDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "arrayType": def.setArrayType(val); break;
+ case "collectionFormat": def.setCollectionFormat(CollectionFormat.valueOf(val)); break;
+ case "dataFormat": def.setDataFormat(val); break;
+ case "dataType": def.setDataType(val); break;
+ case "description": def.setDescription(val); break;
+ case "example": def.setExample(val); break;
+ case "name": def.setName(val); break;
+ default: return false;
+ }
+ return true;
+ }, (def, key) -> {
+ if ("value".equals(key)) {
+ doAdd(doParseText(), def.getAllowableValues(), def::setAllowableValues);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected <T extends RestSecurityDefinition> AttributeHandler<T> restSecurityDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "description": def.setDescription(val); break;
+ case "key": def.setKey(val); break;
+ default: return false;
+ }
+ return true;
+ };
+ }
+ protected RestSecurityApiKey doParseRestSecurityApiKey() throws IOException, XmlPullParserException {
+ return doParse(new RestSecurityApiKey(), (def, key, val) -> {
+ switch (key) {
+ case "inHeader": def.setInHeader(Boolean.valueOf(val)); break;
+ case "inQuery": def.setInQuery(Boolean.valueOf(val)); break;
+ case "name": def.setName(val); break;
+ default: return restSecurityDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected RestSecurityBasicAuth doParseRestSecurityBasicAuth() throws IOException, XmlPullParserException {
+ return doParse(new RestSecurityBasicAuth(),
+ restSecurityDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+ }
+ protected RestSecurityOAuth2 doParseRestSecurityOAuth2() throws IOException, XmlPullParserException {
+ return doParse(new RestSecurityOAuth2(), (def, key, val) -> {
+ switch (key) {
+ case "authorizationUrl": def.setAuthorizationUrl(val); break;
+ case "flow": def.setFlow(val); break;
+ case "tokenUrl": def.setTokenUrl(val); break;
+ default: return restSecurityDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, (def, key) -> {
+ if ("scopes".equals(key)) {
+ doAdd(doParseRestPropertyDefinition(), def.getScopes(), def::setScopes);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ public RestsDefinition parseRestsDefinition()
+ throws IOException, XmlPullParserException {
+ expectTag("rests");
+ return doParseRestsDefinition();
+ }
+ protected RestsDefinition doParseRestsDefinition() throws IOException, XmlPullParserException {
+ return doParse(new RestsDefinition(),
+ optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+ if ("rest".equals(key)) {
+ doAdd(doParseRestDefinition(), def.getRests(), def::setRests);
+ return true;
+ }
+ return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+ }, noValueHandler());
+ }
+ protected CustomTransformerDefinition doParseCustomTransformerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new CustomTransformerDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "className": def.setClassName(val); break;
+ case "ref": def.setRef(val); break;
+ default: return transformerDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected <T extends TransformerDefinition> AttributeHandler<T> transformerDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ switch (key) {
+ case "fromType": def.setFromType(val); break;
+ case "scheme": def.setScheme(val); break;
+ case "toType": def.setToType(val); break;
+ default: return false;
+ }
+ return true;
+ };
+ }
+ protected DataFormatTransformerDefinition doParseDataFormatTransformerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new DataFormatTransformerDefinition(), (def, key, val) -> {
+ if ("ref".equals(key)) {
+ def.setRef(val);
+ return true;
+ }
+ return transformerDefinitionAttributeHandler().accept(def, key, val);
+ }, (def, key) -> {
+ DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+ if (v != null) {
+ def.setDataFormatType(v);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected EndpointTransformerDefinition doParseEndpointTransformerDefinition() throws IOException, XmlPullParserException {
+ return doParse(new EndpointTransformerDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "ref": def.setRef(val); break;
+ case "uri": def.setUri(val); break;
+ default: return transformerDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected TransformersDefinition doParseTransformersDefinition() throws IOException, XmlPullParserException {
+ return doParse(new TransformersDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "dataFormatTransformer": doAdd(doParseDataFormatTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+ case "endpointTransformer": doAdd(doParseEndpointTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+ case "customTransformer": doAdd(doParseCustomTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected CustomValidatorDefinition doParseCustomValidatorDefinition() throws IOException, XmlPullParserException {
+ return doParse(new CustomValidatorDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "className": def.setClassName(val); break;
+ case "ref": def.setRef(val); break;
+ default: return validatorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected <T extends ValidatorDefinition> AttributeHandler<T> validatorDefinitionAttributeHandler() {
+ return (def, key, val) -> {
+ if ("type".equals(key)) {
+ def.setType(val);
+ return true;
+ }
+ return false;
+ };
+ }
+ protected EndpointValidatorDefinition doParseEndpointValidatorDefinition() throws IOException, XmlPullParserException {
+ return doParse(new EndpointValidatorDefinition(), (def, key, val) -> {
+ switch (key) {
+ case "ref": def.setRef(val); break;
+ case "uri": def.setUri(val); break;
+ default: return validatorDefinitionAttributeHandler().accept(def, key, val);
+ }
+ return true;
+ }, noElementHandler(), noValueHandler());
+ }
+ protected PredicateValidatorDefinition doParsePredicateValidatorDefinition() throws IOException, XmlPullParserException {
+ return doParse(new PredicateValidatorDefinition(),
+ validatorDefinitionAttributeHandler(), (def, key) -> {
+ ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+ if (v != null) {
+ def.setExpression(v);
+ return true;
+ }
+ return false;
+ }, noValueHandler());
+ }
+ protected ValidatorsDefinition doParseValidatorsDefinition() throws IOException, XmlPullParserException {
+ return doParse(new ValidatorsDefinition(),
+ noAttributeHandler(), (def, key) -> {
+ switch (key) {
+ case "endpointValidator": doAdd(doParseEndpointValidatorDefinition(), def.getValidators(), def::setValidators); break;
+ case "predicateValidator": doAdd(doParsePredicateValidatorDefinition(), def.getValidators(), def::setValidators); break;
+ case "customValidator": doAdd(doParseCustomValidatorDefinition(), def.getValidators(), def::setValidators); break;
+ default: return false;
+ }
+ return true;
+ }, noValueHandler());
+ }
+ protected ProcessorDefinition doParseProcessorDefinitionRef(String key) throws IOException, XmlPullParserException {
+ switch (key) {
+ case "aggregate": return doParseAggregateDefinition();
+ case "bean": return doParseBeanDefinition();
+ case "doCatch": return doParseCatchDefinition();
+ case "when": return doParseWhenDefinition();
+ case "choice": return doParseChoiceDefinition();
+ case "otherwise": return doParseOtherwiseDefinition();
+ case "circuitBreaker": return doParseCircuitBreakerDefinition();
+ case "claimCheck": return doParseClaimCheckDefinition();
+ case "convertBodyTo": return doParseConvertBodyDefinition();
+ case "delay": return doParseDelayDefinition();
+ case "dynamicRouter": return doParseDynamicRouterDefinition();
+ case "enrich": return doParseEnrichDefinition();
+ case "filter": return doParseFilterDefinition();
+ case "doFinally": return doParseFinallyDefinition();
+ case "idempotentConsumer": return doParseIdempotentConsumerDefinition();
+ case "inOnly": return doParseInOnlyDefinition();
+ case "inOut": return doParseInOutDefinition();
+ case "intercept": return doParseInterceptDefinition();
+ case "interceptFrom": return doParseInterceptFromDefinition();
+ case "interceptSendToEndpoint": return doParseInterceptSendToEndpointDefinition();
+ case "loadBalance": return doParseLoadBalanceDefinition();
+ case "log": return doParseLogDefinition();
+ case "loop": return doParseLoopDefinition();
+ case "marshal": return doParseMarshalDefinition();
+ case "multicast": return doParseMulticastDefinition();
+ case "onCompletion": return doParseOnCompletionDefinition();
+ case "onException": return doParseOnExceptionDefinition();
+ case "onFallback": return doParseOnFallbackDefinition();
+ case "pipeline": return doParsePipelineDefinition();
+ case "policy": return doParsePolicyDefinition();
+ case "pollEnrich": return doParsePollEnrichDefinition();
+ case "process": return doParseProcessDefinition();
+ case "recipientList": return doParseRecipientListDefinition();
+ case "removeHeader": return doParseRemoveHeaderDefinition();
+ case "removeHeaders": return doParseRemoveHeadersDefinition();
+ case "removeProperties": return doParseRemovePropertiesDefinition();
+ case "removeProperty": return doParseRemovePropertyDefinition();
+ case "resequence": return doParseResequenceDefinition();
+ case "rollback": return doParseRollbackDefinition();
+ case "route": return doParseRouteDefinition();
+ case "routingSlip": return doParseRoutingSlipDefinition();
+ case "saga": return doParseSagaDefinition();
+ case "sample": return doParseSamplingDefinition();
+ case "script": return doParseScriptDefinition();
+ case "setBody": return doParseSetBodyDefinition();
+ case "setExchangePattern": return doParseSetExchangePatternDefinition();
+ case "setHeader": return doParseSetHeaderDefinition();
+ case "setProperty": return doParseSetPropertyDefinition();
+ case "sort": return doParseSortDefinition();
+ case "split": return doParseSplitDefinition();
+ case "step": return doParseStepDefinition();
+ case "stop": return doParseStopDefinition();
+ case "threads": return doParseThreadsDefinition();
+ case "throttle": return doParseThrottleDefinition();
+ case "throwException": return doParseThrowExceptionDefinition();
+ case "to": return doParseToDefinition();
+ case "toD": return doParseToDynamicDefinition();
+ case "transacted": return doParseTransactedDefinition();
+ case "transform": return doParseTransformDefinition();
+ case "doTry": return doParseTryDefinition();
+ case "unmarshal": return doParseUnmarshalDefinition();
+ case "validate": return doParseValidateDefinition();
+ case "whenSkipSendToEndpoint": return doParseWhenSkipSendToEndpointDefinition();
+ case "wireTap": return doParseWireTapDefinition();
+ case "serviceCall": return doParseServiceCallDefinition();
+ default: return null;
+ }
+ }
+ protected ExpressionDefinition doParseExpressionDefinitionRef(String key) throws IOException, XmlPullParserException {
+ switch (key) {
+ case "expressionDefinition": return doParseExpressionDefinition();
+ case "constant": return doParseConstantExpression();
+ case "exchangeProperty": return doParseExchangePropertyExpression();
+ case "groovy": return doParseGroovyExpression();
+ case "header": return doParseHeaderExpression();
+ case "hl7terser": return doParseHl7TerserExpression();
+ case "jsonpath": return doParseJsonPathExpression();
+ case "language": return doParseLanguageExpression();
+ case "method": return doParseMethodCallExpression();
+ case "mvel": return doParseMvelExpression();
+ case "ognl": return doParseOgnlExpression();
+ case "ref": return doParseRefExpression();
+ case "simple": return doParseSimpleExpression();
+ case "spel": return doParseSpELExpression();
+ case "tokenize": return doParseTokenizerExpression();
+ case "xtokenize": return doParseXMLTokenizerExpression();
+ case "xpath": return doParseXPathExpression();
+ case "xquery": return doParseXQueryExpression();
+ default: return null;
+ }
+ }
+ protected DataFormatDefinition doParseDataFormatDefinitionRef(String key) throws IOException, XmlPullParserException {
+ switch (key) {
+ case "asn1": return doParseASN1DataFormat();
+ case "any23": return doParseAny23DataFormat();
+ case "avro": return doParseAvroDataFormat();
+ case "barcode": return doParseBarcodeDataFormat();
+ case "base64": return doParseBase64DataFormat();
+ case "beanio": return doParseBeanioDataFormat();
+ case "bindy": return doParseBindyDataFormat();
+ case "cbor": return doParseCBORDataFormat();
+ case "crypto": return doParseCryptoDataFormat();
+ case "csv": return doParseCsvDataFormat();
+ case "customDataFormat": return doParseCustomDataFormat();
+ case "fhirJson": return doParseFhirJsonDataFormat();
+ case "fhirXml": return doParseFhirXmlDataFormat();
+ case "flatpack": return doParseFlatpackDataFormat();
+ case "grok": return doParseGrokDataFormat();
+ case "gzipdeflater": return doParseGzipDataFormat();
+ case "hl7": return doParseHL7DataFormat();
+ case "ical": return doParseIcalDataFormat();
+ case "jacksonxml": return doParseJacksonXMLDataFormat();
+ case "jaxb": return doParseJaxbDataFormat();
+ case "jsonApi": return doParseJsonApiDataFormat();
+ case "json": return doParseJsonDataFormat();
+ case "lzf": return doParseLZFDataFormat();
+ case "mime-multipart": return doParseMimeMultipartDataFormat();
+ case "pgp": return doParsePGPDataFormat();
+ case "protobuf": return doParseProtobufDataFormat();
+ case "rss": return doParseRssDataFormat();
+ case "soapjaxb": return doParseSoapJaxbDataFormat();
+ case "syslog": return doParseSyslogDataFormat();
+ case "tarfile": return doParseTarFileDataFormat();
+ case "thrift": return doParseThriftDataFormat();
+ case "tidyMarkup": return doParseTidyMarkupDataFormat();
+ case "univocity-csv": return doParseUniVocityCsvDataFormat();
+ case "univocity-fixed": return doParseUniVocityFixedWidthDataFormat();
+ case "univocity-tsv": return doParseUniVocityTsvDataFormat();
+ case "secureXML": return doParseXMLSecurityDataFormat();
+ case "xstream": return doParseXStreamDataFormat();
+ case "xmlrpc": return doParseXmlRpcDataFormat();
+ case "yaml": return doParseYAMLDataFormat();
+ case "zipdeflater": return doParseZipDeflaterDataFormat();
+ case "zipfile": return doParseZipFileDataFormat();
+ default: return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java
new file mode 100644
index 0000000..1126078
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java
@@ -0,0 +1,3243 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
+/*
+ * Copyright (c) 2003 Extreme! Lab, Indiana University. All rights reserved.
+ *
+ * This software is open source. See the bottom of this file for the license.
+ *
+ * $Id: MXParser.java,v 1.52 2006/11/09 18:29:37 aslom Exp $
+ */
+
+package org.apache.camel.xml.io;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+//TODO best handling of interning issues
+// have isAllNewStringInterned ???
+
+//TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6
+
+//TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf()
+
+/**
+ * Absolutely minimal implementation of XMLPULL V1 API
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public class MXParser
+ implements XmlPullParser {
+ //NOTE: no interning of those strings --> by Java lang spec they MUST be already interned
+ protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace";
+ protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+ protected final static String FEATURE_XML_ROUNDTRIP =
+ //"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+ "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+ protected final static String FEATURE_NAMES_INTERNED =
+ "http://xmlpull.org/v1/doc/features.html#names-interned";
+ protected final static String PROPERTY_XMLDECL_VERSION =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-version";
+ protected final static String PROPERTY_XMLDECL_STANDALONE =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone";
+ protected final static String PROPERTY_XMLDECL_CONTENT =
+ "http://xmlpull.org/v1/doc/properties.html#xmldecl-content";
+ protected final static String PROPERTY_LOCATION =
+ "http://xmlpull.org/v1/doc/properties.html#location";
+
+ /**
+ * Implementation notice:
+ * the is instance variable that controls if newString() is interning.
+ * <p><b>NOTE:</b> newStringIntern <b>always</b> returns interned strings
+ * and newString MAY return interned String depending on this variable.
+ * <p><b>NOTE:</b> by default in this minimal implementation it is false!
+ */
+ protected boolean allStringsInterned;
+
+ protected void resetStringCache() {
+ //System.out.println("resetStringCache() minimum called");
+ }
+
+ protected String newString(char[] cbuf, int off, int len) {
+ return new String(cbuf, off, len);
+ }
+
+ protected String newStringIntern(char[] cbuf, int off, int len) {
+ return (new String(cbuf, off, len)).intern();
+ }
+
+ private static final boolean TRACE_SIZING = false;
+
+ // NOTE: features are not resettable and typically defaults to false ...
+ protected boolean processNamespaces;
+ protected boolean roundtripSupported;
+
+ // global parser state
+ protected String location;
+ protected int lineNumber;
+ protected int columnNumber;
+ protected boolean seenRoot;
+ protected boolean reachedEnd;
+ protected int eventType;
+ protected boolean emptyElementTag;
+ // element stack
+ protected int depth;
+ protected char[] elRawName[];
+ protected int elRawNameEnd[];
+ protected int elRawNameLine[];
+
+ protected String elName[];
+ protected String elPrefix[];
+ protected String elUri[];
+ //protected String elValue[];
+ protected int elNamespaceCount[];
+
+
+ /**
+ * Make sure that we have enough space to keep element stack if passed size.
+ * It will always create one additional slot then current depth
+ */
+ protected void ensureElementsCapacity() {
+ final int elStackSize = elName != null ? elName.length : 0;
+ if ((depth + 1) >= elStackSize) {
+ // we add at least one extra slot ...
+ final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
+ if (TRACE_SIZING) {
+ System.err.println("TRACE_SIZING elStackSize " + elStackSize + " ==> " + newSize);
+ }
+ final boolean needsCopying = elStackSize > 0;
+ String[] arr = null;
+ // reuse arr local variable slot
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
+ elName = arr;
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize);
+ elPrefix = arr;
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize);
+ elUri = arr;
+
+ int[] iarr = new int[newSize];
+ if (needsCopying) {
+ System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
+ } else {
+ // special initialization
+ iarr[0] = 0;
+ }
+ elNamespaceCount = iarr;
+
+ //TODO: avoid using element raw name ...
+ iarr = new int[newSize];
+ if (needsCopying) {
+ System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize);
+ }
+ elRawNameEnd = iarr;
+
+ iarr = new int[newSize];
+ if (needsCopying) {
+ System.arraycopy(elRawNameLine, 0, iarr, 0, elStackSize);
+ }
+ elRawNameLine = iarr;
+
+ final char[][] carr = new char[newSize][];
+ if (needsCopying) {
+ System.arraycopy(elRawName, 0, carr, 0, elStackSize);
+ }
+ elRawName = carr;
+ // arr = new String[newSize];
+ // if(needsCopying) System.arraycopy(elLocalName, 0, arr, 0, elStackSize);
+ // elLocalName = arr;
+ // arr = new String[newSize];
+ // if(needsCopying) System.arraycopy(elDefaultNs, 0, arr, 0, elStackSize);
+ // elDefaultNs = arr;
+ // int[] iarr = new int[newSize];
+ // if(needsCopying) System.arraycopy(elNsStackPos, 0, iarr, 0, elStackSize);
+ // for (int i = elStackSize; i < iarr.length; i++)
+ // {
+ // iarr[i] = (i > 0) ? -1 : 0;
+ // }
+ // elNsStackPos = iarr;
+ //assert depth < elName.length;
+ }
+ }
+
+
+ // attribute stack
+ protected int attributeCount;
+ protected String attributeName[];
+ protected int attributeNameHash[];
+ //protected int attributeNameStart[];
+ //protected int attributeNameEnd[];
+ protected String attributePrefix[];
+ protected String attributeUri[];
+ protected String attributeValue[];
+ //protected int attributeValueStart[];
+ //protected int attributeValueEnd[];
+
+
+ /**
+ * Make sure that in attributes temporary array is enough space.
+ */
+ protected void ensureAttributesCapacity(int size) {
+ final int attrPosSize = attributeName != null ? attributeName.length : 0;
+ if (size >= attrPosSize) {
+ final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+ if (TRACE_SIZING) {
+ System.err.println("TRACE_SIZING attrPosSize " + attrPosSize + " ==> " + newSize);
+ }
+ final boolean needsCopying = attrPosSize > 0;
+ String[] arr = null;
+
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize);
+ attributeName = arr;
+
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize);
+ attributePrefix = arr;
+
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize);
+ attributeUri = arr;
+
+ arr = new String[newSize];
+ if (needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize);
+ attributeValue = arr;
+
+ if (!allStringsInterned) {
+ final int[] iarr = new int[newSize];
+ if (needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize);
+ attributeNameHash = iarr;
+ }
+
+ arr = null;
+ // //assert attrUri.length > size
+ }
+ }
+
+ // namespace stack
+ protected int namespaceEnd;
+ protected String namespacePrefix[];
+ protected int namespacePrefixHash[];
+ protected String namespaceUri[];
+
+ protected void ensureNamespacesCapacity(int size) {
+ final int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
+ if (size >= namespaceSize) {
+ final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+ if (TRACE_SIZING) {
+ System.err.println("TRACE_SIZING namespaceSize " + namespaceSize + " ==> " + newSize);
+ }
+ final String[] newNamespacePrefix = new String[newSize];
+ final String[] newNamespaceUri = new String[newSize];
+ if (namespacePrefix != null) {
+ System.arraycopy(
+ namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
+ System.arraycopy(
+ namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
+ }
+ namespacePrefix = newNamespacePrefix;
+ namespaceUri = newNamespaceUri;
+
+
+ if (!allStringsInterned) {
+ final int[] newNamespacePrefixHash = new int[newSize];
+ if (namespacePrefixHash != null) {
+ System.arraycopy(
+ namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
+ }
+ namespacePrefixHash = newNamespacePrefixHash;
+ }
+ //prefixesSize = newSize;
+ // //assert nsPrefixes.length > size && nsPrefixes.length == newSize
+ }
+ }
+
+ /**
+ * simplistic implementation of hash function that has <b>constant</b>
+ * time to compute - so it also means diminishing hash quality for long strings
+ * but for XML parsing it should be good enough ...
+ */
+ protected static final int fastHash(char ch[], int off, int len) {
+ if (len == 0) return 0;
+ //assert len >0
+ int hash = ch[off]; // hash at beginning
+ //try {
+ hash = (hash << 7) + ch[off + len - 1]; // hash at the end
+ //} catch(ArrayIndexOutOfBoundsException aie) {
+ // aie.printStackTrace(); //should never happen ...
+ // throw new RuntimeException("this is violation of pre-condition");
+ //}
+ if (len > 16) hash = (hash << 7) + ch[off + (len / 4)]; // 1/4 from beginning
+ if (len > 8) hash = (hash << 7) + ch[off + (len / 2)]; // 1/2 of string size ...
+ // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
+ // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
+ //assert hash >= 0;
+ return hash;
+ }
+
+ // entity replacement stack
+ protected int entityEnd;
+
+ protected String entityName[];
+ protected char[] entityNameBuf[];
+ protected String entityReplacement[];
+ protected char[] entityReplacementBuf[];
+
+ protected int entityNameHash[];
+
+ protected void ensureEntityCapacity() {
+ final int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0;
+ if (entityEnd >= entitySize) {
+ final int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25
+ if (TRACE_SIZING) {
+ System.err.println("TRACE_SIZING entitySize " + entitySize + " ==> " + newSize);
+ }
+ final String[] newEntityName = new String[newSize];
+ final char[] newEntityNameBuf[] = new char[newSize][];
+ final String[] newEntityReplacement = new String[newSize];
+ final char[] newEntityReplacementBuf[] = new char[newSize][];
+ if (entityName != null) {
+ System.arraycopy(entityName, 0, newEntityName, 0, entityEnd);
+ System.arraycopy(entityNameBuf, 0, newEntityNameBuf, 0, entityEnd);
+ System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd);
+ System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd);
+ }
+ entityName = newEntityName;
+ entityNameBuf = newEntityNameBuf;
+ entityReplacement = newEntityReplacement;
+ entityReplacementBuf = newEntityReplacementBuf;
+
+ if (!allStringsInterned) {
+ final int[] newEntityNameHash = new int[newSize];
+ if (entityNameHash != null) {
+ System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd);
+ }
+ entityNameHash = newEntityNameHash;
+ }
+ }
+ }
+
+ // input buffer management
+ protected static final int READ_CHUNK_SIZE = 8 * 1024; //max data chars in one read() call
+ protected Reader reader;
+ protected String inputEncoding;
+
+
+ protected int bufLoadFactor = 95; // 99%
+ //protected int bufHardLimit; // only matters when expanding
+
+ protected char buf[] = new char[
+ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 256];
+ protected int bufSoftLimit = (bufLoadFactor * buf.length) / 100; // desirable size of buffer
+ protected boolean preventBufferCompaction;
+
+ protected int bufAbsoluteStart; // this is buf
+ protected int bufStart;
+ protected int bufEnd;
+ protected int pos;
+ protected int posStart;
+ protected int posEnd;
+
+ protected char pc[] = new char[
+ Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 64];
+ protected int pcStart;
+ protected int pcEnd;
+
+
+ // parsing state
+ //protected boolean needsMore;
+ //protected boolean seenMarkup;
+ protected boolean usePC;
+
+
+ protected boolean seenStartTag;
+ protected boolean seenEndTag;
+ protected boolean pastEndTag;
+ protected boolean seenAmpersand;
+ protected boolean seenMarkup;
+ protected boolean seenDocdecl;
+
+ // transient variable set during each call to next/Token()
+ protected boolean tokenize;
+ protected String text;
+ protected String entityRefName;
+
+ protected String xmlDeclVersion;
+ protected Boolean xmlDeclStandalone;
+ protected String xmlDeclContent;
+
+ protected void reset() {
+ //System.out.println("reset() called");
+ location = null;
+ lineNumber = 1;
+ columnNumber = 0;
+ seenRoot = false;
+ reachedEnd = false;
+ eventType = START_DOCUMENT;
+ emptyElementTag = false;
+
+ depth = 0;
+
+ attributeCount = 0;
+
+ namespaceEnd = 0;
+
+ entityEnd = 0;
+
+ reader = null;
+ inputEncoding = null;
+
+ preventBufferCompaction = false;
+ bufAbsoluteStart = 0;
+ bufEnd = bufStart = 0;
+ pos = posStart = posEnd = 0;
+
+ pcEnd = pcStart = 0;
+
+ usePC = false;
+
+ seenStartTag = false;
+ seenEndTag = false;
+ pastEndTag = false;
+ seenAmpersand = false;
+ seenMarkup = false;
+ seenDocdecl = false;
+
+ xmlDeclVersion = null;
+ xmlDeclStandalone = null;
+ xmlDeclContent = null;
+
+ resetStringCache();
+ }
+
+ public MXParser() {
+ }
+
+
+ /**
+ * Method setFeature
+ *
+ * @param name a String
+ * @param state a boolean
+ * @throws XmlPullParserException
+ */
+ public void setFeature(String name,
+ boolean state) throws XmlPullParserException {
+ if (name == null) throw new IllegalArgumentException("feature name should not be null");
+ if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ if (eventType != START_DOCUMENT) throw new XmlPullParserException(
+ "namespace processing feature can only be changed before parsing", this, null);
+ processNamespaces = state;
+ // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ // if(type != START_DOCUMENT) throw new XmlPullParserException(
+ // "namespace reporting feature can only be changed before parsing", this, null);
+ // reportNsAttribs = state;
+ } else if (FEATURE_NAMES_INTERNED.equals(name)) {
+ if (state != false) {
+ throw new XmlPullParserException(
+ "interning names in this implementation is not supported");
+ }
+ } else if (FEATURE_PROCESS_DOCDECL.equals(name)) {
+ if (state != false) {
+ throw new XmlPullParserException(
+ "processing DOCDECL is not supported");
+ }
+ //} else if(REPORT_DOCDECL.equals(name)) {
+ // paramNotifyDoctype = state;
+ } else if (FEATURE_XML_ROUNDTRIP.equals(name)) {
+ //if(state == false) {
+ // throw new XmlPullParserException(
+ // "roundtrip feature can not be switched off");
+ //}
+ roundtripSupported = state;
+ } else {
+ throw new XmlPullParserException("unsupported feature " + name);
+ }
+ }
+
+ /**
+ * Unknown properties are <strong>always</strong> returned as false
+ */
+ public boolean getFeature(String name) {
+ if (name == null) throw new IllegalArgumentException("feature name should not be null");
+ if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ return processNamespaces;
+ // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ // return reportNsAttribs;
+ } else if (FEATURE_NAMES_INTERNED.equals(name)) {
+ return false;
+ } else if (FEATURE_PROCESS_DOCDECL.equals(name)) {
+ return false;
+ //} else if(REPORT_DOCDECL.equals(name)) {
+ // return paramNotifyDoctype;
+ } else if (FEATURE_XML_ROUNDTRIP.equals(name)) {
+ //return true;
+ return roundtripSupported;
+ }
+ return false;
+ }
+
+ public void setProperty(String name,
+ Object value)
+ throws XmlPullParserException {
+ if (PROPERTY_LOCATION.equals(name)) {
+ location = (String) value;
+ } else {
+ throw new XmlPullParserException("unsupported property: '" + name + "'");
+ }
+ }
+
+
+ public Object getProperty(String name) {
+ if (name == null) throw new IllegalArgumentException("property name should not be null");
+ if (PROPERTY_XMLDECL_VERSION.equals(name)) {
+ return xmlDeclVersion;
+ } else if (PROPERTY_XMLDECL_STANDALONE.equals(name)) {
+ return xmlDeclStandalone;
+ } else if (PROPERTY_XMLDECL_CONTENT.equals(name)) {
+ return xmlDeclContent;
+ } else if (PROPERTY_LOCATION.equals(name)) {
+ return location;
+ }
+ return null;
+ }
+
+
+ public void setInput(Reader in) throws XmlPullParserException {
+ if (in == null) {
+ throw new IllegalArgumentException("input reader can not be null");
+ }
+ reset();
+ reader = in;
+ }
+
+ public void setInput(java.io.InputStream inputStream, String inputEncoding)
+ throws XmlPullParserException {
+ if (inputStream == null) {
+ throw new IllegalArgumentException("input stream can not be null");
+ }
+ reset();
+ try {
+ if (inputEncoding != null) {
+ this.reader = new InputStreamReader(inputStream, inputEncoding);
+ this.inputEncoding = inputEncoding;
+ } else {
+ XmlStreamReader xr = new XmlStreamReader(inputStream);
+ this.reader = xr;
+ this.inputEncoding = xr.getEncoding();
+ }
+ } catch (IOException une) {
+ throw new XmlPullParserException(
+ "could not create reader for encoding " + inputEncoding + " : " + une, this, une);
+ }
+ }
+
+ public String getInputEncoding() {
+ return inputEncoding;
+ }
+
+ public void defineEntityReplacementText(String entityName,
+ String replacementText)
+ throws XmlPullParserException {
+ // throw new XmlPullParserException("not allowed");
+
+ //protected char[] entityReplacement[];
+ ensureEntityCapacity();
+
+ // this is to make sure that if interning works we will take advantage of it ...
+ this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length());
+ entityNameBuf[entityEnd] = entityName.toCharArray();
+
+ entityReplacement[entityEnd] = replacementText;
+ entityReplacementBuf[entityEnd] = replacementText.toCharArray();
+ if (!allStringsInterned) {
+ entityNameHash[entityEnd] =
+ fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length);
+ }
+ ++entityEnd;
+ //TODO disallow < or & in entity replacement text (or ]]>???)
+ // TOOD keepEntityNormalizedForAttributeValue cached as well ...
+ }
+
+ public int getNamespaceCount(int depth)
+ throws XmlPullParserException {
+ if (processNamespaces == false || depth == 0) {
+ return 0;
+ }
+ //int maxDepth = eventType == END_TAG ? this.depth + 1 : this.depth;
+ //if(depth < 0 || depth > maxDepth) throw new IllegalArgumentException(
+ if (depth < 0 || depth > this.depth) throw new IllegalArgumentException(
+ "allowed namespace depth 0.." + this.depth + " not " + depth);
+ return elNamespaceCount[depth];
+ }
+
+ public String getNamespacePrefix(int pos)
+ throws XmlPullParserException {
+
+ //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+ //if(pos < end) {
+ if (pos < namespaceEnd) {
+ return namespacePrefix[pos];
+ } else {
+ throw new XmlPullParserException(
+ "position " + pos + " exceeded number of available namespaces " + namespaceEnd);
+ }
+ }
+
+ public String getNamespaceUri(int pos) throws XmlPullParserException {
+ //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+ //if(pos < end) {
+ if (pos < namespaceEnd) {
+ return namespaceUri[pos];
+ } else {
+ throw new XmlPullParserException(
+ "position " + pos + " exceeded number of available namespaces " + namespaceEnd);
+ }
+ }
+
+ public String getNamespace(String prefix)
+ //throws XmlPullParserException
+ {
+ //int count = namespaceCount[ depth ];
+ if (prefix != null) {
+ for (int i = namespaceEnd - 1; i >= 0; i--) {
+ if (prefix.equals(namespacePrefix[i])) {
+ return namespaceUri[i];
+ }
+ }
+ if ("xml".equals(prefix)) {
+ return XML_URI;
+ } else if ("xmlns".equals(prefix)) {
+ return XMLNS_URI;
+ }
+ } else {
+ for (int i = namespaceEnd - 1; i >= 0; i--) {
+ if (namespacePrefix[i] == null) { //"") { //null ) { //TODO check FIXME Alek
+ return namespaceUri[i];
+ }
+ }
+
+ }
+ return null;
+ }
+
+
+ public int getDepth() {
+ return depth;
+ }
+
+
+ private static int findFragment(int bufMinPos, char[] b, int start, int end) {
+ //System.err.println("bufStart="+bufStart+" b="+printable(new String(b, start, end - start))+" start="+start+" end="+end);
+ if (start < bufMinPos) {
+ start = bufMinPos;
+ if (start > end) start = end;
+ return start;
+ }
+ if (end - start > 65) {
+ start = end - 10; // try to find good location
+ }
+ int i = start + 1;
+ while (--i > bufMinPos) {
+ if ((end - i) > 65) break;
+ final char c = b[i];
+ if (c == '<' && (start - i) > 10) break;
+ }
+ return i;
+ }
+
+
+ /**
+ * Return string describing current position of parsers as
+ * text 'STATE [seen %s...] @line:column'.
+ */
+ public String getPositionDescription() {
+ String fragment = null;
+ if (posStart <= pos) {
+ final int start = findFragment(0, buf, posStart, pos);
+ //System.err.println("start="+start);
+ if (start < pos) {
+ fragment = new String(buf, start, pos - start);
+ }
+ if (bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment;
+ }
+ // return " at line "+tokenizerPosRow
+ // +" and column "+(tokenizerPosCol-1)
+ // +(fragment != null ? " seen "+printable(fragment)+"..." : "");
+ return " " + TYPES[eventType] +
+ (fragment != null ? " seen " + printable(fragment) + "..." : "")
+ + " " + (location != null ? location : "")
+ + "@" + getLineNumber() + ":" + getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ public int getColumnNumber() {
+ return columnNumber;
+ }
+
+
+ public boolean isWhitespace() throws XmlPullParserException {
+ if (eventType == TEXT || eventType == CDSECT) {
+ if (usePC) {
+ for (int i = pcStart; i < pcEnd; i++) {
+ if (!isS(pc[i])) return false;
+ }
+ return true;
+ } else {
+ for (int i = posStart; i < posEnd; i++) {
+ if (!isS(buf[i])) return false;
+ }
+ return true;
+ }
+ } else if (eventType == IGNORABLE_WHITESPACE) {
+ return true;
+ }
+ throw new XmlPullParserException("no content available to check for white spaces");
+ }
+
+ public String getText() {
+ if (eventType == START_DOCUMENT || eventType == END_DOCUMENT) {
+ //throw new XmlPullParserException("no content available to read");
+ // if(roundtripSupported) {
+ // text = new String(buf, posStart, posEnd - posStart);
+ // } else {
+ return null;
+ // }
+ } else if (eventType == ENTITY_REF) {
+ return text;
+ }
+ if (text == null) {
+ if (!usePC || eventType == START_TAG || eventType == END_TAG) {
+ text = new String(buf, posStart, posEnd - posStart);
+ } else {
+ text = new String(pc, pcStart, pcEnd - pcStart);
+ }
+ }
+ return text;
+ }
+
+ public char[] getTextCharacters(int[] holderForStartAndLength) {
+ if (eventType == TEXT) {
+ if (usePC) {
+ holderForStartAndLength[0] = pcStart;
+ holderForStartAndLength[1] = pcEnd - pcStart;
+ return pc;
+ } else {
+ holderForStartAndLength[0] = posStart;
+ holderForStartAndLength[1] = posEnd - posStart;
+ return buf;
+
+ }
+ } else if (eventType == START_TAG
+ || eventType == END_TAG
+ || eventType == CDSECT
+ || eventType == COMMENT
+ || eventType == ENTITY_REF
+ || eventType == PROCESSING_INSTRUCTION
+ || eventType == IGNORABLE_WHITESPACE
+ || eventType == DOCDECL) {
+ holderForStartAndLength[0] = posStart;
+ holderForStartAndLength[1] = posEnd - posStart;
+ return buf;
+ } else if (eventType == START_DOCUMENT
+ || eventType == END_DOCUMENT) {
+ //throw new XmlPullParserException("no content available to read");
+ holderForStartAndLength[0] = holderForStartAndLength[1] = -1;
+ return null;
+ } else {
+ throw new IllegalArgumentException("unknown text eventType: " + eventType);
+ }
+ // String s = getText();
+ // char[] cb = null;
+ // if(s!= null) {
+ // cb = s.toCharArray();
+ // holderForStartAndLength[0] = 0;
+ // holderForStartAndLength[1] = s.length();
+ // } else {
+ // }
+ // return cb;
+ }
+
+ public String getNamespace() {
+ if (eventType == START_TAG) {
+ //return processNamespaces ? elUri[ depth - 1 ] : NO_NAMESPACE;
+ return processNamespaces ? elUri[depth] : NO_NAMESPACE;
+ } else if (eventType == END_TAG) {
+ return processNamespaces ? elUri[depth] : NO_NAMESPACE;
+ }
+ return null;
+ // String prefix = elPrefix[ maxDepth ];
+ // if(prefix != null) {
+ // for( int i = namespaceEnd -1; i >= 0; i--) {
+ // if( prefix.equals( namespacePrefix[ i ] ) ) {
+ // return namespaceUri[ i ];
+ // }
+ // }
+ // } else {
+ // for( int i = namespaceEnd -1; i >= 0; i--) {
+ // if( namespacePrefix[ i ] == null ) {
+ // return namespaceUri[ i ];
+ // }
+ // }
+ //
+ // }
+ // return "";
+ }
+
+ public String getName() {
+ if (eventType == START_TAG) {
+ //return elName[ depth - 1 ] ;
+ return elName[depth];
+ } else if (eventType == END_TAG) {
+ return elName[depth];
+ } else if (eventType == ENTITY_REF) {
+ if (entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ return entityRefName;
+ } else {
+ return null;
+ }
+ }
+
+ public String getPrefix() {
+ if (eventType == START_TAG) {
+ //return elPrefix[ depth - 1 ] ;
+ return elPrefix[depth];
+ } else if (eventType == END_TAG) {
+ return elPrefix[depth];
+ }
+ return null;
+ // if(eventType != START_TAG && eventType != END_TAG) return null;
+ // int maxDepth = eventType == END_TAG ? depth : depth - 1;
+ // return elPrefix[ maxDepth ];
+ }
+
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (eventType != START_TAG) throw new XmlPullParserException(
+ "parser must be on START_TAG to check for empty element", this, null);
+ return emptyElementTag;
+ }
+
+ public int getAttributeCount() {
+ if (eventType != START_TAG) return -1;
+ return attributeCount;
+ }
+
+ public String getAttributeNamespace(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (processNamespaces == false) return NO_NAMESPACE;
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return attributeUri[index];
+ }
+
+ public String getAttributeName(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return attributeName[index];
+ }
+
+ public String getAttributePrefix(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (processNamespaces == false) return null;
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return attributePrefix[index];
+ }
+
+ public String getAttributeType(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return "CDATA";
+ }
+
+ public boolean isAttributeDefault(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return false;
+ }
+
+ public String getAttributeValue(int index) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes");
+ if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+ "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+ return attributeValue[index];
+ }
+
+ public String getAttributeValue(String namespace,
+ String name) {
+ if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+ "only START_TAG can have attributes" + getPositionDescription());
+ if (name == null) {
+ throw new IllegalArgumentException("attribute name can not be null");
+ }
+ // TODO make check if namespace is interned!!! etc. for names!!!
+ if (processNamespaces) {
+ if (namespace == null) {
+ namespace = "";
+ }
+
+ for (int i = 0; i < attributeCount; ++i) {
+ if ((namespace == attributeUri[i] ||
+ namespace.equals(attributeUri[i]))
+ //(namespace != null && namespace.equals(attributeUri[ i ]))
+ // taking advantage of String.intern()
+ && name.equals(attributeName[i])) {
+ return attributeValue[i];
+ }
+ }
+ } else {
+ if (namespace != null && namespace.length() == 0) {
+ namespace = null;
+ }
+ if (namespace != null) throw new IllegalArgumentException(
+ "when namespaces processing is disabled attribute namespace must be null");
+ for (int i = 0; i < attributeCount; ++i) {
+ if (name.equals(attributeName[i])) {
+ return attributeValue[i];
+ }
+ }
+ }
+ return null;
+ }
+
+
+ public int getEventType()
+ throws XmlPullParserException {
+ return eventType;
+ }
+
+ public void require(int type, String namespace, String name)
+ throws XmlPullParserException, IOException {
+ if (processNamespaces == false && namespace != null) {
+ throw new XmlPullParserException(
+ "processing namespaces must be enabled on parser (or factory)" +
+ " to have possible namespaces declared on elements"
+ + (" (position:" + getPositionDescription()) + ")");
+ }
+ if (type != getEventType()
+ || (namespace != null && !namespace.equals(getNamespace()))
+ || (name != null && !name.equals(getName()))) {
+ throw new XmlPullParserException(
+ "expected event " + TYPES[type]
+ + (name != null ? " with name '" + name + "'" : "")
+ + (namespace != null && name != null ? " and" : "")
+ + (namespace != null ? " with namespace '" + namespace + "'" : "")
+ + " but got"
+ + (type != getEventType() ? " " + TYPES[getEventType()] : "")
+ + (name != null && getName() != null && !name.equals(getName())
+ ? " name '" + getName() + "'" : "")
+ + (namespace != null && name != null
+ && getName() != null && !name.equals(getName())
+ && getNamespace() != null && !namespace.equals(getNamespace())
+ ? " and" : "")
+ + (namespace != null && getNamespace() != null && !namespace.equals(getNamespace())
+ ? " namespace '" + getNamespace() + "'" : "")
+ + (" (position:" + getPositionDescription()) + ")");
+ }
+ }
+
+
+ /**
+ * Skip sub tree that is currently parser positioned on.
+ * <br>NOTE: parser must be on START_TAG and when function returns
+ * parser will be positioned on corresponding END_TAG
+ */
+ public void skipSubTree()
+ throws XmlPullParserException, IOException {
+ require(START_TAG, null, null);
+ int level = 1;
+ while (level > 0) {
+ int eventType = next();
+ if (eventType == END_TAG) {
+ --level;
+ } else if (eventType == START_TAG) {
+ ++level;
+ }
+ }
+ }
+
+ // public String readText() throws XmlPullParserException, IOException
+ // {
+ // if (getEventType() != TEXT) return "";
+ // String result = getText();
+ // next();
+ // return result;
+ // }
+
+ public String nextText() throws XmlPullParserException, IOException {
+ // String result = null;
+ // boolean onStartTag = false;
+ // if(eventType == START_TAG) {
+ // onStartTag = true;
+ // next();
+ // }
+ // if(eventType == TEXT) {
+ // result = getText();
+ // next();
+ // } else if(onStartTag && eventType == END_TAG) {
+ // result = "";
+ // } else {
+ // throw new XmlPullParserException(
+ // "parser must be on START_TAG or TEXT to read text", this, null);
+ // }
+ // if(eventType != END_TAG) {
+ // throw new XmlPullParserException(
+ // "event TEXT it must be immediately followed by END_TAG", this, null);
+ // }
+ // return result;
+ if (getEventType() != START_TAG) {
+ throw new XmlPullParserException(
+ "parser must be on START_TAG to read next text", this, null);
+ }
+ int eventType = next();
+ if (eventType == TEXT) {
+ final String result = getText();
+ eventType = next();
+ if (eventType != END_TAG) {
+ throw new XmlPullParserException(
+ "TEXT must be immediately followed by END_TAG and not "
+ + TYPES[getEventType()], this, null);
+ }
+ return result;
+ } else if (eventType == END_TAG) {
+ return "";
+ } else {
+ throw new XmlPullParserException(
+ "parser must be on START_TAG or TEXT to read text", this, null);
+ }
+ }
+
+ public int nextTag() throws XmlPullParserException, IOException {
+ next();
+ if (eventType == TEXT && isWhitespace()) { // skip whitespace
+ next();
+ }
+ if (eventType != START_TAG && eventType != END_TAG) {
+ throw new XmlPullParserException("expected START_TAG or END_TAG not "
+ + TYPES[getEventType()], this, null);
+ }
+ return eventType;
+ }
+
+ public int next()
+ throws XmlPullParserException, IOException {
+ tokenize = false;
+ return nextImpl();
+ }
+
+ public int nextToken()
+ throws XmlPullParserException, IOException {
+ tokenize = true;
+ return nextImpl();
+ }
+
+
+ protected int nextImpl()
+ throws XmlPullParserException, IOException {
+ text = null;
+ pcEnd = pcStart = 0;
+ usePC = false;
+ bufStart = posEnd;
+ if (pastEndTag) {
+ pastEndTag = false;
+ --depth;
+ namespaceEnd = elNamespaceCount[depth]; // less namespaces available
+ }
+ if (emptyElementTag) {
+ emptyElementTag = false;
+ pastEndTag = true;
+ return eventType = END_TAG;
+ }
+
+ // [1] document ::= prolog element Misc*
+ if (depth > 0) {
+
+ if (seenStartTag) {
+ seenStartTag = false;
+ return eventType = parseStartTag();
+ }
+ if (seenEndTag) {
+ seenEndTag = false;
+ return eventType = parseEndTag();
+ }
+
+ // ASSUMPTION: we are _on_ first character of content or markup!!!!
+ // [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
+ char ch;
+ if (seenMarkup) { // we have read ahead ...
+ seenMarkup = false;
+ ch = '<';
+ } else if (seenAmpersand) {
+ seenAmpersand = false;
+ ch = '&';
+ } else {
+ ch = more();
+ }
+ posStart = pos - 1; // VERY IMPORTANT: this is correct start of event!!!
+
+ // when true there is some potential event TEXT to return - keep gathering
+ boolean hadCharData = false;
+
+ // when true TEXT data is not continual (like <![CDATA[text]]>) and requires PC merging
+ boolean needsMerging = false;
+
+ MAIN_LOOP:
+ while (true) {
+ // work on MARKUP
+ if (ch == '<') {
+ if (hadCharData) {
+ //posEnd = pos - 1;
+ if (tokenize) {
+ seenMarkup = true;
+ return eventType = TEXT;
+ }
+ }
+ ch = more();
+ if (ch == '/') {
+ if (!tokenize && hadCharData) {
+ seenEndTag = true;
+ //posEnd = pos - 2;
+ return eventType = TEXT;
+ }
+ return eventType = parseEndTag();
+ } else if (ch == '!') {
+ ch = more();
+ if (ch == '-') {
+ // note: if(tokenize == false) posStart/End is NOT changed!!!!
+ parseComment();
+ if (tokenize) return eventType = COMMENT;
+ if (!usePC && hadCharData) {
+ needsMerging = true;
+ } else {
+ posStart = pos; //completely ignore comment
+ }
+ } else if (ch == '[') {
+ //posEnd = pos - 3;
+ // must remember previous posStart/End as it merges with content of CDATA
+ //int oldStart = posStart + bufAbsoluteStart;
+ //int oldEnd = posEnd + bufAbsoluteStart;
+ parseCDSect(hadCharData);
+ if (tokenize) return eventType = CDSECT;
+ final int cdStart = posStart;
+ final int cdEnd = posEnd;
+ final int cdLen = cdEnd - cdStart;
+
+
+ if (cdLen > 0) { // was there anything inside CDATA section?
+ hadCharData = true;
+ if (!usePC) {
+ needsMerging = true;
+ }
+ }
+
+ // posStart = oldStart;
+ // posEnd = oldEnd;
+ // if(cdLen > 0) { // was there anything inside CDATA section?
+ // if(hadCharData) {
+ // // do merging if there was anything in CDSect!!!!
+ // // if(!usePC) {
+ // // // posEnd is correct already!!!
+ // // if(posEnd > posStart) {
+ // // joinPC();
+ // // } else {
+ // // usePC = true;
+ // // pcStart = pcEnd = 0;
+ // // }
+ // // }
+ // // if(pcEnd + cdLen >= pc.length) ensurePC(pcEnd + cdLen);
+ // // // copy [cdStart..cdEnd) into PC
+ // // System.arraycopy(buf, cdStart, pc, pcEnd, cdLen);
+ // // pcEnd += cdLen;
+ // if(!usePC) {
+ // needsMerging = true;
+ // posStart = cdStart;
+ // posEnd = cdEnd;
+ // }
+ // } else {
+ // if(!usePC) {
+ // needsMerging = true;
+ // posStart = cdStart;
+ // posEnd = cdEnd;
+ // hadCharData = true;
+ // }
+ // }
+ // //hadCharData = true;
+ // } else {
+ // if( !usePC && hadCharData ) {
+ // needsMerging = true;
+ // }
+ // }
+ } else {
+ throw new XmlPullParserException(
+ "unexpected character in markup " + printable(ch), this, null);
+ }
+ } else if (ch == '?') {
+ parsePI();
+ if (tokenize) return eventType = PROCESSING_INSTRUCTION;
+ if (!usePC && hadCharData) {
+ needsMerging = true;
+ } else {
+ posStart = pos; //completely ignore PI
+ }
+
+ } else if (isNameStartChar(ch)) {
+ if (!tokenize && hadCharData) {
+ seenStartTag = true;
+ //posEnd = pos - 2;
+ return eventType = TEXT;
+ }
+ return eventType = parseStartTag();
+ } else {
+ throw new XmlPullParserException(
+ "unexpected character in markup " + printable(ch), this, null);
+ }
+ // do content compaction if it makes sense!!!!
+
+ } else if (ch == '&') {
+ // work on ENTITTY
+ //posEnd = pos - 1;
+ if (tokenize && hadCharData) {
+ seenAmpersand = true;
+ return eventType = TEXT;
+ }
+ final int oldStart = posStart + bufAbsoluteStart;
+ final int oldEnd = posEnd + bufAbsoluteStart;
+ final char[] resolvedEntity = parseEntityRef();
+ if (tokenize) return eventType = ENTITY_REF;
+ // check if replacement text can be resolved !!!
+ if (resolvedEntity == null) {
+ if (entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ throw new XmlPullParserException(
+ "could not resolve entity named '" + printable(entityRefName) + "'",
+ this, null);
+ }
+ //int entStart = posStart;
+ //int entEnd = posEnd;
+ posStart = oldStart - bufAbsoluteStart;
+ posEnd = oldEnd - bufAbsoluteStart;
+ if (!usePC) {
+ if (hadCharData) {
+ joinPC(); // posEnd is already set correctly!!!
+ needsMerging = false;
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ // write into PC replacement text - do merge for replacement text!!!!
+ for (int i = 0; i < resolvedEntity.length; i++) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = resolvedEntity[i];
+
+ }
+ hadCharData = true;
+ //assert needsMerging == false;
+ } else {
+
+ if (needsMerging) {
+ //assert usePC == false;
+ joinPC(); // posEnd is already set correctly!!!
+ //posStart = pos - 1;
+ needsMerging = false;
+ }
+
+
+ //no MARKUP not ENTITIES so work on character data ...
+
+
+ // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
+
+
+ hadCharData = true;
+
+ boolean normalizedCR = false;
+ final boolean normalizeInput = tokenize == false || roundtripSupported == false;
+ // use loop locality here!!!!
+ boolean seenBracket = false;
+ boolean seenBracketBracket = false;
+ do {
+
+ // check that ]]> does not show in
+ if (ch == ']') {
+ if (seenBracket) {
+ seenBracketBracket = true;
+ } else {
+ seenBracket = true;
+ }
+ } else if (seenBracketBracket && ch == '>') {
+ throw new XmlPullParserException(
+ "characters ]]> are not allowed in content", this, null);
+ } else {
+ if (seenBracket) {
+ seenBracketBracket = seenBracket = false;
+ }
+ // assert seenTwoBrackets == seenBracket == false;
+ }
+ if (normalizeInput) {
+ // deal with normalization issues ...
+ if (ch == '\r') {
+ normalizedCR = true;
+ posEnd = pos - 1;
+ // posEnd is already is set
+ if (!usePC) {
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ // if(!usePC) { joinPC(); } else { if(pcEnd >= pc.length) ensurePC(); }
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+
+ ch = more();
+ } while (ch != '<' && ch != '&');
+ posEnd = pos - 1;
+ continue MAIN_LOOP; // skip ch = more() from below - we are alreayd ahead ...
+ }
+ ch = more();
+ } // endless while(true)
+ } else {
+ if (seenRoot) {
+ return parseEpilog();
+ } else {
+ return parseProlog();
+ }
+ }
+ }
+
+
+ protected int parseProlog()
+ throws XmlPullParserException, IOException {
+ // [2] prolog: ::= XMLDecl? Misc* (doctypedecl Misc*)? and look for [39] element
+
+ char ch;
+ if (seenMarkup) {
+ ch = buf[pos - 1];
+ } else {
+ ch = more();
+ }
+
+ if (eventType == START_DOCUMENT) {
+ // bootstrap parsing with getting first character input!
+ // deal with BOM
+ // detect BOM and drop it (Unicode int Order Mark)
+ if (ch == '\uFFFE') {
+ throw new XmlPullParserException(
+ "first character in input was UNICODE noncharacter (0xFFFE)" +
+ "- input requires int swapping", this, null);
+ }
+ if (ch == '\uFEFF') {
+ // skipping UNICODE int Order Mark (so called BOM)
+ ch = more();
+ }
+ }
+ seenMarkup = false;
+ boolean gotS = false;
+ posStart = pos - 1;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+ while (true) {
+ // deal with Misc
+ // [27] Misc ::= Comment | PI | S
+ // deal with docdecl --> mark it!
+ // else parseStartTag seen <[^/]
+ if (ch == '<') {
+ if (gotS && tokenize) {
+ posEnd = pos - 1;
+ seenMarkup = true;
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ ch = more();
+ if (ch == '?') {
+ // check if it is 'xml'
+ // deal with XMLDecl
+ if (parsePI()) { // make sure to skip XMLDecl
+ if (tokenize) {
+ return eventType = PROCESSING_INSTRUCTION;
+ }
+ } else {
+ // skip over - continue tokenizing
+ posStart = pos;
+ gotS = false;
+ }
+
+ } else if (ch == '!') {
+ ch = more();
+ if (ch == 'D') {
+ if (seenDocdecl) {
+ throw new XmlPullParserException(
+ "only one docdecl allowed in XML document", this, null);
+ }
+ seenDocdecl = true;
+ parseDocdecl();
+ if (tokenize) return eventType = DOCDECL;
+ } else if (ch == '-') {
+ parseComment();
+ if (tokenize) return eventType = COMMENT;
+ } else {
+ throw new XmlPullParserException(
+ "unexpected markup <!" + printable(ch), this, null);
+ }
+ } else if (ch == '/') {
+ throw new XmlPullParserException(
+ "expected start tag name and not " + printable(ch), this, null);
+ } else if (isNameStartChar(ch)) {
+ seenRoot = true;
+ return parseStartTag();
+ } else {
+ throw new XmlPullParserException(
+ "expected start tag name and not " + printable(ch), this, null);
+ }
+ } else if (isS(ch)) {
+ gotS = true;
+ if (normalizeIgnorableWS) {
+ if (ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is already is set
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ } else {
+ throw new XmlPullParserException(
+ "only whitespace content allowed before start tag and not " + printable(ch),
+ this, null);
+ }
+ ch = more();
+ }
+ }
+
+ protected int parseEpilog()
+ throws XmlPullParserException, IOException {
+ if (eventType == END_DOCUMENT) {
+ throw new XmlPullParserException("already reached end of XML input", this, null);
+ }
+ if (reachedEnd) {
+ return eventType = END_DOCUMENT;
+ }
+ boolean gotS = false;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+ try {
+ // epilog: Misc*
+ char ch;
+ if (seenMarkup) {
+ ch = buf[pos - 1];
+ } else {
+ ch = more();
+ }
+ seenMarkup = false;
+ posStart = pos - 1;
+ if (!reachedEnd) {
+ while (true) {
+ // deal with Misc
+ // [27] Misc ::= Comment | PI | S
+ if (ch == '<') {
+ if (gotS && tokenize) {
+ posEnd = pos - 1;
+ seenMarkup = true;
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ ch = more();
+ if (reachedEnd) {
+ break;
+ }
+ if (ch == '?') {
+ // check if it is 'xml'
+ // deal with XMLDecl
+ parsePI();
+ if (tokenize) return eventType = PROCESSING_INSTRUCTION;
+
+ } else if (ch == '!') {
+ ch = more();
+ if (reachedEnd) {
+ break;
+ }
+ if (ch == 'D') {
+ parseDocdecl(); //FIXME
+ if (tokenize) return eventType = DOCDECL;
+ } else if (ch == '-') {
+ parseComment();
+ if (tokenize) return eventType = COMMENT;
+ } else {
+ throw new XmlPullParserException(
+ "unexpected markup <!" + printable(ch), this, null);
+ }
+ } else if (ch == '/') {
+ throw new XmlPullParserException(
+ "end tag not allowed in epilog but got " + printable(ch), this, null);
+ } else if (isNameStartChar(ch)) {
+ throw new XmlPullParserException(
+ "start tag not allowed in epilog but got " + printable(ch), this, null);
+ } else {
+ throw new XmlPullParserException(
+ "in epilog expected ignorable content and not " + printable(ch),
+ this, null);
+ }
+ } else if (isS(ch)) {
+ gotS = true;
+ if (normalizeIgnorableWS) {
+ if (ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is alreadys set
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ } else {
+ throw new XmlPullParserException(
+ "in epilog non whitespace content is not allowed but got " + printable(ch),
+ this, null);
+ }
+ ch = more();
+ if (reachedEnd) {
+ break;
+ }
+
+ }
+ }
+
+ // throw Exception("unexpected content in epilog
+ // catch EOFException return END_DOCUEMENT
+ //try {
+ } catch (EOFException ex) {
+ reachedEnd = true;
+ }
+ if (reachedEnd) {
+ if (tokenize && gotS) {
+ posEnd = pos; // well - this is LAST available character pos
+ return eventType = IGNORABLE_WHITESPACE;
+ }
+ return eventType = END_DOCUMENT;
+ } else {
+ throw new XmlPullParserException("internal error in parseEpilog");
+ }
+ }
+
+
+ public int parseEndTag() throws XmlPullParserException, IOException {
+ //ASSUMPTION ch is past "</"
+ // [42] ETag ::= '</' Name S? '>'
+ char ch = more();
+ if (!isNameStartChar(ch)) {
+ throw new XmlPullParserException(
+ "expected name start and not " + printable(ch), this, null);
+ }
+ posStart = pos - 3;
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ do {
+ ch = more();
+ } while (isNameChar(ch));
+
+ // now we go one level down -- do checks
+ //--depth; //FIXME
+
+ // check that end tag name is the same as start tag
+ //String name = new String(buf, nameStart - bufAbsoluteStart,
+ // (pos - 1) - (nameStart - bufAbsoluteStart));
+ //int last = pos - 1;
+ int off = nameStart - bufAbsoluteStart;
+ //final int len = last - off;
+ final int len = (pos - 1) - off;
+ final char[] cbuf = elRawName[depth];
+ if (elRawNameEnd[depth] != len) {
+ // construct strings for exception
+ final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+ final String endname = new String(buf, off, len);
+ throw new XmlPullParserException(
+ "end tag name </" + endname + "> must match start tag name <" + startname + ">"
+ + " from line " + elRawNameLine[depth], this, null);
+ }
+ for (int i = 0; i < len; i++) {
+ if (buf[off++] != cbuf[i]) {
+ // construct strings for exception
+ final String startname = new String(cbuf, 0, len);
+ final String endname = new String(buf, off - i - 1, len);
+ throw new XmlPullParserException(
+ "end tag name </" + endname + "> must be the same as start tag <" + startname + ">"
+ + " from line " + elRawNameLine[depth], this, null);
+ }
+ }
+
+ while (isS(ch)) {
+ ch = more();
+ } // skip additional white spaces
+ if (ch != '>') {
+ throw new XmlPullParserException(
+ "expected > to finish end tag not " + printable(ch)
+ + " from line " + elRawNameLine[depth], this, null);
+ }
+
+
+ //namespaceEnd = elNamespaceCount[ depth ]; //FIXME
+
+ posEnd = pos;
+ pastEndTag = true;
+ return eventType = END_TAG;
+ }
+
+ public int parseStartTag() throws XmlPullParserException, IOException {
+ //ASSUMPTION ch is past <T
+ // [40] STag ::= '<' Name (S Attribute)* S? '>'
+ // [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ ++depth; //FIXME
+
+ posStart = pos - 2;
+
+ emptyElementTag = false;
+ attributeCount = 0;
+ // retrieve name
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ int colonPos = -1;
+ char ch = buf[pos - 1];
+ if (ch == ':' && processNamespaces) throw new XmlPullParserException(
+ "when namespaces processing enabled colon can not be at element name start",
+ this, null);
+ while (true) {
+ ch = more();
+ if (!isNameChar(ch)) break;
+ if (ch == ':' && processNamespaces) {
+ if (colonPos != -1) throw new XmlPullParserException(
+ "only one colon is allowed in name of element when namespaces are enabled",
+ this, null);
+ colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+
+ // retrieve name
+ ensureElementsCapacity();
+
+
+ //TODO check for efficient interning and then use elRawNameInterned!!!!
+
+ int elLen = (pos - 1) - (nameStart - bufAbsoluteStart);
+ if (elRawName[depth] == null || elRawName[depth].length < elLen) {
+ elRawName[depth] = new char[2 * elLen];
+ }
+ System.arraycopy(buf, nameStart - bufAbsoluteStart, elRawName[depth], 0, elLen);
+ elRawNameEnd[depth] = elLen;
+ elRawNameLine[depth] = lineNumber;
+
+ String name = null;
+
+ // work on prefixes and namespace URI
+ String prefix = null;
+ if (processNamespaces) {
+ if (colonPos != -1) {
+ prefix = elPrefix[depth] = newString(buf, nameStart - bufAbsoluteStart,
+ colonPos - nameStart);
+ name = elName[depth] = newString(buf, colonPos + 1 - bufAbsoluteStart,
+ //(pos -1) - (colonPos + 1));
+ pos - 2 - (colonPos - bufAbsoluteStart));
+ } else {
+ prefix = elPrefix[depth] = null;
+ name = elName[depth] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+ }
+ } else {
+
+ name = elName[depth] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+
+ }
+
+
+ while (true) {
+
+ while (isS(ch)) {
+ ch = more();
+ } // skip additional white spaces
+
+ if (ch == '>') {
+ break;
+ } else if (ch == '/') {
+ if (emptyElementTag) throw new XmlPullParserException(
+ "repeated / in tag declaration", this, null);
+ emptyElementTag = true;
+ ch = more();
+ if (ch != '>') throw new XmlPullParserException(
+ "expected > to end empty tag not " + printable(ch), this, null);
+ break;
+ } else if (isNameStartChar(ch)) {
+ ch = parseAttribute();
+ ch = more();
+ continue;
+ } else {
+ throw new XmlPullParserException(
+ "start tag unexpected character " + printable(ch), this, null);
+ }
+ //ch = more(); // skip space
+ }
+
+ // now when namespaces were declared we can resolve them
+ if (processNamespaces) {
+ String uri = getNamespace(prefix);
+ if (uri == null) {
+ if (prefix == null) { // no prefix and no uri => use default namespace
+ uri = NO_NAMESPACE;
+ } else {
+ throw new XmlPullParserException(
+ "could not determine namespace bound to element prefix " + prefix,
+ this, null);
+ }
+
+ }
+ elUri[depth] = uri;
+
+
+ //String uri = getNamespace(prefix);
+ //if(uri == null && prefix == null) { // no prefix and no uri => use default namespace
+ // uri = "";
+ //}
+ // resolve attribute namespaces
+ for (int i = 0; i < attributeCount; i++) {
+ final String attrPrefix = attributePrefix[i];
+ if (attrPrefix != null) {
+ final String attrUri = getNamespace(attrPrefix);
+ if (attrUri == null) {
+ throw new XmlPullParserException(
+ "could not determine namespace bound to attribute prefix " + attrPrefix,
+ this, null);
+
+ }
+ attributeUri[i] = attrUri;
+ } else {
+ attributeUri[i] = NO_NAMESPACE;
+ }
+ }
+
+ //TODO
+ //[ WFC: Unique Att Spec ]
+ // check attribute uniqueness constraint for attributes that has namespace!!!
+
+ for (int i = 1; i < attributeCount; i++) {
+ for (int j = 0; j < i; j++) {
+ if (attributeUri[j] == attributeUri[i]
+ && (allStringsInterned && attributeName[j].equals(attributeName[i])
+ || (!allStringsInterned
+ && attributeNameHash[j] == attributeNameHash[i]
+ && attributeName[j].equals(attributeName[i])))
+
+ ) {
+ // prepare data for nice error message?
+ String attr1 = attributeName[j];
+ if (attributeUri[j] != null) attr1 = attributeUri[j] + ":" + attr1;
+ String attr2 = attributeName[i];
+ if (attributeUri[i] != null) attr2 = attributeUri[i] + ":" + attr2;
+ throw new XmlPullParserException(
+ "duplicated attributes " + attr1 + " and " + attr2, this, null);
+ }
+ }
+ }
+
+
+ } else { // ! processNamespaces
+
+ //[ WFC: Unique Att Spec ]
+ // check raw attribute uniqueness constraint!!!
+ for (int i = 1; i < attributeCount; i++) {
+ for (int j = 0; j < i; j++) {
+ if ((allStringsInterned && attributeName[j].equals(attributeName[i])
+ || (!allStringsInterned
+ && attributeNameHash[j] == attributeNameHash[i]
+ && attributeName[j].equals(attributeName[i])))
+
+ ) {
+ // prepare data for nice error message?
+ final String attr1 = attributeName[j];
+ final String attr2 = attributeName[i];
+ throw new XmlPullParserException(
+ "duplicated attributes " + attr1 + " and " + attr2, this, null);
+ }
+ }
+ }
+ }
+
+ elNamespaceCount[depth] = namespaceEnd;
+ posEnd = pos;
+ return eventType = START_TAG;
+ }
+
+ protected char parseAttribute() throws XmlPullParserException, IOException {
+ // parse attribute
+ // [41] Attribute ::= Name Eq AttValue
+ // [WFC: No External Entity References]
+ // [WFC: No < in Attribute Values]
+ final int prevPosStart = posStart + bufAbsoluteStart;
+ final int nameStart = pos - 1 + bufAbsoluteStart;
+ int colonPos = -1;
+ char ch = buf[pos - 1];
+ if (ch == ':' && processNamespaces) throw new XmlPullParserException(
+ "when namespaces processing enabled colon can not be at attribute name start",
+ this, null);
+
+
+ boolean startsWithXmlns = processNamespaces && ch == 'x';
+ int xmlnsPos = 0;
+
+ ch = more();
+ while (isNameChar(ch)) {
+ if (processNamespaces) {
+ if (startsWithXmlns && xmlnsPos < 5) {
+ ++xmlnsPos;
+ if (xmlnsPos == 1) {
+ if (ch != 'm') startsWithXmlns = false;
+ } else if (xmlnsPos == 2) {
+ if (ch != 'l') startsWithXmlns = false;
+ } else if (xmlnsPos == 3) {
+ if (ch != 'n') startsWithXmlns = false;
+ } else if (xmlnsPos == 4) {
+ if (ch != 's') startsWithXmlns = false;
+ } else {
+ if (ch != ':') throw new XmlPullParserException(
+ "after xmlns in attribute name must be colon"
+ + " when namespaces are enabled", this, null);
+ //colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+ if (ch == ':') {
+ if (colonPos != -1) throw new XmlPullParserException(
+ "only one colon is allowed in attribute name"
+ + " when namespaces are enabled", this, null);
+ colonPos = pos - 1 + bufAbsoluteStart;
+ }
+ }
+ ch = more();
+ }
+
+ ensureAttributesCapacity(attributeCount);
+
+ // --- start processing attributes
+ String name = null;
+ String prefix = null;
+ // work on prefixes and namespace URI
+ if (processNamespaces) {
+ if (xmlnsPos < 4) startsWithXmlns = false;
+ if (startsWithXmlns) {
+ if (colonPos != -1) {
+ //prefix = attributePrefix[ attributeCount ] = null;
+ final int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+ if (nameLen == 0) {
+ throw new XmlPullParserException(
+ "namespace prefix is required after xmlns: "
+ + " when namespaces are enabled", this, null);
+ }
+ name = //attributeName[ attributeCount ] =
+ newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+ //pos - 1 - (colonPos + 1 - bufAbsoluteStart)
+ }
+ } else {
+ if (colonPos != -1) {
+ int prefixLen = colonPos - nameStart;
+ prefix = attributePrefix[attributeCount] =
+ newString(buf, nameStart - bufAbsoluteStart, prefixLen);
+ //colonPos - (nameStart - bufAbsoluteStart));
+ int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+ name = attributeName[attributeCount] =
+ newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+ //pos - 1 - (colonPos + 1 - bufAbsoluteStart));
+
+ //name.substring(0, colonPos-nameStart);
+ } else {
+ prefix = attributePrefix[attributeCount] = null;
+ name = attributeName[attributeCount] =
+ newString(buf, nameStart - bufAbsoluteStart,
+ pos - 1 - (nameStart - bufAbsoluteStart));
+ }
+ if (!allStringsInterned) {
+ attributeNameHash[attributeCount] = name.hashCode();
+ }
+ }
+
+ } else {
+ // retrieve name
+ name = attributeName[attributeCount] =
+ newString(buf, nameStart - bufAbsoluteStart,
+ pos - 1 - (nameStart - bufAbsoluteStart));
+ ////assert name != null;
+ if (!allStringsInterned) {
+ attributeNameHash[attributeCount] = name.hashCode();
+ }
+ }
+
+ // [25] Eq ::= S? '=' S?
+ while (isS(ch)) {
+ ch = more();
+ } // skip additional spaces
+ if (ch != '=') throw new XmlPullParserException(
+ "expected = after attribute name", this, null);
+ ch = more();
+ while (isS(ch)) {
+ ch = more();
+ } // skip additional spaces
+
+ // [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
+ // | "'" ([^<&'] | Reference)* "'"
+ final char delimit = ch;
+ if (delimit != '"' && delimit != '\'') throw new XmlPullParserException(
+ "attribute value must start with quotation or apostrophe not "
+ + printable(delimit), this, null);
+ // parse until delimit or < and resolve Reference
+ //[67] Reference ::= EntityRef | CharRef
+ //int valueStart = pos + bufAbsoluteStart;
+
+
+ boolean normalizedCR = false;
+ usePC = false;
+ pcStart = pcEnd;
+ posStart = pos;
+
+ while (true) {
+ ch = more();
+ if (ch == delimit) {
+ break;
+ }
+ if (ch == '<') {
+ throw new XmlPullParserException(
+ "markup not allowed inside attribute value - illegal < ", this, null);
+ }
+ if (ch == '&') {
+ // extractEntityRef
+ posEnd = pos - 1;
+ if (!usePC) {
+ final boolean hadCharData = posEnd > posStart;
+ if (hadCharData) {
+ // posEnd is already set correctly!!!
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+
+ final char[] resolvedEntity = parseEntityRef();
+ // check if replacement text can be resolved !!!
+ if (resolvedEntity == null) {
+ if (entityRefName == null) {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ }
+ throw new XmlPullParserException(
+ "could not resolve entity named '" + printable(entityRefName) + "'",
+ this, null);
+ }
+ // write into PC replacement text - do merge for replacement text!!!!
+ for (int i = 0; i < resolvedEntity.length; i++) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = resolvedEntity[i];
+ }
+ } else if (ch == '\t' || ch == '\n' || ch == '\r') {
+ // do attribute value normalization
+ // as described in http://www.w3.org/TR/REC-xml#AVNormalize
+ // TODO add test for it form spec ...
+ // handle EOL normalization ...
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcEnd = pcStart = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ if (ch != '\n' || !normalizedCR) {
+ pc[pcEnd++] = ' '; //'\n';
+ }
+
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ }
+ normalizedCR = ch == '\r';
+ }
+
+
+ if (processNamespaces && startsWithXmlns) {
+ String ns = null;
+ if (!usePC) {
+ ns = newStringIntern(buf, posStart, pos - 1 - posStart);
+ } else {
+ ns = newStringIntern(pc, pcStart, pcEnd - pcStart);
+ }
+ ensureNamespacesCapacity(namespaceEnd);
+ int prefixHash = -1;
+ if (colonPos != -1) {
+ if (ns.length() == 0) {
+ throw new XmlPullParserException(
+ "non-default namespace can not be declared to be empty string", this, null);
+ }
+ // declare new namespace
+ namespacePrefix[namespaceEnd] = name;
+ if (!allStringsInterned) {
+ prefixHash = namespacePrefixHash[namespaceEnd] = name.hashCode();
+ }
+ } else {
+ // declare new default namespace ...
+ namespacePrefix[namespaceEnd] = null; //""; //null; //TODO check FIXME Alek
+ if (!allStringsInterned) {
+ prefixHash = namespacePrefixHash[namespaceEnd] = -1;
+ }
+ }
+ namespaceUri[namespaceEnd] = ns;
+
+ // detect duplicate namespace declarations!!!
+ final int startNs = elNamespaceCount[depth - 1];
+ for (int i = namespaceEnd - 1; i >= startNs; --i) {
+ if (((allStringsInterned || name == null) && namespacePrefix[i] == name)
+ || (!allStringsInterned && name != null &&
+ namespacePrefixHash[i] == prefixHash
+ && name.equals(namespacePrefix[i])
+ )) {
+ final String s = name == null ? "default" : "'" + name + "'";
+ throw new XmlPullParserException(
+ "duplicated namespace declaration for " + s + " prefix", this, null);
+ }
+ }
+
+ ++namespaceEnd;
+
+ } else {
+ if (!usePC) {
+ attributeValue[attributeCount] =
+ new String(buf, posStart, pos - 1 - posStart);
+ } else {
+ attributeValue[attributeCount] =
+ new String(pc, pcStart, pcEnd - pcStart);
+ }
+ ++attributeCount;
+ }
+ posStart = prevPosStart - bufAbsoluteStart;
+ return ch;
+ }
+
+ protected char[] charRefOneCharBuf = new char[1];
+
+ protected char[] parseEntityRef()
+ throws XmlPullParserException, IOException {
+ // entity reference http://www.w3.org/TR/2000/REC-xml-20001006#NT-Reference
+ // [67] Reference ::= EntityRef | CharRef
+
+ // ASSUMPTION just after &
+ entityRefName = null;
+ posStart = pos;
+ char ch = more();
+ if (ch == '#') {
+ // parse character reference
+ char charRef = 0;
+ ch = more();
+ if (ch == 'x') {
+ //encoded in hex
+ while (true) {
+ ch = more();
+ if (ch >= '0' && ch <= '9') {
+ charRef = (char) (charRef * 16 + (ch - '0'));
+ } else if (ch >= 'a' && ch <= 'f') {
+ charRef = (char) (charRef * 16 + (ch - ('a' - 10)));
+ } else if (ch >= 'A' && ch <= 'F') {
+ charRef = (char) (charRef * 16 + (ch - ('A' - 10)));
+ } else if (ch == ';') {
+ break;
+ } else {
+ throw new XmlPullParserException(
+ "character reference (with hex value) may not contain "
+ + printable(ch), this, null);
+ }
+ }
+ } else {
+ // encoded in decimal
+ while (true) {
+ if (ch >= '0' && ch <= '9') {
+ charRef = (char) (charRef * 10 + (ch - '0'));
+ } else if (ch == ';') {
+ break;
+ } else {
+ throw new XmlPullParserException(
+ "character reference (with decimal value) may not contain "
+ + printable(ch), this, null);
+ }
+ ch = more();
+ }
+ }
+ posEnd = pos - 1;
+ charRefOneCharBuf[0] = charRef;
+ if (tokenize) {
+ text = newString(charRefOneCharBuf, 0, 1);
+ }
+ return charRefOneCharBuf;
+ } else {
+ // [68] EntityRef ::= '&' Name ';'
+ // scan name until ;
+ if (!isNameStartChar(ch)) {
+ throw new XmlPullParserException(
+ "entity reference names can not start with character '"
+ + printable(ch) + "'", this, null);
+ }
+ while (true) {
+ ch = more();
+ if (ch == ';') {
+ break;
+ }
+ if (!isNameChar(ch)) {
+ throw new XmlPullParserException(
+ "entity reference name can not contain character "
+ + printable(ch) + "'", this, null);
+ }
+ }
+ posEnd = pos - 1;
+ // determine what name maps to
+ final int len = posEnd - posStart;
+ if (len == 2 && buf[posStart] == 'l' && buf[posStart + 1] == 't') {
+ if (tokenize) {
+ text = "<";
+ }
+ charRefOneCharBuf[0] = '<';
+ return charRefOneCharBuf;
+ //if(paramPC || isParserTokenizing) {
+ // if(pcEnd >= pc.length) ensurePC();
+ // pc[pcEnd++] = '<';
+ //}
+ } else if (len == 3 && buf[posStart] == 'a'
+ && buf[posStart + 1] == 'm' && buf[posStart + 2] == 'p') {
+ if (tokenize) {
+ text = "&";
+ }
+ charRefOneCharBuf[0] = '&';
+ return charRefOneCharBuf;
+ } else if (len == 2 && buf[posStart] == 'g' && buf[posStart + 1] == 't') {
+ if (tokenize) {
+ text = ">";
+ }
+ charRefOneCharBuf[0] = '>';
+ return charRefOneCharBuf;
+ } else if (len == 4 && buf[posStart] == 'a' && buf[posStart + 1] == 'p'
+ && buf[posStart + 2] == 'o' && buf[posStart + 3] == 's') {
+ if (tokenize) {
+ text = "'";
+ }
+ charRefOneCharBuf[0] = '\'';
+ return charRefOneCharBuf;
+ } else if (len == 4 && buf[posStart] == 'q' && buf[posStart + 1] == 'u'
+ && buf[posStart + 2] == 'o' && buf[posStart + 3] == 't') {
+ if (tokenize) {
+ text = "\"";
+ }
+ charRefOneCharBuf[0] = '"';
+ return charRefOneCharBuf;
+ } else {
+ final char[] result = lookuEntityReplacement(len);
+ if (result != null) {
+ return result;
+ }
+ }
+ if (tokenize) text = null;
+ return null;
+ }
+ }
+
+ protected char[] lookuEntityReplacement(int entitNameLen)
+ throws XmlPullParserException, IOException {
+ if (!allStringsInterned) {
+ final int hash = fastHash(buf, posStart, posEnd - posStart);
+ LOOP:
+ for (int i = entityEnd - 1; i >= 0; --i) {
+ if (hash == entityNameHash[i] && entitNameLen == entityNameBuf[i].length) {
+ final char[] entityBuf = entityNameBuf[i];
+ for (int j = 0; j < entitNameLen; j++) {
+ if (buf[posStart + j] != entityBuf[j]) continue LOOP;
+ }
+ if (tokenize) text = entityReplacement[i];
+ return entityReplacementBuf[i];
+ }
+ }
+ } else {
+ entityRefName = newString(buf, posStart, posEnd - posStart);
+ for (int i = entityEnd - 1; i >= 0; --i) {
+ // take advantage that interning for newStirng is enforced
+ if (entityRefName == entityName[i]) {
+ if (tokenize) text = entityReplacement[i];
+ return entityReplacementBuf[i];
+ }
+ }
+ }
+ return null;
+ }
+
+
+ protected void parseComment()
+ throws XmlPullParserException, IOException {
+ // implements XML 1.0 Section 2.5 Comments
+
+ //ASSUMPTION: seen <!-
+ char ch = more();
+ if (ch != '-') throw new XmlPullParserException(
+ "expected <!-- for comment start", this, null);
+ if (tokenize) posStart = pos;
+
+ final int curLine = lineNumber;
+ final int curColumn = columnNumber;
+ try {
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+
+ boolean seenDash = false;
+ boolean seenDashDash = false;
+ while (true) {
+ // scan until it hits -->
+ ch = more();
+ if (seenDashDash && ch != '>') {
+ throw new XmlPullParserException(
+ "in comment after two dashes (--) next character must be >"
+ + " not " + printable(ch), this, null);
+ }
+ if (ch == '-') {
+ if (!seenDash) {
+ seenDash = true;
+ } else {
+ seenDashDash = true;
+ seenDash = false;
+ }
+ } else if (ch == '>') {
+ if (seenDashDash) {
+ break; // found end sequence!!!!
+ } else {
+ seenDashDash = false;
+ }
+ seenDash = false;
+ } else {
+ seenDash = false;
+ }
+ if (normalizeIgnorableWS) {
+ if (ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is already set
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ }
+
+ } catch (EOFException ex) {
+ // detect EOF and create meaningful error ...
+ throw new XmlPullParserException(
+ "comment started on line " + curLine + " and column " + curColumn + " was not closed",
+ this, ex);
+ }
+ if (tokenize) {
+ posEnd = pos - 3;
+ if (usePC) {
+ pcEnd -= 2;
+ }
+ }
+ }
+
+ protected boolean parsePI()
+ throws XmlPullParserException, IOException {
+ // implements XML 1.0 Section 2.6 Processing Instructions
+
+ // [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
+ // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+ //ASSUMPTION: seen <?
+ if (tokenize) posStart = pos;
+ final int curLine = lineNumber;
+ final int curColumn = columnNumber;
+ int piTargetStart = pos + bufAbsoluteStart;
+ int piTargetEnd = -1;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+
+ try {
+ boolean seenQ = false;
+ char ch = more();
+ if (isS(ch)) {
+ throw new XmlPullParserException(
+ "processing instruction PITarget must be exactly after <? and not white space character",
+ this, null);
+ }
+ while (true) {
+ // scan until it hits ?>
+ //ch = more();
+
+ if (ch == '?') {
+ seenQ = true;
+ } else if (ch == '>') {
+ if (seenQ) {
+ break; // found end sequence!!!!
+ }
+ seenQ = false;
+ } else {
+ if (piTargetEnd == -1 && isS(ch)) {
+ piTargetEnd = pos - 1 + bufAbsoluteStart;
+
+ // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+ if ((piTargetEnd - piTargetStart) == 3) {
+ if ((buf[piTargetStart] == 'x' || buf[piTargetStart] == 'X')
+ && (buf[piTargetStart + 1] == 'm' || buf[piTargetStart + 1] == 'M')
+ && (buf[piTargetStart + 2] == 'l' || buf[piTargetStart + 2] == 'L')
+ ) {
+ if (piTargetStart > 3) { //<?xml is allowed as first characters in input ...
+ throw new XmlPullParserException(
+ "processing instruction can not have PITarget with reserveld xml name",
+ this, null);
+ } else {
+ if (buf[piTargetStart] != 'x'
+ && buf[piTargetStart + 1] != 'm'
+ && buf[piTargetStart + 2] != 'l') {
+ throw new XmlPullParserException(
+ "XMLDecl must have xml name in lowercase",
+ this, null);
+ }
+ }
+ parseXmlDecl(ch);
+ if (tokenize) posEnd = pos - 2;
+ final int off = piTargetStart - bufAbsoluteStart + 3;
+ final int len = pos - 2 - off;
+ xmlDeclContent = newString(buf, off, len);
+ return false;
+ }
+ }
+ }
+ seenQ = false;
+ }
+ if (normalizeIgnorableWS) {
+ if (ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is already set
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ ch = more();
+ }
+ } catch (EOFException ex) {
+ // detect EOF and create meaningful error ...
+ throw new XmlPullParserException(
+ "processing instruction started on line " + curLine + " and column " + curColumn
+ + " was not closed",
+ this, ex);
+ }
+ if (piTargetEnd == -1) {
+ piTargetEnd = pos - 2 + bufAbsoluteStart;
+ //throw new XmlPullParserException(
+ // "processing instruction must have PITarget name", this, null);
+ }
+ piTargetStart -= bufAbsoluteStart;
+ piTargetEnd -= bufAbsoluteStart;
+ if (tokenize) {
+ posEnd = pos - 2;
+ if (normalizeIgnorableWS) {
+ --pcEnd;
+ }
+ }
+ return true;
+ }
+
+ // protected final static char[] VERSION = {'v','e','r','s','i','o','n'};
+ // protected final static char[] NCODING = {'n','c','o','d','i','n','g'};
+ // protected final static char[] TANDALONE = {'t','a','n','d','a','l','o','n','e'};
+ // protected final static char[] YES = {'y','e','s'};
+ // protected final static char[] NO = {'n','o'};
+
+ protected final static char[] VERSION = "version".toCharArray();
+ protected final static char[] NCODING = "ncoding".toCharArray();
+ protected final static char[] TANDALONE = "tandalone".toCharArray();
+ protected final static char[] YES = "yes".toCharArray();
+ protected final static char[] NO = "no".toCharArray();
+
+
+ protected void parseXmlDecl(char ch)
+ throws XmlPullParserException, IOException {
+ // [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+
+ // first make sure that relative positions will stay OK
+ preventBufferCompaction = true;
+ bufStart = 0; // necessary to keep pos unchanged during expansion!
+
+ // --- parse VersionInfo
+
+ // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
+ // parse is positioned just on first S past <?xml
+ ch = skipS(ch);
+ ch = requireInput(ch, VERSION);
+ // [25] Eq ::= S? '=' S?
+ ch = skipS(ch);
+ if (ch != '=') {
+ throw new XmlPullParserException(
+ "expected equals sign (=) after version and not " + printable(ch), this, null);
+ }
+ ch = more();
+ ch = skipS(ch);
+ if (ch != '\'' && ch != '"') {
+ throw new XmlPullParserException(
+ "expected apostrophe (') or quotation mark (\") after version and not "
+ + printable(ch), this, null);
+ }
+ final char quotChar = ch;
+ //int versionStart = pos + bufAbsoluteStart; // required if preventBufferCompaction==false
+ final int versionStart = pos;
+ ch = more();
+ // [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
+ while (ch != quotChar) {
+ if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9')
+ && ch != '_' && ch != '.' && ch != ':' && ch != '-') {
+ throw new XmlPullParserException(
+ "<?xml version value expected to be in ([a-zA-Z0-9_.:] | '-')"
+ + " not " + printable(ch), this, null);
+ }
+ ch = more();
+ }
+ final int versionEnd = pos - 1;
+ parseXmlDeclWithVersion(versionStart, versionEnd);
+ preventBufferCompaction = false; // alow again buffer commpaction - pos MAY chnage
+ }
+ //protected String xmlDeclVersion;
+
+ protected void parseXmlDeclWithVersion(int versionStart, int versionEnd)
+ throws XmlPullParserException, IOException {
+ // check version is "1.0"
+ if ((versionEnd - versionStart != 3)
+ || buf[versionStart] != '1'
+ || buf[versionStart + 1] != '.'
+ || buf[versionStart + 2] != '0') {
+ throw new XmlPullParserException(
+ "only 1.0 is supported as <?xml version not '"
+ + printable(new String(buf, versionStart, versionEnd - versionStart)) + "'", this, null);
+ }
+ xmlDeclVersion = newString(buf, versionStart, versionEnd - versionStart);
+
+ // [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
+ char ch = more();
+ ch = skipS(ch);
+ if (ch == 'e') {
+ ch = more();
+ ch = requireInput(ch, NCODING);
+ ch = skipS(ch);
+ if (ch != '=') {
+ throw new XmlPullParserException(
+ "expected equals sign (=) after encoding and not " + printable(ch), this, null);
+ }
+ ch = more();
+ ch = skipS(ch);
+ if (ch != '\'' && ch != '"') {
+ throw new XmlPullParserException(
+ "expected apostrophe (') or quotation mark (\") after encoding and not "
+ + printable(ch), this, null);
+ }
+ final char quotChar = ch;
+ final int encodingStart = pos;
+ ch = more();
+ // [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z')) {
+ throw new XmlPullParserException(
+ "<?xml encoding name expected to start with [A-Za-z]"
+ + " not " + printable(ch), this, null);
+ }
+ ch = more();
+ while (ch != quotChar) {
+ if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9')
+ && ch != '.' && ch != '_' && ch != '-') {
+ throw new XmlPullParserException(
+ "<?xml encoding value expected to be in ([A-Za-z0-9._] | '-')"
+ + " not " + printable(ch), this, null);
+ }
+ ch = more();
+ }
+ final int encodingEnd = pos - 1;
+
+ // TODO reconcile with setInput encodingName
+ inputEncoding = newString(buf, encodingStart, encodingEnd - encodingStart);
+ ch = more();
+ }
+
+ ch = skipS(ch);
+ // [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
+ if (ch == 's') {
+ ch = more();
+ ch = requireInput(ch, TANDALONE);
+ ch = skipS(ch);
+ if (ch != '=') {
+ throw new XmlPullParserException(
+ "expected equals sign (=) after standalone and not " + printable(ch),
+ this, null);
+ }
+ ch = more();
+ ch = skipS(ch);
+ if (ch != '\'' && ch != '"') {
+ throw new XmlPullParserException(
+ "expected apostrophe (') or quotation mark (\") after encoding and not "
+ + printable(ch), this, null);
+ }
+ char quotChar = ch;
+ int standaloneStart = pos;
+ ch = more();
+ if (ch == 'y') {
+ ch = requireInput(ch, YES);
+ //Boolean standalone = new Boolean(true);
+ xmlDeclStandalone = new Boolean(true);
+ } else if (ch == 'n') {
+ ch = requireInput(ch, NO);
+ //Boolean standalone = new Boolean(false);
+ xmlDeclStandalone = new Boolean(false);
+ } else {
+ throw new XmlPullParserException(
+ "expected 'yes' or 'no' after standalone and not "
+ + printable(ch), this, null);
+ }
+ if (ch != quotChar) {
+ throw new XmlPullParserException(
+ "expected " + quotChar + " after standalone value not "
+ + printable(ch), this, null);
+ }
+ ch = more();
+ }
+
+
+ ch = skipS(ch);
+ if (ch != '?') {
+ throw new XmlPullParserException(
+ "expected ?> as last part of <?xml not "
+ + printable(ch), this, null);
+ }
+ ch = more();
+ if (ch != '>') {
+ throw new XmlPullParserException(
+ "expected ?> as last part of <?xml not "
+ + printable(ch), this, null);
+ }
+
+// NOTE: this code is broken as for some types of input streams (URLConnection ...)
+// it is not possible to do more than once new InputStreamReader(inputStream)
+// as it somehow detects it and closes undelrying inout stram (b.....d!)
+// In future one will need better low level byte-by-byte reading of prolog and then doing InputStream ...
+// for more details see http://www.extreme.indiana.edu/bugzilla/show_bug.cgi?id=135
+ // //reset input stream
+// if ((this.inputEncoding != oldEncoding) && (this.inputStream != null)) {
+// if ((this.inputEncoding != null) && (!this.inputEncoding.equalsIgnoreCase(oldEncoding))) {
+// // //there is need to reparse input to set location OK
+// // reset();
+// this.reader = new InputStreamReader(this.inputStream, this.inputEncoding);
+// // //skip <?xml
+// // for (int i = 0; i < 5; i++){
+// // ch=more();
+// // }
+// // parseXmlDecl(ch);
+// }
+// }
+ }
+
+ protected void parseDocdecl()
+ throws XmlPullParserException, IOException {
+ //ASSUMPTION: seen <!D
+ char ch = more();
+ if (ch != 'O') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ ch = more();
+ if (ch != 'C') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ ch = more();
+ if (ch != 'T') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ ch = more();
+ if (ch != 'Y') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ ch = more();
+ if (ch != 'P') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ ch = more();
+ if (ch != 'E') throw new XmlPullParserException(
+ "expected <!DOCTYPE", this, null);
+ posStart = pos;
+ // do simple and crude scanning for end of doctype
+
+ // [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('['
+ // (markupdecl | DeclSep)* ']' S?)? '>'
+ int bracketLevel = 0;
+ final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+ boolean normalizedCR = false;
+ while (true) {
+ ch = more();
+ if (ch == '[') ++bracketLevel;
+ if (ch == ']') --bracketLevel;
+ if (ch == '>' && bracketLevel == 0) break;
+ if (normalizeIgnorableWS) {
+ if (ch == '\r') {
+ normalizedCR = true;
+ //posEnd = pos -1;
+ //joinPC();
+ // posEnd is alreadys set
+ if (!usePC) {
+ posEnd = pos - 1;
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+
+ }
+ posEnd = pos - 1;
+ }
+
+ protected void parseCDSect(boolean hadCharData)
+ throws XmlPullParserException, IOException {
+ // implements XML 1.0 Section 2.7 CDATA Sections
+
+ // [18] CDSect ::= CDStart CData CDEnd
+ // [19] CDStart ::= '<![CDATA['
+ // [20] CData ::= (Char* - (Char* ']]>' Char*))
+ // [21] CDEnd ::= ']]>'
+
+ //ASSUMPTION: seen <![
+ char ch = more();
+ if (ch != 'C') throw new XmlPullParserException(
+ "expected <[CDATA[ for comment start", this, null);
+ ch = more();
+ if (ch != 'D') throw new XmlPullParserException(
+ "expected <[CDATA[ for comment start", this, null);
+ ch = more();
+ if (ch != 'A') throw new XmlPullParserException(
+ "expected <[CDATA[ for comment start", this, null);
+ ch = more();
+ if (ch != 'T') throw new XmlPullParserException(
+ "expected <[CDATA[ for comment start", this, null);
+ ch = more();
+ if (ch != 'A') throw new XmlPullParserException(
+ "expected <[CDATA[ for comment start", this, null);
+ ch = more();
+ if (ch != '[') throw new XmlPullParserException(
+ "expected <![CDATA[ for comment start", this, null);
+
+ //if(tokenize) {
+ final int cdStart = pos + bufAbsoluteStart;
+ final int curLine = lineNumber;
+ final int curColumn = columnNumber;
+ final boolean normalizeInput = tokenize == false || roundtripSupported == false;
+ try {
+ if (normalizeInput) {
+ if (hadCharData) {
+ if (!usePC) {
+ // posEnd is correct already!!!
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ }
+ }
+ boolean seenBracket = false;
+ boolean seenBracketBracket = false;
+ boolean normalizedCR = false;
+ while (true) {
+ // scan until it hits "]]>"
+ ch = more();
+ if (ch == ']') {
+ if (!seenBracket) {
+ seenBracket = true;
+ } else {
+ seenBracketBracket = true;
+ //seenBracket = false;
+ }
+ } else if (ch == '>') {
+ if (seenBracket && seenBracketBracket) {
+ break; // found end sequence!!!!
+ } else {
+ seenBracketBracket = false;
+ }
+ seenBracket = false;
+ } else {
+ if (seenBracket) {
+ seenBracket = false;
+ }
+ }
+ if (normalizeInput) {
+ // deal with normalization issues ...
+ if (ch == '\r') {
+ normalizedCR = true;
+ posStart = cdStart - bufAbsoluteStart;
+ posEnd = pos - 1; // posEnd is alreadys set
+ if (!usePC) {
+ if (posEnd > posStart) {
+ joinPC();
+ } else {
+ usePC = true;
+ pcStart = pcEnd = 0;
+ }
+ }
+ //assert usePC == true;
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ } else if (ch == '\n') {
+ if (!normalizedCR && usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = '\n';
+ }
+ normalizedCR = false;
+ } else {
+ if (usePC) {
+ if (pcEnd >= pc.length) ensurePC(pcEnd);
+ pc[pcEnd++] = ch;
+ }
+ normalizedCR = false;
+ }
+ }
+ }
+ } catch (EOFException ex) {
+ // detect EOF and create meaningful error ...
+ throw new XmlPullParserException(
+ "CDATA section started on line " + curLine + " and column " + curColumn + " was not closed",
+ this, ex);
+ }
+ if (normalizeInput) {
+ if (usePC) {
+ pcEnd = pcEnd - 2;
+ }
+ }
+ posStart = cdStart - bufAbsoluteStart;
+ posEnd = pos - 3;
+ }
+
+ protected void fillBuf() throws IOException, XmlPullParserException {
+ if (reader == null) throw new XmlPullParserException(
+ "reader must be set before parsing is started");
+
+ // see if we are in compaction area
+ if (bufEnd > bufSoftLimit) {
+
+ // expand buffer it makes sense!!!!
+ boolean compact = bufStart > bufSoftLimit;
+ boolean expand = false;
+ if (preventBufferCompaction) {
+ compact = false;
+ expand = true;
+ } else if (!compact) {
+ //freeSpace
+ if (bufStart < buf.length / 2) {
+ // less then half buffer available forcompactin --> expand instead!!!
+ expand = true;
+ } else {
+ // at least half of buffer can be reclaimed --> worthwhile effort!!!
+ compact = true;
+ }
+ }
+
+ // if buffer almost full then compact it
+ if (compact) {
+ //TODO: look on trashing
+ // //assert bufStart > 0
+ System.arraycopy(buf, bufStart, buf, 0, bufEnd - bufStart);
+ if (TRACE_SIZING) System.out.println(
+ "TRACE_SIZING fillBuf() compacting " + bufStart
+ + " bufEnd=" + bufEnd
+ + " pos=" + pos + " posStart=" + posStart + " posEnd=" + posEnd
+ + " buf first 100 chars:" + new String(buf, bufStart,
+ bufEnd - bufStart < 100 ? bufEnd - bufStart : 100));
+
+ } else if (expand) {
+ final int newSize = 2 * buf.length;
+ final char newBuf[] = new char[newSize];
+ if (TRACE_SIZING) System.out.println("TRACE_SIZING fillBuf() " + buf.length + " => " + newSize);
+ System.arraycopy(buf, bufStart, newBuf, 0, bufEnd - bufStart);
+ buf = newBuf;
+ if (bufLoadFactor > 0) {
+ //bufSoftLimit = ( bufLoadFactor * buf.length ) /100;
+ bufSoftLimit = (int) ((((long) bufLoadFactor) * buf.length) / 100);
+ }
+
+ } else {
+ throw new XmlPullParserException("internal error in fillBuffer()");
+ }
+ bufEnd -= bufStart;
+ pos -= bufStart;
+ posStart -= bufStart;
+ posEnd -= bufStart;
+ bufAbsoluteStart += bufStart;
+ bufStart = 0;
+ if (TRACE_SIZING) System.out.println(
+ "TRACE_SIZING fillBuf() after bufEnd=" + bufEnd
+ + " pos=" + pos + " posStart=" + posStart + " posEnd=" + posEnd
+ + " buf first 100 chars:" + new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
+ }
+ // at least one character must be read or error
+ final int len = buf.length - bufEnd > READ_CHUNK_SIZE ? READ_CHUNK_SIZE : buf.length - bufEnd;
+ final int ret = reader.read(buf, bufEnd, len);
+ if (ret > 0) {
+ bufEnd += ret;
+ if (TRACE_SIZING) System.out.println(
+ "TRACE_SIZING fillBuf() after filling in buffer"
+ + " buf first 100 chars:" + new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
+
+ return;
+ }
+ if (ret == -1) {
+ if (bufAbsoluteStart == 0 && pos == 0) {
+ throw new EOFException("input contained no data");
+ } else {
+ if (seenRoot && depth == 0) { // inside parsing epilog!!!
+ reachedEnd = true;
+ return;
+ } else {
+ StringBuffer expectedTagStack = new StringBuffer();
+ if (depth > 0) {
+ //final char[] cbuf = elRawName[depth];
+ //final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+ expectedTagStack.append(" - expected end tag");
+ if (depth > 1) {
+ expectedTagStack.append("s"); //more than one end tag
+ }
+ expectedTagStack.append(" ");
+ for (int i = depth; i > 0; i--) {
+ String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
+ expectedTagStack.append("</").append(tagName).append('>');
+ }
+ expectedTagStack.append(" to close");
+ for (int i = depth; i > 0; i--) {
+ if (i != depth) {
+ expectedTagStack.append(" and"); //more than one end tag
+ }
+ String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
+ expectedTagStack.append(" start tag <" + tagName + ">");
+ expectedTagStack.append(" from line " + elRawNameLine[i]);
+ }
+ expectedTagStack.append(", parser stopped on");
+ }
+ throw new EOFException("no more data available"
+ + expectedTagStack.toString() + getPositionDescription());
+ }
+ }
+ } else {
+ throw new IOException("error reading input, returned " + ret);
+ }
+ }
+
+ protected char more() throws IOException, XmlPullParserException {
+ if (pos >= bufEnd) {
+ fillBuf();
+ // this return value should be ignonored as it is used in epilog parsing ...
+ if (reachedEnd) return (char) -1;
+ }
+ final char ch = buf[pos++];
+ //line/columnNumber
+ if (ch == '\n') {
+ ++lineNumber;
+ columnNumber = 1;
+ } else {
+ ++columnNumber;
+ }
+ //System.out.print(ch);
+ return ch;
+ }
+
+ // /**
+ // * This function returns position of parser in XML input stream
+ // * (how many <b>characters</b> were processed.
+ // * <p><b>NOTE:</b> this logical position and not byte offset as encodings
+ // * such as UTF8 may use more than one byte to encode one character.
+ // */
+ // public int getCurrentInputPosition() {
+ // return pos + bufAbsoluteStart;
+ // }
+
+ protected void ensurePC(int end) {
+ //assert end >= pc.length;
+ final int newSize = end > READ_CHUNK_SIZE ? 2 * end : 2 * READ_CHUNK_SIZE;
+ final char[] newPC = new char[newSize];
+ if (TRACE_SIZING)
+ System.out.println("TRACE_SIZING ensurePC() " + pc.length + " ==> " + newSize + " end=" + end);
+ System.arraycopy(pc, 0, newPC, 0, pcEnd);
+ pc = newPC;
+ //assert end < pc.length;
+ }
+
+ protected void joinPC() {
+ //assert usePC == false;
+ //assert posEnd > posStart;
+ final int len = posEnd - posStart;
+ final int newEnd = pcEnd + len + 1;
+ if (newEnd >= pc.length) ensurePC(newEnd); // add 1 for extra space for one char
+ //assert newEnd < pc.length;
+ System.arraycopy(buf, posStart, pc, pcEnd, len);
+ pcEnd += len;
+ usePC = true;
+
+ }
+
+ protected char requireInput(char ch, char[] input)
+ throws XmlPullParserException, IOException {
+ for (int i = 0; i < input.length; i++) {
+ if (ch != input[i]) {
+ throw new XmlPullParserException(
+ "expected " + printable(input[i]) + " in " + new String(input)
+ + " and not " + printable(ch), this, null);
+ }
+ ch = more();
+ }
+ return ch;
+ }
+
+ protected char requireNextS()
+ throws XmlPullParserException, IOException {
+ final char ch = more();
+ if (!isS(ch)) {
+ throw new XmlPullParserException(
+ "white space is required and not " + printable(ch), this, null);
+ }
+ return skipS(ch);
+ }
+
+ protected char skipS(char ch)
+ throws XmlPullParserException, IOException {
+ while (isS(ch)) {
+ ch = more();
+ } // skip additional spaces
+ return ch;
+ }
+
+ // nameStart / name lookup tables based on XML 1.1 http://www.w3.org/TR/2001/WD-xml11-20011213/
+ protected static final int LOOKUP_MAX = 0x400;
+ protected static final char LOOKUP_MAX_CHAR = (char) LOOKUP_MAX;
+ // protected static int lookupNameStartChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
+ // protected static int lookupNameChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
+ protected static boolean lookupNameStartChar[] = new boolean[LOOKUP_MAX];
+ protected static boolean lookupNameChar[] = new boolean[LOOKUP_MAX];
+
+ private static final void setName(char ch)
+ //{ lookupNameChar[ (int)ch / 32 ] |= (1 << (ch % 32)); }
+ {
+ lookupNameChar[ch] = true;
+ }
+
+ private static final void setNameStart(char ch)
+ //{ lookupNameStartChar[ (int)ch / 32 ] |= (1 << (ch % 32)); setName(ch); }
+ {
+ lookupNameStartChar[ch] = true;
+ setName(ch);
+ }
+
+ static {
+ setNameStart(':');
+ for (char ch = 'A'; ch <= 'Z'; ++ch) setNameStart(ch);
+ setNameStart('_');
+ for (char ch = 'a'; ch <= 'z'; ++ch) setNameStart(ch);
+ for (char ch = '\u00c0'; ch <= '\u02FF'; ++ch) setNameStart(ch);
+ for (char ch = '\u0370'; ch <= '\u037d'; ++ch) setNameStart(ch);
+ for (char ch = '\u037f'; ch < '\u0400'; ++ch) setNameStart(ch);
+
+ setName('-');
+ setName('.');
+ for (char ch = '0'; ch <= '9'; ++ch) setName(ch);
+ setName('\u00b7');
+ for (char ch = '\u0300'; ch <= '\u036f'; ++ch) setName(ch);
+ }
+
+ //private final static boolean isNameStartChar(char ch) {
+ protected boolean isNameStartChar(char ch) {
+ return (ch < LOOKUP_MAX_CHAR && lookupNameStartChar[ch])
+ || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
+ || (ch >= '\u202A' && ch <= '\u218F')
+ || (ch >= '\u2800' && ch <= '\uFFEF')
+ ;
+
+ // if(ch < LOOKUP_MAX_CHAR) return lookupNameStartChar[ ch ];
+ // else return ch <= '\u2027'
+ // || (ch >= '\u202A' && ch <= '\u218F')
+ // || (ch >= '\u2800' && ch <= '\uFFEF')
+ // ;
+ //return false;
+ // return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
+ // || (ch >= '0' && ch <= '9');
+ // if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+ // if(ch <= '\u2027') return true;
+ // //[#x202A-#x218F]
+ // if(ch < '\u202A') return false;
+ // if(ch <= '\u218F') return true;
+ // // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
+ // if(ch < '\u2800') return false;
+ // if(ch <= '\uFFEF') return true;
+ // return false;
+
+
+ // else return (supportXml11 && ( (ch < '\u2027') || (ch > '\u2029' && ch < '\u2200') ...
+ }
+
+ //private final static boolean isNameChar(char ch) {
+ protected boolean isNameChar(char ch) {
+ //return isNameStartChar(ch);
+
+ // if(ch < LOOKUP_MAX_CHAR) return (lookupNameChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+
+ return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ch])
+ || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
+ || (ch >= '\u202A' && ch <= '\u218F')
+ || (ch >= '\u2800' && ch <= '\uFFEF')
+ ;
+ //return false;
+ // return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
+ // || (ch >= '0' && ch <= '9');
+ // if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+
+ //else return
+ // else if(ch <= '\u2027') return true;
+ // //[#x202A-#x218F]
+ // else if(ch < '\u202A') return false;
+ // else if(ch <= '\u218F') return true;
+ // // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
+ // else if(ch < '\u2800') return false;
+ // else if(ch <= '\uFFEF') return true;
+ //else return false;
+ }
+
+ protected boolean isS(char ch) {
+ return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
+ // || (supportXml11 && (ch == '\u0085' || ch == '\u2028');
+ }
+
+ //protected boolean isChar(char ch) { return (ch < '\uD800' || ch > '\uDFFF')
+ // ch != '\u0000' ch < '\uFFFE'
+
+
+ //protected char printable(char ch) { return ch; }
+ protected String printable(char ch) {
+ if (ch == '\n') {
+ return "\\n";
+ } else if (ch == '\r') {
+ return "\\r";
+ } else if (ch == '\t') {
+ return "\\t";
+ } else if (ch == '\'') {
+ return "\\'";
+ }
+ if (ch > 127 || ch < 32) {
+ return "\\u" + Integer.toHexString((int) ch);
+ }
+ return "" + ch;
+ }
+
+ protected String printable(String s) {
+ if (s == null) return null;
+ final int sLen = s.length();
+ StringBuffer buf = new StringBuffer(sLen + 10);
+ for (int i = 0; i < sLen; ++i) {
+ buf.append(printable(s.charAt(i)));
+ }
+ s = buf.toString();
+ return s;
+ }
+}
+
+
+/*
+ * Indiana University Extreme! Lab Software License, Version 1.2
+ *
+ * Copyright (C) 2003 The Trustees of Indiana University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1) All redistributions of source code must retain the above
+ * copyright notice, the list of authors in the original source
+ * code, this list of conditions and the disclaimer listed in this
+ * license;
+ *
+ * 2) All redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the disclaimer
+ * listed in this license in the documentation and/or other
+ * materials provided with the distribution;
+ *
+ * 3) Any documentation included with all redistributions must include
+ * the following acknowledgement:
+ *
+ * "This product includes software developed by the Indiana
+ * University Extreme! Lab. For further information please visit
+ * http://www.extreme.indiana.edu/"
+ *
+ * Alternatively, this acknowledgment may appear in the software
+ * itself, and wherever such third-party acknowledgments normally
+ * appear.
+ *
+ * 4) The name "Indiana University" or "Indiana University
+ * Extreme! Lab" shall not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission from Indiana University. For written permission,
+ * please contact http://www.extreme.indiana.edu/.
+ *
+ * 5) Products derived from this software may not use "Indiana
+ * University" name nor may "Indiana University" appear in their name,
+ * without prior written permission of the Indiana University.
+ *
+ * Indiana University provides no reassurances that the source code
+ * provided does not infringe the patent or any other intellectual
+ * property rights of any other entity. Indiana University disclaims any
+ * liability to any recipient for claims brought by any other entity
+ * based on infringement of intellectual property rights or otherwise.
+ *
+ * LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
+ * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA
+ * UNIVERSITY GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT
+ * SOFTWARE IS FREE OF INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR
+ * OTHER PROPRIETARY RIGHTS. INDIANA UNIVERSITY MAKES NO WARRANTIES THAT
+ * SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES", "TRAP
+ * DOORS", "WORMS", OR OTHER HARMFUL CODE. LICENSEE ASSUMES THE ENTIRE
+ * RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS,
+ * AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING
+ * SOFTWARE.
+ */
+
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java
new file mode 100644
index 0000000..f31a090
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java
@@ -0,0 +1,964 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.apache.camel.xml.io;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * XML Pull Parser is an interface that defines parsing functionality provided in
+ * <a href="http://www.xmlpull.org/">XMLPULL V1 API</a> (visit this website to learn more about API and its
+ * implementations).
+ * <p>
+ * There are following different kinds of parser depending on which features are set:
+ * <ul>
+ * <li><b>non-validating</b> parser as defined in XML 1.0 spec when FEATURE_PROCESS_DOCDECL is set to true
+ * <li><b>validating parser</b> as defined in XML 1.0 spec when FEATURE_VALIDATION is true (and that implies that
+ * FEATURE_PROCESS_DOCDECL is true)
+ * <li>when FEATURE_PROCESS_DOCDECL is false (this is default and if different value is required necessary must be
+ * changed before parsing is started) then parser behaves like XML 1.0 compliant non-validating parser under condition
+ * that <em>no DOCDECL is present</em> in XML documents (internal entities can still be defined with
+ * defineEntityReplacementText()). This mode of operation is intended <b>for operation in constrained environments</b>
+ * such as J2ME.
+ * </ul>
+ * <p>
+ * There are two key methods: next() and nextToken(). While next() provides access to high level parsing events,
+ * nextToken() allows access to lower level tokens.
+ * <p>
+ * The current event state of the parser can be determined by calling the <a href="#getEventType()">getEventType()</a>
+ * method. Initially, the parser is in the <a href="#START_DOCUMENT">START_DOCUMENT</a> state.
+ * <p>
+ * The method <a href="#next()">next()</a> advances the parser to the next event. The int value returned from next
+ * determines the current parser state and is identical to the value returned from following calls to getEventType ().
+ * <p>
+ * The following event types are seen by next()
+ * <dl>
+ * <dt><a href="#START_TAG">START_TAG</a>
+ * <dd>An XML start tag was read.
+ * <dt><a href="#TEXT">TEXT</a>
+ * <dd>Text content was read; the text content can be retrieved using the getText() method. (when in validating mode
+ * next() will not report ignorable whitespaces, use nextToken() instead)
+ * <dt><a href="#END_TAG">END_TAG</a>
+ * <dd>An end tag was read
+ * <dt><a href="#END_DOCUMENT">END_DOCUMENT</a>
+ * <dd>No more events are available
+ * </dl>
+ * <p>
+ * after first next() or nextToken() (or any other next*() method) is called user application can obtain XML version,
+ * standalone and encoding from XML declaration in following ways:
+ * <ul>
+ * <li><b>version</b>: getProperty("<a href=
+ * "http://xmlpull.org/v1/doc/properties.html#xmldecl-version">http://xmlpull.org/v1/doc/properties.html#xmldecl-version</a>")
+ * returns String ("1.0") or null if XMLDecl was not read or if property is not supported
+ * <li><b>standalone</b>: getProperty("<a href=
+ * "http://xmlpull.org/v1/doc/features.html#xmldecl-standalone">http://xmlpull.org/v1/doc/features.html#xmldecl-standalone</a>")
+ * returns Boolean: null if there was no standalone declaration or if property is not supported otherwise returns
+ * Boolean(true) if standalone="yes" and Boolean(false) when standalone="no"
+ * <li><b>encoding</b>: obtained from getInputEncoding() null if stream had unknown encoding (not set in setInputStream)
+ * and it was not declared in XMLDecl
+ * </ul>
+ * A minimal example for using this API may look as follows:
+ *
+ * <pre>
+ * import java.io.IOException;
+ * import java.io.StringReader;
+ *
+ * import org.xmlpull.v1.XmlPullParser;
+ * import org.xmlpull.v1.XmlPullParserException;
+ * import org.xmlpull.v1.XmlPullParserFactory;
+ *
+ * public class SimpleXmlPullApp
+ * {
+ *
+ * public static void main (String args[])
+ * throws XmlPullParserException, IOException
+ * {
+ * XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ * factory.setNamespaceAware(true);
+ * XmlPullParser xpp = factory.newPullParser();
+ *
+ * xpp.setInput( new StringReader ( "<foo%gt;Hello World!</foo>" ) );
+ * int eventType = xpp.getEventType();
+ * while (eventType != xpp.END_DOCUMENT) {
+ * if(eventType == xpp.START_DOCUMENT) {
+ * System.out.println("Start document");
+ * } else if(eventType == xpp.END_DOCUMENT) {
+ * System.out.println("End document");
+ * } else if(eventType == xpp.START_TAG) {
+ * System.out.println("Start tag "+xpp.getName());
+ * } else if(eventType == xpp.END_TAG) {
+ * System.out.println("End tag "+xpp.getName());
+ * } else if(eventType == xpp.TEXT) {
+ * System.out.println("Text "+xpp.getText());
+ * }
+ * eventType = xpp.next();
+ * }
+ * }
+ * }
+ * </pre>
+ * <p>
+ * The above example will generate the following output:
+ *
+ * <pre>
+ * Start document
+ * Start tag foo
+ * Text Hello World!
+ * End tag foo
+ * </pre>
+ *
+ * For more details on API usage, please refer to the quick Introduction available at
+ * <a href="http://www.xmlpull.org">http://www.xmlpull.org</a>
+ *
+ * @see #defineEntityReplacementText
+ * @see #getName
+ * @see #getNamespace
+ * @see #getText
+ * @see #next
+ * @see #nextToken
+ * @see #setInput
+ * @see #FEATURE_PROCESS_DOCDECL
+ * @see #FEATURE_VALIDATION
+ * @see #START_DOCUMENT
+ * @see #START_TAG
+ * @see #TEXT
+ * @see #END_TAG
+ * @see #END_DOCUMENT
+ * @author <a href="http://www-ai.cs.uni-dortmund.de/PERSONAL/haustein.html">Stefan Haustein</a>
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public interface XmlPullParser
+{
+
+ /** This constant represents the default namespace (empty string "") */
+ String NO_NAMESPACE = "";
+
+ // ----------------------------------------------------------------------------
+ // EVENT TYPES as reported by next()
+
+ /**
+ * Signalize that parser is at the very beginning of the document and nothing was read yet. This event type can only
+ * be observed by calling getEvent() before the first call to next(), nextToken, or nextTag()).
+ *
+ * @see #next
+ * @see #nextToken
+ */
+ int START_DOCUMENT = 0;
+
+ /**
+ * Logical end of the xml document. Returned from getEventType, next() and nextToken() when the end of the input
+ * document has been reached.
+ * <p>
+ * <strong>NOTE:</strong> calling again <a href="#next()">next()</a> or <a href="#nextToken()">nextToken()</a> will
+ * result in exception being thrown.
+ *
+ * @see #next
+ * @see #nextToken
+ */
+ int END_DOCUMENT = 1;
+
+ /**
+ * Returned from getEventType(), <a href="#next()">next()</a>, <a href="#nextToken()">nextToken()</a> when a start
+ * tag was read. The name of start tag is available from getName(), its namespace and prefix are available from
+ * getNamespace() and getPrefix() if <a href='#FEATURE_PROCESS_NAMESPACES'>namespaces are enabled</a>. See
+ * getAttribute* methods to retrieve element attributes. See getNamespace* methods to retrieve newly declared
+ * namespaces.
+ *
+ * @see #next
+ * @see #nextToken
+ * @see #getName
+ * @see #getPrefix
+ * @see #getNamespace
+ * @see #getAttributeCount
+ * @see #getDepth
+ * @see #getNamespaceCount
+ * @see #getNamespace
+ * @see #FEATURE_PROCESS_NAMESPACES
+ */
+ int START_TAG = 2;
+
+ /**
+ * Returned from getEventType(), <a href="#next()">next()</a>, or <a href="#nextToken()">nextToken()</a> when an end
+ * tag was read. The name of start tag is available from getName(), its namespace and prefix are available from
+ * getNamespace() and getPrefix().
+ *
+ * @see #next
+ * @see #nextToken
+ * @see #getName
+ * @see #getPrefix
+ * @see #getNamespace
+ * @see #FEATURE_PROCESS_NAMESPACES
+ */
+ int END_TAG = 3;
+
+ /**
+ * Character data was read and will is available by calling getText().
+ * <p>
+ * <strong>Please note:</strong> <a href="#next()">next()</a> will accumulate multiple events into one TEXT event,
+ * skipping IGNORABLE_WHITESPACE, PROCESSING_INSTRUCTION and COMMENT events, In contrast,
+ * <a href="#nextToken()">nextToken()</a> will stop reading text when any other event is observed. Also, when the
+ * state was reached by calling next(), the text value will be normalized, whereas getText() will return
+ * unnormalized content in the case of nextToken(). This allows an exact roundtrip without changing line ends when
+ * examining low level events, whereas for high level applications the text is normalized appropriately.
+ *
+ * @see #next
+ * @see #nextToken
+ * @see #getText
+ */
+ int TEXT = 4;
+
+ // ----------------------------------------------------------------------------
+ // additional events exposed by lower level nextToken()
+
+ /**
+ * A CDATA sections was just read; this token is available only from calls to
+ * <a href="#nextToken()">nextToken()</a>. A call to next() will accumulate various text events into a single event
+ * of type TEXT. The text contained in the CDATA section is available by calling getText().
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int CDSECT = 5;
+
+ /**
+ * An entity reference was just read; this token is available from <a href="#nextToken()">nextToken()</a> only. The
+ * entity name is available by calling getName(). If available, the replacement text can be obtained by calling
+ * getTextt(); otherwise, the user is responsible for resolving the entity reference. This event type is never
+ * returned from next(); next() will accumulate the replacement text and other text events to a single TEXT event.
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int ENTITY_REF = 6;
+
+ /**
+ * Ignorable whitespace was just read. This token is available only from <a href="#nextToken()">nextToken()</a>).
+ * For non-validating parsers, this event is only reported by nextToken() when outside the root element. Validating
+ * parsers may be able to detect ignorable whitespace at other locations. The ignorable whitespace string is
+ * available by calling getText()
+ * <p>
+ * <strong>NOTE:</strong> this is different from calling the isWhitespace() method, since text content may be
+ * whitespace but not ignorable. Ignorable whitespace is skipped by next() automatically; this event type is never
+ * returned from next().
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int IGNORABLE_WHITESPACE = 7;
+
+ /**
+ * An XML processing instruction declaration was just read. This event type is available only via
+ * <a href="#nextToken()">nextToken()</a>. getText() will return text that is inside the processing instruction.
+ * Calls to next() will skip processing instructions automatically.
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int PROCESSING_INSTRUCTION = 8;
+
+ /**
+ * An XML comment was just read. This event type is this token is available via
+ * <a href="#nextToken()">nextToken()</a> only; calls to next() will skip comments automatically. The content of the
+ * comment can be accessed using the getText() method.
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int COMMENT = 9;
+
+ /**
+ * An XML document type declaration was just read. This token is available from
+ * <a href="#nextToken()">nextToken()</a> only. The unparsed text inside the doctype is available via the getText()
+ * method.
+ *
+ * @see #nextToken
+ * @see #getText
+ */
+ int DOCDECL = 10;
+
+ /**
+ * This array can be used to convert the event type integer constants such as START_TAG or TEXT to to a string. For
+ * example, the value of TYPES[START_TAG] is the string "START_TAG". This array is intended for diagnostic output
+ * only. Relying on the contents of the array may be dangerous since malicious applications may alter the array,
+ * although it is final, due to limitations of the Java language.
+ */
+ String[] TYPES = { "START_DOCUMENT", "END_DOCUMENT", "START_TAG", "END_TAG", "TEXT", "CDSECT", "ENTITY_REF",
+ "IGNORABLE_WHITESPACE", "PROCESSING_INSTRUCTION", "COMMENT", "DOCDECL" };
+
+ // ----------------------------------------------------------------------------
+ // namespace related features
+
+ /**
+ * This feature determines whether the parser processes namespaces. As for all features, the default value is false.
+ * <p>
+ * <strong>NOTE:</strong> The value can not be changed during parsing an must be set before parsing.
+ *
+ * @see #getFeature
+ * @see #setFeature
+ */
+ String FEATURE_PROCESS_NAMESPACES = "http://xmlpull.org/v1/doc/features.html#process-namespaces";
+
+ /**
+ * This feature determines whether namespace attributes are exposed via the attribute access methods. Like all
+ * features, the default value is false. This feature cannot be changed during parsing.
+ *
+ * @see #getFeature
+ * @see #setFeature
+ */
+ String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+
+ /**
+ * This feature determines whether the document declaration is processed. If set to false, the DOCDECL event type is
+ * reported by nextToken() and ignored by next(). If this feature is activated, then the document declaration must
+ * be processed by the parser.
+ * <p>
+ * <strong>Please note:</strong> If the document type declaration was ignored, entity references may cause
+ * exceptions later in the parsing process. The default value of this feature is false. It cannot be changed during
+ * parsing.
+ *
+ * @see #getFeature
+ * @see #setFeature
+ */
+ String FEATURE_PROCESS_DOCDECL = "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+
+ /**
+ * If this feature is activated, all validation errors as defined in the XML 1.0 specification are reported. This
+ * implies that FEATURE_PROCESS_DOCDECL is true and both, the internal and external document type declaration will
+ * be processed.
+ * <p>
+ * <strong>Please Note:</strong> This feature can not be changed during parsing. The default value is false.
+ *
+ * @see #getFeature
+ * @see #setFeature
+ */
+ String FEATURE_VALIDATION = "http://xmlpull.org/v1/doc/features.html#validation";
+
+ /**
+ * Use this call to change the general behaviour of the parser, such as namespace processing or doctype declaration
+ * handling. This method must be called before the first call to next or nextToken. Otherwise, an exception is
+ * thrown.
+ * <p>
+ * Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order to switch on namespace processing. The
+ * initial settings correspond to the properties requested from the XML Pull Parser factory. If none were requested,
+ * all features are deactivated by default.
+ *
+ * @exception XmlPullParserException If the feature is not supported or can not be set
+ * @exception IllegalArgumentException If string with the feature name is null
+ */
+ void setFeature( String name, boolean state )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the current value of the given feature.
+ * <p>
+ * <strong>Please note:</strong> unknown features are <strong>always</strong> returned as false.
+ *
+ * @param name The name of feature to be retrieved.
+ * @return The value of the feature.
+ * @exception IllegalArgumentException if string the feature name is null
+ */
+
+ boolean getFeature( String name );
+
+ /**
+ * Set the value of a property. The property name is any fully-qualified URI.
+ *
+ * @exception XmlPullParserException If the property is not supported or can not be set
+ * @exception IllegalArgumentException If string with the property name is null
+ */
+ void setProperty( String name, Object value )
+ throws XmlPullParserException;
+
+ /**
+ * Look up the value of a property. The property name is any fully-qualified URI.
+ * <p>
+ * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null.
+ *
+ * @param name The name of property to be retrieved.
+ * @return The value of named property.
+ */
+ Object getProperty( String name );
+
+ /**
+ * Set the input source for parser to the given reader and resets the parser. The event type is set to the initial
+ * value START_DOCUMENT. Setting the reader to null will just stop parsing and reset parser state, allowing the
+ * parser to free internal resources such as parsing buffers.
+ */
+ void setInput( Reader in )
+ throws XmlPullParserException;
+
+ /**
+ * Sets the input stream the parser is going to process. This call resets the parser state and sets the event type
+ * to the initial value START_DOCUMENT.
+ * <p>
+ * <strong>NOTE:</strong> If an input encoding string is passed, it MUST be used. Otherwise, if inputEncoding is
+ * null, the parser SHOULD try to determine input encoding following XML 1.0 specification (see below). If encoding
+ * detection is supported then following feature <a href=
+ * "http://xmlpull.org/v1/doc/features.html#detect-encoding">http://xmlpull.org/v1/doc/features.html#detect-encoding</a>
+ * MUST be true and otherwise it must be false
+ *
+ * @param inputStream contains a raw byte input stream of possibly unknown encoding (when inputEncoding is null).
+ * @param inputEncoding if not null it MUST be used as encoding for inputStream
+ */
+ void setInput( InputStream inputStream, String inputEncoding )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the input encoding if known, null otherwise. If setInput(InputStream, inputEncoding) was called with an
+ * inputEncoding value other than null, this value must be returned from this method. Otherwise, if inputEncoding is
+ * null and the parser supports the encoding detection feature
+ * (http://xmlpull.org/v1/doc/features.html#detect-encoding), it must return the detected encoding. If
+ * setInput(Reader) was called, null is returned. After first call to next if XML declaration was present this
+ * method will return encoding declared.
+ */
+ String getInputEncoding();
+
+ /**
+ * Set new value for entity replacement text as defined in
+ * <a href="http://www.w3.org/TR/REC-xml#intern-replacement">XML 1.0 Section 4.5 Construction of Internal Entity
+ * Replacement Text</a>. If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this function will result
+ * in an exception -- when processing of DOCDECL is enabled, there is no need to the entity replacement text
+ * manually.
+ * <p>
+ * The motivation for this function is to allow very small implementations of XMLPULL that will work in J2ME
+ * environments. Though these implementations may not be able to process the document type declaration, they still
+ * can work with known DTDs by using this function.
+ * <p>
+ * <b>Please notes:</b> The given value is used literally as replacement text and it corresponds to declaring entity
+ * in DTD that has all special characters escaped: left angle bracket is replaced with &lt;, ampersand with
+ * &amp; and so on.
+ * <p>
+ * <b>Note:</b> The given value is the literal replacement text and must not contain any other entity reference (if
+ * it contains any entity reference there will be no further replacement).
+ * <p>
+ * <b>Note:</b> The list of pre-defined entity names will always contain standard XML entities such as amp
+ * (&amp;), lt (&lt;), gt (&gt;), quot (&quot;), and apos (&apos;). Those cannot be redefined by
+ * this method!
+ *
+ * @see #setInput
+ * @see #FEATURE_PROCESS_DOCDECL
+ * @see #FEATURE_VALIDATION
+ */
+ void defineEntityReplacementText( String entityName, String replacementText )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the numbers of elements in the namespace stack for the given depth. If namespaces are not enabled, 0 is
+ * returned.
+ * <p>
+ * <b>NOTE:</b> when parser is on END_TAG then it is allowed to call this function with getDepth()+1 argument to
+ * retrieve position of namespace prefixes and URIs that were declared on corresponding START_TAG.
+ * <p>
+ * <b>NOTE:</b> to retrieve lsit of namespaces declared in current element:
+ *
+ * <pre>
+ * XmlPullParser pp = ...
+ * int nsStart = pp.getNamespaceCount(pp.getDepth()-1);
+ * int nsEnd = pp.getNamespaceCount(pp.getDepth());
+ * for (int i = nsStart; i > nsEnd; i++) {
+ * String prefix = pp.getNamespacePrefix(i);
+ * String ns = pp.getNamespaceUri(i);
+ * // ...
+ * }
+ * </pre>
+ *
+ * @see #getNamespacePrefix
+ * @see #getNamespaceUri
+ * @see #getNamespace()
+ * @see #getNamespace(String)
+ */
+ int getNamespaceCount( int depth )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the namespace prefix for the given position in the namespace stack. Default namespace declaration
+ * (xmlns='...') will have null as prefix. If the given index is out of range, an exception is thrown.
+ * <p>
+ * <b>Please note:</b> when the parser is on an END_TAG, namespace prefixes that were declared in the corresponding
+ * START_TAG are still accessible although they are no longer in scope.
+ */
+ String getNamespacePrefix( int pos )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the namespace URI for the given position in the namespace stack If the position is out of range, an
+ * exception is thrown.
+ * <p>
+ * <b>NOTE:</b> when parser is on END_TAG then namespace prefixes that were declared in corresponding START_TAG are
+ * still accessible even though they are not in scope
+ */
+ String getNamespaceUri( int pos )
+ throws XmlPullParserException;
+
+ /**
+ * Returns the URI corresponding to the given prefix, depending on current state of the parser.
+ * <p>
+ * If the prefix was not declared in the current scope, null is returned. The default namespace is included in the
+ * namespace table and is available via getNamespace (null).
+ * <p>
+ * This method is a convenience method for
+ *
+ * <pre>
+ * for ( int i = getNamespaceCount( getDepth() ) - 1; i >= 0; i-- )
+ * {
+ * if ( getNamespacePrefix( i ).equals( prefix ) )
+ * {
+ * return getNamespaceUri( i );
+ * }
+ * }
+ * return null;
+ * </pre>
+ * <p>
+ * <strong>Please note:</strong> parser implementations may provide more efficient lookup, e.g. using a Hashtable.
+ * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as defined in the
+ * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> specification. Analogous, the
+ * 'xmlns' prefix is resolved to <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
+ *
+ * @see #getNamespaceCount
+ * @see #getNamespacePrefix
+ * @see #getNamespaceUri
+ */
+ String getNamespace( String prefix );
+
+ // --------------------------------------------------------------------------
+ // miscellaneous reporting methods
+
+ /**
+ * Returns the current depth of the element. Outside the root element, the depth is 0. The depth is incremented by 1
+ * when a start tag is reached. The depth is decremented AFTER the end tag event was observed.
+ *
+ * <pre>
+ * <!-- outside --> 0
+ * <root> 1
+ * sometext 1
+ * <foobar> 2
+ * </foobar> 2
+ * </root> 1
+ * <!-- outside --> 0
+ * </pre>
+ */
+ int getDepth();
+
+ /**
+ * Returns a short text describing the current parser state, including the position, a description of the current
+ * event and the data source if known. This method is especially useful to provide meaningful error messages and for
+ * debugging purposes.
+ */
+ String getPositionDescription();
+
+ /**
+ * Returns the current line number, starting from 1. When the parser does not know the current line number or can
+ * not determine it, -1 is returned (e.g. for WBXML).
+ *
+ * @return current line number or -1 if unknown.
+ */
+ int getLineNumber();
+
+ /**
+ * Returns the current column number, starting from 0. When the parser does not know the current column number or
+ * can not determine it, -1 is returned (e.g. for WBXML).
+ *
+ * @return current column number or -1 if unknown.
+ */
+ int getColumnNumber();
+
+ // --------------------------------------------------------------------------
+ // TEXT related methods
+
+ /**
+ * Checks whether the current TEXT event contains only whitespace characters. For IGNORABLE_WHITESPACE, this is
+ * always true. For TEXT and CDSECT, false is returned when the current event text contains at least one non-white
+ * space character. For any other event type an exception is thrown.
+ * <p>
+ * <b>Please note:</b> non-validating parsers are not able to distinguish whitespace and ignorable whitespace,
+ * except from whitespace outside the root element. Ignorable whitespace is reported as separate event, which is
+ * exposed via nextToken only.
+ */
+ boolean isWhitespace()
+ throws XmlPullParserException;
+
+ /**
+ * Returns the text content of the current event as String. The value returned depends on current event type, for
+ * example for TEXT event it is element content (this is typical case when next() is used). See description of
+ * nextToken() for detailed description of possible returned values for different types of events.
+ * <p>
+ * <strong>NOTE:</strong> in case of ENTITY_REF, this method returns the entity replacement text (or null if not
+ * available). This is the only case where getText() and getTextCharacters() return different values.
+ *
+ * @see #getEventType
+ * @see #next
+ * @see #nextToken
+ */
+ String getText();
+
+ /**
+ * Returns the buffer that contains the text of the current event, as well as the start offset and length relevant
+ * for the current event. See getText(), next() and nextToken() for description of possible returned values.
+ * <p>
+ * <strong>Please note:</strong> this buffer must not be modified and its content MAY change after a call to next()
+ * or nextToken(). This method will always return the same value as getText(), except for ENTITY_REF. In the case of
+ * ENTITY ref, getText() returns the replacement text and this method returns the actual input buffer containing the
+ * entity name. If getText() returns null, this method returns null as well and the values returned in the holder
+ * array MUST be -1 (both start and length).
+ *
+ * @see #getText
+ * @see #next
+ * @see #nextToken
+ * @param holderForStartAndLength Must hold an 2-element int array into which the start offset and length values
+ * will be written.
+ * @return char buffer that contains the text of the current event (null if the current event has no text
+ * associated).
+ */
+ char[] getTextCharacters( int[] holderForStartAndLength );
+
+ // --------------------------------------------------------------------------
+ // START_TAG / END_TAG shared methods
+
+ /**
+ * Returns the namespace URI of the current element. The default namespace is represented as empty string. If
+ * namespaces are not enabled, an empty String ("") is always returned. The current event must be START_TAG or
+ * END_TAG; otherwise, null is returned.
+ */
+ String getNamespace();
+
+ /**
+ * For START_TAG or END_TAG events, the (local) name of the current element is returned when namespaces are enabled.
+ * When namespace processing is disabled, the raw name is returned. For ENTITY_REF events, the entity name is
+ * returned. If the current event is not START_TAG, END_TAG, or ENTITY_REF, null is returned.
+ * <p>
+ * <b>Please note:</b> To reconstruct the raw element name when namespaces are enabled and the prefix is not null,
+ * you will need to add the prefix and a colon to localName..
+ */
+ String getName();
+
+ /**
+ * Returns the prefix of the current element. If the element is in the default namespace (has no prefix), null is
+ * returned. If namespaces are not enabled, or the current event is not START_TAG or END_TAG, null is returned.
+ */
+ String getPrefix();
+
+ /**
+ * Returns true if the current event is START_TAG and the tag is degenerated (e.g. <foobar/>).
+ * <p>
+ * <b>NOTE:</b> if the parser is not on START_TAG, an exception will be thrown.
+ */
+ boolean isEmptyElementTag()
+ throws XmlPullParserException;
+
+ // --------------------------------------------------------------------------
+ // START_TAG Attributes retrieval methods
+
+ /**
+ * Returns the number of attributes of the current start tag, or -1 if the current event type is not START_TAG
+ *
+ * @see #getAttributeNamespace
+ * @see #getAttributeName
+ * @see #getAttributePrefix
+ * @see #getAttributeValue
+ */
+ int getAttributeCount();
+
+ /**
+ * Returns the namespace URI of the attribute with the given index (starts from 0). Returns an empty string ("") if
+ * namespaces are not enabled or the attribute has no namespace. Throws an IndexOutOfBoundsException if the index is
+ * out of range or the current event type is not START_TAG.
+ * <p>
+ * <strong>NOTE:</strong> if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set then namespace attributes (xmlns:ns='...')
+ * must be reported with namespace <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> (visit
+ * this URL for description!). The default namespace attribute (xmlns="...") will be reported with empty namespace.
+ * <p>
+ * <strong>NOTE:</strong>The xml prefix is bound as defined in
+ * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> specification to
+ * "http://www.w3.org/XML/1998/namespace".
+ *
+ * @param index zero based index of attribute
+ * @return attribute namespace, empty string ("") is returned if namespaces processing is not enabled or namespaces
+ * processing is enabled but attribute has no namespace (it has no prefix).
+ */
+ String getAttributeNamespace( int index );
+
+ /**
+ * Returns the local name of the specified attribute if namespaces are enabled or just attribute name if namespaces
+ * are disabled. Throws an IndexOutOfBoundsException if the index is out of range or current event type is not
+ * START_TAG.
+ *
+ * @param index zero based index of attribute
+ * @return attribute name (null is never returned)
+ */
+ String getAttributeName( int index );
+
+ /**
+ * Returns the prefix of the specified attribute Returns null if the element has no prefix. If namespaces are
+ * disabled it will always return null. Throws an IndexOutOfBoundsException if the index is out of range or current
+ * event type is not START_TAG.
+ *
+ * @param index zero based index of attribute
+ * @return attribute prefix or null if namespaces processing is not enabled.
+ */
+ String getAttributePrefix( int index );
+
+ /**
+ * Returns the type of the specified attribute If parser is non-validating it MUST return CDATA.
+ *
+ * @param index zero based index of attribute
+ * @return attribute type (null is never returned)
+ */
+ String getAttributeType( int index );
+
+ /**
+ * Returns if the specified attribute was not in input was declared in XML. If parser is non-validating it MUST
+ * always return false. This information is part of XML infoset:
+ *
+ * @param index zero based index of attribute
+ * @return false if attribute was in input
+ */
+ boolean isAttributeDefault( int index );
+
+ /**
+ * Returns the given attributes value. Throws an IndexOutOfBoundsException if the index is out of range or current
+ * event type is not START_TAG.
+ * <p>
+ * <strong>NOTE:</strong> attribute value must be normalized (including entity replacement text if PROCESS_DOCDECL
+ * is false) as described in <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section 3.3.3
+ * Attribute-Value Normalization</a>
+ *
+ * @see #defineEntityReplacementText
+ * @param index zero based index of attribute
+ * @return value of attribute (null is never returned)
+ */
+ String getAttributeValue( int index );
+
+ /**
+ * Returns the attributes value identified by namespace URI and namespace localName. If namespaces are disabled
+ * namespace must be null. If current event type is not START_TAG then IndexOutOfBoundsException will be thrown.
+ * <p>
+ * <strong>NOTE:</strong> attribute value must be normalized (including entity replacement text if PROCESS_DOCDECL
+ * is false) as described in <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section 3.3.3
+ * Attribute-Value Normalization</a>
+ *
+ * @see #defineEntityReplacementText
+ * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null
+ * @param name If namespaces enabled local name of attribute otherwise just attribute name
+ * @return value of attribute or null if attribute with given name does not exist
+ */
+ String getAttributeValue( String namespace, String name );
+
+ // --------------------------------------------------------------------------
+ // actual parsing methods
+
+ /**
+ * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.)
+ *
+ * @see #next()
+ * @see #nextToken()
+ */
+ int getEventType()
+ throws XmlPullParserException;
+
+ /**
+ * Get next parsing event - element content wil be coalesced and only one TEXT event must be returned for whole
+ * element content (comments and processing instructions will be ignored and entity references must be expanded or
+ * exception mus be thrown if entity reference can not be expanded). If element content is empty (content is "")
+ * then no TEXT event will be reported.
+ * <p>
+ * <b>NOTE:</b> empty element (such as <tag/>) will be reported with two separate events: START_TAG, END_TAG - it
+ * must be so to preserve parsing equivalency of empty element to <tag></tag>. (see isEmptyElementTag ())
+ *
+ * @see #isEmptyElementTag
+ * @see #START_TAG
+ * @see #TEXT
+ * @see #END_TAG
+ * @see #END_DOCUMENT
+ */
+
+ int next()
+ throws XmlPullParserException, IOException;
+
+ /**
+ * This method works similarly to next() but will expose additional event types (COMMENT, CDSECT, DOCDECL,
+ * ENTITY_REF, PROCESSING_INSTRUCTION, or IGNORABLE_WHITESPACE) if they are available in input.
+ * <p>
+ * If special feature <a href="http://xmlpull.org/v1/doc/features.html#xml-roundtrip">FEATURE_XML_ROUNDTRIP</a>
+ * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip) is enabled it is possible to do XML
+ * document round trip ie. reproduce exactly on output the XML input using getText(): returned content is always
+ * unnormalized (exactly as in input). Otherwise returned content is end-of-line normalized as described
+ * <a href="http://www.w3.org/TR/REC-xml#sec-line-ends">XML 1.0 End-of-Line Handling</a> and. Also when this feature
+ * is enabled exact content of START_TAG, END_TAG, DOCDECL and PROCESSING_INSTRUCTION is available.
+ * <p>
+ * Here is the list of tokens that can be returned from nextToken() and what getText() and getTextCharacters()
+ * returns:
+ * <dl>
+ * <dt>START_DOCUMENT
+ * <dd>null
+ * <dt>END_DOCUMENT
+ * <dd>null
+ * <dt>START_TAG
+ * <dd>null unless FEATURE_XML_ROUNDTRIP enabled and then returns XML tag, ex: <tag attr='val'>
+ * <dt>END_TAG
+ * <dd>null unless FEATURE_XML_ROUNDTRIP id enabled and then returns XML tag, ex: </tag>
+ * <dt>TEXT
+ * <dd>return element content. <br>
+ * Note: that element content may be delivered in multiple consecutive TEXT events.
+ * <dt>IGNORABLE_WHITESPACE
+ * <dd>return characters that are determined to be ignorable white space. If the FEATURE_XML_ROUNDTRIP is enabled
+ * all whitespace content outside root element will always reported as IGNORABLE_WHITESPACE otherwise reporting is
+ * optional. <br>
+ * Note: that element content may be delivered in multiple consecutive IGNORABLE_WHITESPACE events.
+ * <dt>CDSECT
+ * <dd>return text <em>inside</em> CDATA (ex. 'fo<o' from <!CDATA[fo<o]]>)
+ * <dt>PROCESSING_INSTRUCTION
+ * <dd>if FEATURE_XML_ROUNDTRIP is true return exact PI content ex: 'pi foo' from <?pi foo?> otherwise it may be
+ * exact PI content or concatenation of PI target, space and data so for example for <?target data?> string
+ * "target data" may be returned if FEATURE_XML_ROUNDTRIP is false.
+ * <dt>COMMENT
+ * <dd>return comment content ex. 'foo bar' from <!--foo bar-->
+ * <dt>ENTITY_REF
+ * <dd>getText() MUST return entity replacement text if PROCESS_DOCDECL is false otherwise getText() MAY return
+ * null, additionally getTextCharacters() MUST return entity name (for example 'entity_name' for &entity_name;).
+ * <br>
+ * <b>NOTE:</b> this is the only place where value returned from getText() and getTextCharacters() <b>are
+ * different</b> <br>
+ * <b>NOTE:</b> it is user responsibility to resolve entity reference if PROCESS_DOCDECL is false and there is no
+ * entity replacement text set in defineEntityReplacementText() method (getText() will be null) <br>
+ * <b>NOTE:</b> character entities (ex. &#32;) and standard entities such as &amp; &lt; &gt;
+ * &quot; &apos; are reported as well and are <b>not</b> reported as TEXT tokens but as ENTITY_REF tokens!
+ * This requirement is added to allow to do roundtrip of XML documents!
+ * <dt>DOCDECL
+ * <dd>if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false then return what is inside of DOCDECL for
+ * example it returns:
+ *
+ * <pre>
+ * " titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+ * [<!ENTITY % active.links "INCLUDE">]"
+ * </pre>
+ * <p>
+ * for input document that contained:
+ *
+ * <pre>
+ * <!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+ * [<!ENTITY % active.links "INCLUDE">]>
+ * </pre>
+ *
+ * otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true then what is returned is undefined (it
+ * may be even null)</dd>
+ * </dl>
+ * <p>
+ * <strong>NOTE:</strong> there is no guarantee that there will only one TEXT or IGNORABLE_WHITESPACE event from
+ * nextToken() as parser may chose to deliver element content in multiple tokens (dividing element content into
+ * chunks)
+ * <p>
+ * <strong>NOTE:</strong> whether returned text of token is end-of-line normalized is depending on
+ * FEATURE_XML_ROUNDTRIP.
+ * <p>
+ * <strong>NOTE:</strong> XMLDecl (<?xml ...?>) is not reported but its content is available through optional
+ * properties (see class description above).
+ *
+ * @see #next
+ * @see #START_TAG
+ * @see #TEXT
+ * @see #END_TAG
+ * @see #END_DOCUMENT
+ * @see #COMMENT
+ * @see #DOCDECL
+ * @see #PROCESSING_INSTRUCTION
+ * @see #ENTITY_REF
+ * @see #IGNORABLE_WHITESPACE
+ */
+ int nextToken()
+ throws XmlPullParserException, IOException;
+
+ // -----------------------------------------------------------------------------
+ // utility methods to mak XML parsing easier ...
+
+ /**
+ * Test if the current event is of the given type and if the namespace and name do match. null will match any
+ * namespace and any name. If the test is not passed, an exception is thrown. The exception text indicates the
+ * parser position, the expected event and the current event that is not meeting the requirement.
+ * <p>
+ * Essentially it does this
+ *
+ * <pre>
+ * if ( type != getEventType() || ( namespace != null && !namespace.equals( getNamespace() ) )
+ * || ( name != null && !name.equals( getName() ) ) )
+ * throw new XmlPullParserException( "expected " + TYPES[type] + getPositionDescription() );
+ * </pre>
+ */
+ void require( int type, String namespace, String name )
+ throws XmlPullParserException, IOException;
+
+ /**
+ * If current event is START_TAG then if next element is TEXT then element content is returned or if next event is
+ * END_TAG then empty string is returned, otherwise exception is thrown. After calling this function successfully
+ * parser will be positioned on END_TAG.
+ * <p>
+ * The motivation for this function is to allow to parse consistently both empty elements and elements that has non
+ * empty content, for example for input:
+ * <ol>
+ * <li><tag>foo</tag>
+ * <li><tag></tag> (which is equivalent to <tag/> both input can be parsed with the same code:
+ *
+ * <pre>
+ * p.nextTag()
+ * p.requireEvent(p.START_TAG, "", "tag");
+ * String content = p.nextText();
+ * p.requireEvent(p.END_TAG, "", "tag");
+ * </pre></li></ol>
+ *
+ * This function together with nextTag make it very easy to parse XML that has no mixed content.
+ * <p>
+ * Essentially it does this
+ *
+ * <pre>
+ * if ( getEventType() != START_TAG )
+ * {
+ * throw new XmlPullParserException( "parser must be on START_TAG to read next text", this, null );
+ * }
+ * int eventType = next();
+ * if ( eventType == TEXT )
+ * {
+ * String result = getText();
+ * eventType = next();
+ * if ( eventType != END_TAG )
+ * {
+ * throw new XmlPullParserException( "event TEXT it must be immediately followed by END_TAG", this, null );
+ * }
+ * return result;
+ * }
+ * else if ( eventType == END_TAG )
+ * {
+ * return "";
+ * }
+ * else
+ * {
+ * throw new XmlPullParserException( "parser must be on START_TAG or TEXT to read text", this, null );
+ * }
+ * </pre>
+ */
+ String nextText()
+ throws XmlPullParserException, IOException;
+
+ /**
+ * Call next() and return event if it is START_TAG or END_TAG otherwise throw an exception. It will skip whitespace
+ * TEXT before actual tag if any.
+ * <p>
+ * essentially it does this
+ *
+ * <pre>
+ * int eventType = next();
+ * if ( eventType == TEXT && isWhitespace() )
+ * { // skip whitespace
+ * eventType = next();
+ * }
+ * if ( eventType != START_TAG && eventType != END_TAG )
+ * {
+ * throw new XmlPullParserException( "expected start or end tag", this, null );
+ * }
+ * return eventType;
+ * </pre>
+ */
+ int nextTag()
+ throws XmlPullParserException, IOException;
+
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java
new file mode 100644
index 0000000..2d9c9d1
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java
@@ -0,0 +1,55 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.apache.camel.xml.io;
+
+/**
+ * This exception is thrown to signal XML Pull Parser related faults.
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+public class XmlPullParserException
+ extends Exception
+{
+ protected int row = -1;
+
+ protected int column = -1;
+
+ public XmlPullParserException( String s )
+ {
+ super( s );
+ }
+
+ /*
+ * public XmlPullParserException(String s, Throwable throwable) { super(s); this.detail = throwable; } public
+ * XmlPullParserException(String s, int row, int column) { super(s); this.row = row; this.column = column; }
+ */
+
+ public XmlPullParserException(String msg, XmlPullParser parser, Throwable cause )
+ {
+ super( ( msg == null ? "" : msg + " " )
+ + ( parser == null ? "" : "(position:" + parser.getPositionDescription() + ") " )
+ + ( cause == null ? "" : "caused by: " + cause ), cause );
+
+ if ( parser != null )
+ {
+ this.row = parser.getLineNumber();
+ this.column = parser.getColumnNumber();
+ }
+ if (cause != null)
+ {
+ initCause(cause);
+ }
+ }
+
+ public int getLineNumber()
+ {
+ return row;
+ }
+
+ public int getColumnNumber()
+ {
+ return column;
+ }
+
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java
new file mode 100644
index 0000000..a3d52a7
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ */
+package org.apache.camel.xml.io;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Character stream that handles (or at least attemtps to) all the necessary Voodo to figure out the
+ * charset encoding of the XML document within the stream.
+ * <p>
+ * IMPORTANT: This class is not related in any way to the org.xml.sax.XMLReader. This one IS a
+ * character stream.
+ * <p>
+ * All this has to be done without consuming characters from the stream, if not the XML parser will
+ * not recognized the document as a valid XML. This is not 100% true, but it's close enough (UTF-8
+ * BOM is not handled by all parsers right now, XmlReader handles it and things work in all
+ * parsers).
+ * <p>
+ * The XmlReader class handles the charset encoding of XML documents in Files, raw streams and HTTP
+ * streams by offering a wide set of constructors.
+ * <P>
+ * By default the charset encoding detection is lenient, the constructor with the lenient flag can
+ * be used for an script (following HTTP MIME and XML specifications). All this is nicely explained
+ * by Mark Pilgrim in his blog, <a
+ * href="https://web.archive.org/web/20060706153721/http://diveintomark.org/archives/2004/02/13/xml-media-types">
+ * Determining the character encoding of a feed</a>.
+ */
+public class XmlStreamReader extends Reader {
+
+ private static final int BUFFER_SIZE = 4096;
+ private static final String US_ASCII = "US-ASCII";
+ private static final String UTF_8 = "UTF-8";
+ private static final String UTF_16BE = "UTF-16BE";
+ private static final String UTF_16LE = "UTF-16LE";
+ private static final String UTF_16 = "UTF-16";
+ private static final String CP1047 = "CP1047";
+ private static final Pattern CHARSET_PATTERN = Pattern.compile("charset=([.[^; ]]*)");
+ private static final Pattern ENCODING_PATTERN = Pattern.compile("<\\?xml.*encoding[\\s]*=[\\s]*((?:\".[^\"]*\")|(?:'.[^']*'))", Pattern.MULTILINE);
+ private static final MessageFormat RAW_EX_1 = new MessageFormat("Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch");
+ private static final MessageFormat RAW_EX_2 = new MessageFormat("Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM");
+ private static final MessageFormat HTTP_EX_1 = new MessageFormat(
+ "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], BOM must be NULL");
+ private static final MessageFormat HTTP_EX_2 = new MessageFormat(
+ "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], encoding mismatch");
+ private static final MessageFormat HTTP_EX_3 = new MessageFormat(
+ "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Invalid MIME");
+
+ private static String staticDefaultEncoding = null;
+
+ private final String defaultEncoding;
+
+ private Reader reader;
+ private String encoding;
+
+ /**
+ * Creates a Reader for a File.
+ * <p>
+ * It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset, if this is also
+ * missing defaults to UTF-8.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param file File to create a Reader from.
+ * @throws IOException thrown if there is a problem reading the file.
+ *
+ */
+ public XmlStreamReader(final File file) throws IOException {
+ this(new FileInputStream(file));
+ }
+
+ /**
+ * Creates a Reader for a raw InputStream.
+ * <p>
+ * It follows the same logic used for files.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param is InputStream to create a Reader from.
+ * @throws IOException thrown if there is a problem reading the stream.
+ *
+ */
+ public XmlStreamReader(final InputStream is) throws IOException {
+ this(is, true);
+ }
+
+ /**
+ * Creates a Reader for a raw InputStream and uses the provided default encoding if none is
+ * determined.
+ * <p>
+ * It follows the same logic used for files.
+ * <p>
+ * If lenient detection is indicated and the detection above fails as per specifications it then
+ * attempts the following:
+ * <p>
+ * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+ * again.
+ * <p>
+ * Else if the XML prolog had a charset encoding that encoding is used.
+ * <p>
+ * Else if the content type had a charset encoding that encoding is used.
+ * <p>
+ * Else 'UTF-8' is used.
+ * <p>
+ * If lenient detection is indicated an XmlStreamReaderException is never thrown.
+ * <p>
+ *
+ * @param is InputStream to create a Reader from.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @param defaultEncoding default encoding to use if one cannot be detected.
+ * @throws IOException thrown if there is a problem reading the stream.
+ * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+ * to the specs.
+ *
+ */
+ public XmlStreamReader(final InputStream is, final boolean lenient, final String defaultEncoding) throws IOException, XmlStreamReaderException {
+ if (defaultEncoding == null) {
+ this.defaultEncoding = staticDefaultEncoding;
+ } else {
+ this.defaultEncoding = defaultEncoding;
+ }
+ try {
+ doRawStream(is, lenient);
+ } catch (final XmlStreamReaderException ex) {
+ if (!lenient) {
+ throw ex;
+ } else {
+ doLenientDetection(null, ex);
+ }
+ }
+ }
+
+ /**
+ * Creates a Reader for a raw InputStream.
+ * <p>
+ * It follows the same logic used for files.
+ * <p>
+ * If lenient detection is indicated and the detection above fails as per specifications it then
+ * attempts the following:
+ * <p>
+ * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+ * again.
+ * <p>
+ * Else if the XML prolog had a charset encoding that encoding is used.
+ * <p>
+ * Else if the content type had a charset encoding that encoding is used.
+ * <p>
+ * Else 'UTF-8' is used.
+ * <p>
+ * If lenient detection is indicated an XmlStreamReaderException is never thrown.
+ * <p>
+ *
+ * @param is InputStream to create a Reader from.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @throws IOException thrown if there is a problem reading the stream.
+ * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+ * to the specs.
+ *
+ */
+ public XmlStreamReader(final InputStream is, final boolean lenient) throws IOException, XmlStreamReaderException {
+ this(is, lenient, null);
+ }
+
+ /**
+ * Creates a Reader using the InputStream of a URL.
+ * <p>
+ * If the URL is not of type HTTP and there is not 'content-type' header in the fetched data it
+ * uses the same logic used for Files.
+ * <p>
+ * If the URL is a HTTP Url or there is a 'content-type' header in the fetched data it uses the
+ * same logic used for an InputStream with content-type.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param url URL to create a Reader from.
+ * @throws IOException thrown if there is a problem reading the stream of the URL.
+ *
+ */
+ public XmlStreamReader(final URL url) throws IOException {
+ this(url, null);
+ }
+
+ /**
+ * Creates a Reader using the InputStream of a URL.
+ * <p>
+ * If the URL is not of type HTTP and there is not 'content-type' header in the fetched data it
+ * uses the same logic used for Files.
+ * <p>
+ * If the URL is a HTTP Url or there is a 'content-type' header in the fetched data it uses the
+ * same logic used for an InputStream with content-type.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param url URL to create a Reader from.
+ * @param requestHeaders optional Map of headers to set on http request.
+ * @throws IOException thrown if there is a problem reading the stream of the URL.
+ *
+ */
+ public XmlStreamReader(final URL url, final Map<String, String> requestHeaders) throws IOException {
+ this(url.openConnection(), requestHeaders);
+ }
+
+ /**
+ * Creates a Reader using the InputStream of a URLConnection.
+ * <p>
+ * If the URLConnection is not of type HttpURLConnection and there is not 'content-type' header
+ * in the fetched data it uses the same logic used for files.
+ * <p>
+ * If the URLConnection is a HTTP Url or there is a 'content-type' header in the fetched data it
+ * uses the same logic used for an InputStream with content-type.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param conn URLConnection to create a Reader from.
+ * @throws IOException thrown if there is a problem reading the stream of the URLConnection.
+ *
+ */
+ public XmlStreamReader(final URLConnection conn) throws IOException {
+ this(conn, null);
+ }
+
+ /**
+ * Creates a Reader using the InputStream of a URLConnection.
+ * <p>
+ * If the URLConnection is not of type HttpURLConnection and there is not 'content-type' header
+ * in the fetched data it uses the same logic used for files.
+ * <p>
+ * If the URLConnection is a HTTP Url or there is a 'content-type' header in the fetched data it
+ * uses the same logic used for an InputStream with content-type.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param conn URLConnection to create a Reader from.
+ * @param requestHeaders optional Map of headers to set on http request.
+ * @throws IOException thrown if there is a problem reading the stream of the URLConnection.
+ *
+ */
+ public XmlStreamReader(final URLConnection conn, final Map<String, String> requestHeaders) throws IOException {
+ defaultEncoding = staticDefaultEncoding;
+ final boolean lenient = true;
+ if (conn instanceof HttpURLConnection) {
+ final Package pckg = this.getClass().getPackage();
+ setRequestHeader(conn, requestHeaders);
+ try {
+ doHttpStream(conn.getInputStream(), conn.getContentType(), lenient);
+ } catch (final XmlStreamReaderException ex) {
+ doLenientDetection(conn.getContentType(), ex);
+ }
+ } else if (conn.getContentType() != null) {
+ try {
+ doHttpStream(conn.getInputStream(), conn.getContentType(), lenient);
+ } catch (final XmlStreamReaderException ex) {
+ doLenientDetection(conn.getContentType(), ex);
+ }
+ } else {
+ try {
+ doRawStream(conn.getInputStream(), lenient);
+ } catch (final XmlStreamReaderException ex) {
+ doLenientDetection(null, ex);
+ }
+ }
+ }
+
+ /**
+ * Creates a Reader using an InputStream and the associated content-type header.
+ * <p>
+ * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+ * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+ * prolog encoding uses the default encoding mandated by the content-type MIME type.
+ * <p>
+ * It does a lenient charset encoding detection, check the constructor with the lenient
+ * parameter for details.
+ * <p>
+ *
+ * @param is InputStream to create the reader from.
+ * @param httpContentType content-type header to use for the resolution of the charset encoding.
+ * @throws IOException thrown if there is a problem reading the file.
+ *
+ */
+ public XmlStreamReader(final InputStream is, final String httpContentType) throws IOException {
+ this(is, httpContentType, true);
+ }
+
+ /**
+ * Creates a Reader using an InputStream and the associated content-type header.
+ * <p>
+ * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+ * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+ * prolog encoding uses the default encoding mandated by the content-type MIME type.
+ * <p>
+ * If lenient detection is indicated and the detection above fails as per specifications it then
+ * attempts the following:
+ * <p>
+ * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+ * again.
+ * <p>
+ * Else if the XML prolog had a charset encoding that encoding is used.
+ * <p>
+ * Else if the content type had a charset encoding that encoding is used.
+ * <p>
+ * Else 'UTF-8' is used.
+ * <p>
+ * If lenient detection is indicated and XmlStreamReaderException is never thrown.
+ * <p>
+ *
+ * @param is InputStream to create the reader from.
+ * @param httpContentType content-type header to use for the resolution of the charset encoding.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @param defaultEncoding default encoding to use if one cannot be detected.
+ * @throws IOException thrown if there is a problem reading the file.
+ * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+ * to the specs.
+ *
+ */
+ public XmlStreamReader(final InputStream is, final String httpContentType, final boolean lenient, final String defaultEncoding) throws IOException,
+ XmlStreamReaderException {
+ if (defaultEncoding == null) {
+ this.defaultEncoding = staticDefaultEncoding;
+ } else {
+ this.defaultEncoding = defaultEncoding;
+ }
+ try {
+ doHttpStream(is, httpContentType, lenient);
+ } catch (final XmlStreamReaderException ex) {
+ if (!lenient) {
+ throw ex;
+ } else {
+ doLenientDetection(httpContentType, ex);
+ }
+ }
+ }
+
+ /**
+ * Creates a Reader using an InputStream and the associated content-type header.
+ * <p>
+ * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+ * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+ * prolog encoding uses the default encoding mandated by the content-type MIME type.
+ * <p>
+ * If lenient detection is indicated and the detection above fails as per specifications it then
+ * attempts the following:
+ * <p>
+ * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+ * again.
+ * <p>
+ * Else if the XML prolog had a charset encoding that encoding is used.
+ * <p>
+ * Else if the content type had a charset encoding that encoding is used.
+ * <p>
+ * Else 'UTF-8' is used.
+ * <p>
+ * If lenient detection is indicated and XmlStreamReaderException is never thrown.
+ * <p>
+ *
+ * @param is InputStream to create the reader from.
+ * @param httpContentType content-type header to use for the resolution of the charset encoding.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @throws IOException thrown if there is a problem reading the file.
+ * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+ * to the specs.
+ *
+ */
+ public XmlStreamReader(final InputStream is, final String httpContentType, final boolean lenient) throws IOException, XmlStreamReaderException {
+ this(is, httpContentType, lenient, null);
+ }
+
+ /**
+ * Returns the default encoding to use if none is set in HTTP content-type, XML prolog and the
+ * rules based on content-type are not adequate.
+ * <p/>
+ * If it is NULL the content-type based rules are used.
+ * <p/>
+ *
+ * @return the default encoding to use.
+ */
+ public static String getDefaultEncoding() {
+ return staticDefaultEncoding;
+ }
+
+ /**
+ * Sets the default encoding to use if none is set in HTTP content-type, XML prolog and the
+ * rules based on content-type are not adequate.
+ * <p/>
+ * If it is set to NULL the content-type based rules are used.
+ * <p/>
+ * By default it is NULL.
+ * <p/>
+ *
+ * @param encoding charset encoding to default to.
+ */
+ public static void setDefaultEncoding(final String encoding) {
+ staticDefaultEncoding = encoding;
+ }
+
+ /**
+ * Returns the charset encoding of the XmlReader.
+ * <p>
+ *
+ * @return charset encoding.
+ *
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ private void doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException {
+ if (httpContentType != null) {
+ if (httpContentType.startsWith("text/html")) {
+ httpContentType = httpContentType.substring("text/html".length());
+ httpContentType = "text/xml" + httpContentType;
+ try {
+ doHttpStream(ex.getInputStream(), httpContentType, true);
+ ex = null;
+ } catch (final XmlStreamReaderException ex2) {
+ ex = ex2;
+ }
+ }
+ }
+ if (ex != null) {
+ String encoding = ex.getXmlEncoding();
+ if (encoding == null) {
+ encoding = ex.getContentTypeEncoding();
+ }
+ if (encoding == null) {
+ if (defaultEncoding == null) {
+ encoding = UTF_8;
+ } else {
+ encoding = defaultEncoding;
+ }
+ }
+ prepareReader(ex.getInputStream(), encoding);
+ }
+ }
+
+ @Override
+ public int read(final char[] buf, final int offset, final int len) throws IOException {
+ return reader.read(buf, offset, len);
+ }
+
+ /**
+ * Closes the XmlReader stream.
+ * <p>
+ *
+ * @throws IOException thrown if there was a problem closing the stream.
+ *
+ */
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+
+ private void doRawStream(final InputStream is, final boolean lenient) throws IOException {
+ final BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
+ final String bomEnc = getBOMEncoding(pis);
+ final String xmlGuessEnc = getXMLGuessEncoding(pis);
+ final String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
+ final String encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, pis);
+ prepareReader(pis, encoding);
+ }
+
+ private void doHttpStream(final InputStream is, final String httpContentType, final boolean lenient) throws IOException {
+ final BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
+ final String cTMime = getContentTypeMime(httpContentType);
+ final String cTEnc = getContentTypeEncoding(httpContentType);
+ final String bomEnc = getBOMEncoding(pis);
+ final String xmlGuessEnc = getXMLGuessEncoding(pis);
+ final String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
+ final String encoding = calculateHttpEncoding(cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, pis, lenient);
+ prepareReader(pis, encoding);
+ }
+
+ private void prepareReader(final InputStream is, final String encoding) throws IOException {
+ reader = new InputStreamReader(is, encoding);
+ this.encoding = encoding;
+ }
+
+ // InputStream is passed for XmlStreamReaderException creation only
+ private String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) throws IOException {
+ String encoding;
+ if (bomEnc == null) {
+ if (xmlGuessEnc == null || xmlEnc == null) {
+ if (defaultEncoding == null) {
+ encoding = UTF_8;
+ } else {
+ encoding = defaultEncoding;
+ }
+ } else if (xmlEnc.equals(UTF_16) && (xmlGuessEnc.equals(UTF_16BE) || xmlGuessEnc.equals(UTF_16LE))) {
+ encoding = xmlGuessEnc;
+ } else {
+ encoding = xmlEnc;
+ }
+ } else if (bomEnc.equals(UTF_8)) {
+ if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) {
+ throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+ }
+ if (xmlEnc != null && !xmlEnc.equals(UTF_8)) {
+ throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+ }
+ encoding = UTF_8;
+ } else if (bomEnc.equals(UTF_16BE) || bomEnc.equals(UTF_16LE)) {
+ if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) {
+ throw new IOException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }));
+ }
+ if (xmlEnc != null && !xmlEnc.equals(UTF_16) && !xmlEnc.equals(bomEnc)) {
+ throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+ }
+ encoding = bomEnc;
+ } else {
+ throw new XmlStreamReaderException(RAW_EX_2.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+ }
+ return encoding;
+ }
+
+ private void setRequestHeader(final URLConnection conn, final Map<String, String> requestHeaders) {
+ final Package pckg = this.getClass().getPackage();
+ if (pckg.getImplementationTitle() != null && pckg.getImplementationVersion() != null) {
+ conn.setRequestProperty("User-Agent", pckg.getImplementationTitle() + "/" + pckg.getImplementationVersion());
+ } else {
+ conn.setRequestProperty("User-Agent", "ROME");
+ }
+ if (requestHeaders != null) {
+ for (final Entry<String, String> requestHeader : requestHeaders.entrySet()) {
+ conn.setRequestProperty(requestHeader.getKey(), requestHeader.getValue());
+ }
+ }
+ }
+
+ // InputStream is passed for XmlStreamReaderException creation only
+ private String calculateHttpEncoding(final String cTMime, final String cTEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc,
+ final InputStream is, final boolean lenient) throws IOException {
+ String encoding;
+ if (lenient && xmlEnc != null) {
+ encoding = xmlEnc;
+ } else {
+ final boolean appXml = isAppXml(cTMime);
+ final boolean textXml = isTextXml(cTMime);
+ if (appXml || textXml) {
+ if (cTEnc == null) {
+ if (appXml) {
+ encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, is);
+ } else {
+ if (defaultEncoding == null) {
+ encoding = US_ASCII;
+ } else {
+ encoding = defaultEncoding;
+ }
+ }
+ } else if (bomEnc != null && (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE))) {
+ throw new XmlStreamReaderException(HTTP_EX_1.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc,
+ xmlGuessEnc, xmlEnc, is);
+ } else if (cTEnc.equals(UTF_16)) {
+ if (bomEnc != null && bomEnc.startsWith(UTF_16)) {
+ encoding = bomEnc;
+ } else {
+ throw new XmlStreamReaderException(HTTP_EX_2.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc,
+ xmlGuessEnc, xmlEnc, is);
+ }
+ } else {
+ encoding = cTEnc;
+ }
+ } else {
+ throw new XmlStreamReaderException(HTTP_EX_3.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc,
+ xmlEnc, is);
+ }
+ }
+ return encoding;
+ }
+
+ // returns MIME type or NULL if httpContentType is NULL
+ private static String getContentTypeMime(final String httpContentType) {
+ String mime = null;
+ if (httpContentType != null) {
+ final int i = httpContentType.indexOf(";");
+ if (i == -1) {
+ mime = httpContentType.trim();
+ } else {
+ mime = httpContentType.substring(0, i).trim();
+ }
+ }
+ return mime;
+ }
+
+ // returns charset parameter value, NULL if not present, NULL if
+ // httpContentType is NULL
+ private static String getContentTypeEncoding(final String httpContentType) {
+ String encoding = null;
+ if (httpContentType != null) {
+ final int i = httpContentType.indexOf(";");
+ if (i > -1) {
+ final String postMime = httpContentType.substring(i + 1);
+ final Matcher m = CHARSET_PATTERN.matcher(postMime);
+ if (m.find()) {
+ encoding = m.group(1);
+ }
+ if (encoding != null) {
+ encoding = encoding.toUpperCase(Locale.ENGLISH);
+ }
+ }
+ if (encoding != null && (encoding.startsWith("\"") && encoding.endsWith("\"") || encoding.startsWith("'") && encoding.endsWith("'"))) {
+ encoding = encoding.substring(1, encoding.length() - 1);
+ }
+ }
+ return encoding;
+ }
+
+ // returns the BOM in the stream, NULL if not present,
+ // if there was BOM the in the stream it is consumed
+ private static String getBOMEncoding(final BufferedInputStream is) throws IOException {
+ String encoding = null;
+ final int[] bytes = new int[3];
+ is.mark(3);
+ bytes[0] = is.read();
+ bytes[1] = is.read();
+ bytes[2] = is.read();
+
+ if (bytes[0] == 0xFE && bytes[1] == 0xFF) {
+ encoding = UTF_16BE;
+ is.reset();
+ is.read();
+ is.read();
+ } else if (bytes[0] == 0xFF && bytes[1] == 0xFE) {
+ encoding = UTF_16LE;
+ is.reset();
+ is.read();
+ is.read();
+ } else if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
+ encoding = UTF_8;
+ } else {
+ is.reset();
+ }
+ return encoding;
+ }
+
+ // returns the best guess for the encoding by looking the first bytes of the
+ // stream, '<?xm'
+ private static String getXMLGuessEncoding(final BufferedInputStream is) throws IOException {
+ String encoding = null;
+ final int[] bytes = new int[4];
+ is.mark(4);
+ bytes[0] = is.read();
+ bytes[1] = is.read();
+ bytes[2] = is.read();
+ bytes[3] = is.read();
+ is.reset();
+
+ if (bytes[0] == 0x00 && bytes[1] == 0x3C && bytes[2] == 0x00 && bytes[3] == 0x3F) {
+ encoding = UTF_16BE;
+ } else if (bytes[0] == 0x3C && bytes[1] == 0x00 && bytes[2] == 0x3F && bytes[3] == 0x00) {
+ encoding = UTF_16LE;
+ } else if (bytes[0] == 0x3C && bytes[1] == 0x3F && bytes[2] == 0x78 && bytes[3] == 0x6D) {
+ encoding = UTF_8;
+ } else if (bytes[0] == 0x4C && bytes[1] == 0x6F && bytes[2] == 0xA7 && bytes[3] == 0x94) {
+ encoding = CP1047;
+ }
+ return encoding;
+ }
+
+ // returns the encoding declared in the <?xml encoding=...?>, NULL if none
+ static String getXmlProlog(final InputStream is, final String guessedEnc) throws IOException {
+ String encoding = null;
+ if (guessedEnc != null) {
+ final byte[] bytes = new byte[BUFFER_SIZE];
+ is.mark(BUFFER_SIZE);
+ int offset = 0;
+ int max = BUFFER_SIZE;
+ int c = is.read(bytes, offset, max);
+ int firstGT = -1;
+ while (c != -1 && firstGT == -1 && offset < BUFFER_SIZE) {
+ offset += c;
+ max -= c;
+ c = is.read(bytes, offset, max);
+ firstGT = new String(bytes, 0, offset, guessedEnc).indexOf(">");
+ }
+ if (firstGT == -1) {
+ if (c == -1) {
+ throw new IOException("Unexpected end of XML stream");
+ } else {
+ throw new IOException("XML prolog or ROOT element not found on first " + offset + " bytes");
+ }
+ }
+ final int bytesRead = offset;
+ if (bytesRead > 0) {
+ is.reset();
+ String prolog = new String(bytes, guessedEnc).substring(0, firstGT);
+ final Matcher m = ENCODING_PATTERN.matcher(prolog);
+ if (m.find()) {
+ encoding = m.group(1).toUpperCase(Locale.ENGLISH);
+ encoding = encoding.substring(1, encoding.length() - 1);
+ }
+ }
+ }
+ return encoding;
+ }
+
+ // indicates if the MIME type belongs to the APPLICATION XML family
+ private static boolean isAppXml(final String mime) {
+ return mime != null
+ && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime.equals("application/xml-external-parsed-entity") || mime
+ .startsWith("application/") && mime.endsWith("+xml"));
+ }
+
+ // indicates if the MIME type belongs to the TEXT XML family
+ private static boolean isTextXml(final String mime) {
+ return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime.startsWith("text/") && mime.endsWith("+xml"));
+ }
+
+}
\ No newline at end of file
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java
new file mode 100644
index 0000000..97d798c
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ */
+package org.apache.camel.xml.io;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * The XmlReaderException is thrown by the XmlReader constructors if the charset encoding can not be
+ * determined according to the XML 1.0 specification and RFC 3023.
+ * <p>
+ * The exception returns the unconsumed InputStream to allow the application to do an alternate
+ * processing with the stream. Note that the original InputStream given to the XmlReader cannot be
+ * used as that one has been already read.
+ */
+public class XmlStreamReaderException extends IOException {
+ private static final long serialVersionUID = 1L;
+ private final String bomEncoding;
+ private final String xmlGuessEncoding;
+ private final String xmlEncoding;
+ private final String contentTypeMime;
+ private final String contentTypeEncoding;
+ private final InputStream is;
+
+ /**
+ * Creates an exception instance if the charset encoding could not be determined.
+ * <p>
+ * Instances of this exception are thrown by the XmlReader.
+ * <p>
+ *
+ * @param msg message describing the reason for the exception.
+ * @param bomEnc BOM encoding.
+ * @param xmlGuessEnc XML guess encoding.
+ * @param xmlEnc XML prolog encoding.
+ * @param is the unconsumed InputStream.
+ *
+ */
+ public XmlStreamReaderException(final String msg, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) {
+ this(msg, null, null, bomEnc, xmlGuessEnc, xmlEnc, is);
+ }
+
+ /**
+ * Creates an exception instance if the charset encoding could not be determined.
+ * <p>
+ * Instances of this exception are thrown by the XmlReader.
+ * <p>
+ *
+ * @param msg message describing the reason for the exception.
+ * @param ctMime MIME type in the content-type.
+ * @param ctEnc encoding in the content-type.
+ * @param bomEnc BOM encoding.
+ * @param xmlGuessEnc XML guess encoding.
+ * @param xmlEnc XML prolog encoding.
+ * @param is the unconsumed InputStream.
+ *
+ */
+ public XmlStreamReaderException(final String msg, final String ctMime, final String ctEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc,
+ final InputStream is) {
+ super(msg);
+ contentTypeMime = ctMime;
+ contentTypeEncoding = ctEnc;
+ bomEncoding = bomEnc;
+ xmlGuessEncoding = xmlGuessEnc;
+ xmlEncoding = xmlEnc;
+ this.is = is;
+ }
+
+ /**
+ * Returns the BOM encoding found in the InputStream.
+ * <p>
+ *
+ * @return the BOM encoding, null if none.
+ *
+ */
+ public String getBomEncoding() {
+ return bomEncoding;
+ }
+
+ /**
+ * Returns the encoding guess based on the first bytes of the InputStream.
+ * <p>
+ *
+ * @return the encoding guess, null if it couldn't be guessed.
+ *
+ */
+ public String getXmlGuessEncoding() {
+ return xmlGuessEncoding;
+ }
+
+ /**
+ * Returns the encoding found in the XML prolog of the InputStream.
+ * <p>
+ *
+ * @return the encoding of the XML prolog, null if none.
+ *
+ */
+ public String getXmlEncoding() {
+ return xmlEncoding;
+ }
+
+ /**
+ * Returns the MIME type in the content-type used to attempt determining the encoding.
+ * <p>
+ *
+ * @return the MIME type in the content-type, null if there was not content-type or the encoding
+ * detection did not involve HTTP.
+ *
+ */
+ public String getContentTypeMime() {
+ return contentTypeMime;
+ }
+
+ /**
+ * Returns the encoding in the content-type used to attempt determining the encoding.
+ * <p>
+ *
+ * @return the encoding in the content-type, null if there was not content-type, no encoding in
+ * it or the encoding detection did not involve HTTP.
+ *
+ */
+ public String getContentTypeEncoding() {
+ return contentTypeEncoding;
+ }
+
+ /**
+ * Returns the unconsumed InputStream to allow the application to do an alternate encoding
+ * detection on the InputStream.
+ * <p>
+ *
+ * @return the unconsumed InputStream.
+ *
+ */
+ public InputStream getInputStream() {
+ return is;
+ }
+}
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
new file mode 100644
index 0000000..c90a932
--- /dev/null
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.xml.in;
+
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+public class ModelParserTest {
+
+ public static final String NAMESPACE = "http://camel.apache.org/schema/spring";
+ private static List<String> REST_XMLS = Arrays.asList("barRest.xml", "simpleRest.xml", "simpleRestToD.xml");
+
+ @Test
+ public void testFiles() throws Exception {
+ Path dir = getResourceFolder();
+ List<Path> files = Files.list(dir).sorted().filter(Files::isRegularFile).collect(Collectors.toList());
+ for (Path path : files) {
+ ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE);
+ boolean isRest = REST_XMLS.contains(path.getFileName().toString());
+ if (isRest) {
+ RestsDefinition rests = parser.parseRestsDefinition();
+ assertNotNull(rests);
+ } else {
+ RoutesDefinition routes = parser.parseRoutesDefinition();
+ assertNotNull(routes);
+ }
+ }
+ }
+
+ @Test
+ public void testSimpleString() throws Exception {
+ RoutesDefinition routes = new ModelParser(new StringReader(
+ "<routes>" +
+ "<route id='foo'>" +
+ "<from uri='my:bar'/>" +
+ "<to uri='mock:res'/>" +
+ "</route>" +
+ "</routes>"
+ )).parseRoutesDefinition();
+ assertNotNull(routes);
+ }
+
+ private Path getResourceFolder() {
+ String url = getClass().getClassLoader().getResource("barInterceptorRoute.xml").toString();
+ if (url.startsWith("file:")) {
+ url = url.substring("file:".length(), url.indexOf("barInterceptorRoute.xml"));
+ } else if (url.startsWith("jar:file:")) {
+ url = url.substring("jar:file:".length(), url.indexOf("!"));
+ }
+ return Paths.get(url);
+ }
+}
diff --git a/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml b/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml
new file mode 100644
index 0000000..c7dbf76
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml
@@ -0,0 +1,31 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+ <route id="bar">
+ <from uri="direct:bar"/>
+ <intercept>
+ <to uri="log:intercept"/>
+ <to uri="mock:intercept"/>
+ </intercept>
+ <to uri="mock:bar"/>
+ </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml b/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml
new file mode 100644
index 0000000..7eda513
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml
@@ -0,0 +1,37 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+ <route id="bar">
+ <from uri="direct:bar"/>
+ <onException>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to uri="log:error"/>
+ <to uri="mock:error"/>
+ </onException>
+ <process ref="myProcessor"/>
+ <to uri="log:bar"/>
+ <to uri="mock:bar"/>
+ </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barPolicyRoute.xml b/core/camel-xml-io/src/test/resources/barPolicyRoute.xml
new file mode 100644
index 0000000..f7ce1ad
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barPolicyRoute.xml
@@ -0,0 +1,37 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+ <route id="foo">
+ <from uri="direct:start"/>
+ <policy ref="foo">
+ <to uri="mock:foo"/>
+ <to uri="mock:bar"/>
+ <to uri="mock:result"/>
+ </policy>
+ </route>
+
+ <route id="bar">
+ <from uri="direct:send"/>
+ <to uri="direct:start"/>
+ <to uri="mock:response"/>
+ </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barRest.xml b/core/camel-xml-io/src/test/resources/barRest.xml
new file mode 100644
index 0000000..dc50305
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barRest.xml
@@ -0,0 +1,26 @@
+<?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.
+
+-->
+<rests xmlns="http://camel.apache.org/schema/spring">
+ <rest id="bar" path="/say/hello">
+ <get uri="/bar">
+ <to uri="mock:bar"/>
+ </get>
+ </rest>
+</rests>
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/barRoute.xml b/core/camel-xml-io/src/test/resources/barRoute.xml
new file mode 100644
index 0000000..e96c1f2
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barRoute.xml
@@ -0,0 +1,31 @@
+<?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.
+
+-->
+<!-- START SNIPPET: e1 -->
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <!-- here we define the bar route -->
+ <route id="bar">
+ <from uri="direct:bar"/>
+ <to uri="mock:bar"/>
+ </route>
+
+ <!-- we could add more routes if we like,
+ but in this example we stick to one route only -->
+</routes>
+<!-- END SNIPPET: e1 -->
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml b/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml
new file mode 100644
index 0000000..e7ce805
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml
@@ -0,0 +1,34 @@
+<?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.
+
+-->
+<!-- START SNIPPET: e1 -->
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <!-- here we define the bar route -->
+ <route id="bar">
+ <from uri="direct:bar"/>
+ <transform>
+ <simple>Bye ${body}</simple>
+ </transform>
+ <to uri="mock:bar"/>
+ </route>
+
+ <!-- we could add more routes if we like,
+ but in this example we stick to one route only -->
+</routes>
+<!-- END SNIPPET: e1 -->
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/convertBody.xml b/core/camel-xml-io/src/test/resources/convertBody.xml
new file mode 100644
index 0000000..7b66154
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/convertBody.xml
@@ -0,0 +1,25 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <convertBodyTo type="java.lang.Integer"/>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml b/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml
new file mode 100644
index 0000000..d924ded
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml
@@ -0,0 +1,27 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <recipientList>
+ <header>foo</header>
+ </recipientList>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/loop.xml b/core/camel-xml-io/src/test/resources/loop.xml
new file mode 100644
index 0000000..9aa9214
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/loop.xml
@@ -0,0 +1,27 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:a"/>
+ <loop>
+ <constant>8</constant>
+ </loop>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processor.xml b/core/camel-xml-io/src/test/resources/processor.xml
new file mode 100644
index 0000000..07b319a
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processor.xml
@@ -0,0 +1,25 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <process ref="myProcessor"/>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithFilter.xml b/core/camel-xml-io/src/test/resources/processorWithFilter.xml
new file mode 100644
index 0000000..975a53d
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithFilter.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <filter>
+ <language language="juel">in.header.foo == 'bar'</language>
+ <process ref="myProcessor"/>
+ </filter>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml b/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml
new file mode 100644
index 0000000..7edf514
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <filter>
+ <groovy>in.headers.any { h -> h.startsWith('foo')}</groovy>
+ <process ref="myProcessor"/>
+ </filter>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml b/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml
new file mode 100644
index 0000000..89d6540
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <filter>
+ <header>foo</header>
+ <process ref="myProcessor"/>
+ </filter>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml b/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml
new file mode 100644
index 0000000..e5d5884
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <filter>
+ <simple>${in.header.foo} == 'bar'</simple>
+ <process ref="myProcessor"/>
+ </filter>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/resequencerBatch.xml b/core/camel-xml-io/src/test/resources/resequencerBatch.xml
new file mode 100644
index 0000000..69e42fe
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/resequencerBatch.xml
@@ -0,0 +1,32 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start" />
+ <resequence>
+ <!--
+ batch-config can be ommitted for default resequence settings
+ -->
+ <batch-config batchTimeout="2000" batchSize="500"/>
+ <simple>body</simple>
+ <to uri="mock:result" />
+ </resequence>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/resequencerStream.xml b/core/camel-xml-io/src/test/resources/resequencerStream.xml
new file mode 100644
index 0000000..b9b4594
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/resequencerStream.xml
@@ -0,0 +1,29 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start" />
+ <resequence>
+ <stream-config timeout="2000"/> <!-- Use default capacity -->
+ <simple>in.header.seqnum</simple>
+ <to uri="mock:result" />
+ </resequence>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeGroup.xml b/core/camel-xml-io/src/test/resources/routeGroup.xml
new file mode 100644
index 0000000..7548f8c
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeGroup.xml
@@ -0,0 +1,31 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <!--
+ xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"
+ -->
+
+ <route id="route-id" group="route-group">
+ <from uri="seda:a"/>
+ <to uri="seda:b"/>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeProperties.xml b/core/camel-xml-io/src/test/resources/routeProperties.xml
new file mode 100644
index 0000000..b425f6c
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeProperties.xml
@@ -0,0 +1,34 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <!--
+ xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"
+ -->
+
+ <route id="route-id">
+ <routeProperty key="key1" value="val1"/>
+ <routeProperty key="key2" value="val2"/>
+
+ <from uri="seda:a"/>
+ <to uri="seda:b"/>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml
new file mode 100644
index 0000000..6aea276
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <bindy type="Csv" classType="org.apache.camel.MyFoo"/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithChoice.xml b/core/camel-xml-io/src/test/resources/routeWithChoice.xml
new file mode 100644
index 0000000..c74bcc7
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithChoice.xml
@@ -0,0 +1,37 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <choice>
+ <when>
+ <simple>${header.foo} == 'bar'</simple>
+ <to uri="seda:b"/>
+ </when>
+ <when>
+ <ognl>header[foo] == 'cheese'</ognl>
+ <to uri="seda:c"/>
+ </when>
+ <otherwise>
+ <to uri="seda:d"/>
+ </otherwise>
+ </choice>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml
new file mode 100644
index 0000000..3c75b19
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml
@@ -0,0 +1,33 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start"/>
+ <loadBalance>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Forced"/>
+ <onFallback>
+ <transform>
+ <constant>Fallback message</constant>
+ </transform>
+ </onFallback>
+ <to uri="mock:result"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml
new file mode 100644
index 0000000..3e94bc1
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <csv/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml
new file mode 100644
index 0000000..0df7b27
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml
@@ -0,0 +1,33 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <loadBalance>
+ <failover>
+ <exception>java.io.IOException</exception>
+ <exception>java.text.ParseException</exception>
+ </failover>
+ <to uri="seda:b"/>
+ <to uri="seda:c"/>
+ <to uri="seda:d"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml
new file mode 100644
index 0000000..db33188
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <flatpack/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml
new file mode 100644
index 0000000..1ee6503
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <hl7/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml
new file mode 100644
index 0000000..c8db92d
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <json library="Jackson"/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml
new file mode 100644
index 0000000..4bc91e9
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <jaxb contextPath="org.apache.camel.model"/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml
new file mode 100644
index 0000000..5eab226
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <loadBalance>
+ <roundRobin/>
+ <to uri="seda:b"/>
+ <to uri="seda:c"/>
+ <to uri="seda:d"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithNamespace.xml b/core/camel-xml-io/src/test/resources/routeWithNamespace.xml
new file mode 100644
index 0000000..664e326
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithNamespace.xml
@@ -0,0 +1,34 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring" xmlns:foo="http://foo">
+ <route id="routeWithNamespace">
+ <from uri="direct:foo" />
+ <choice>
+ <when>
+ <xpath>/foo:foo/foo:bar = 'cheese'</xpath>
+ <setBody>
+ <constant>Hello from foo</constant>
+ </setBody>
+ <to uri="mock:bar"/>
+ </when>
+ </choice>
+ <to uri="log:end"/>
+ </route>
+</routes>
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml
new file mode 100644
index 0000000..bbb79c0
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <rss/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml
new file mode 100644
index 0000000..de26430
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <loadBalance>
+ <random/>
+ <to uri="seda:b"/>
+ <to uri="seda:c"/>
+ <to uri="seda:d"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml
new file mode 100644
index 0000000..f8b0e79
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml
@@ -0,0 +1,34 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <loadBalance>
+ <sticky>
+ <correlationExpression>
+ <language language="juel">in.header.foo == 'bar'</language>
+ </correlationExpression>
+ </sticky>
+ <to uri="seda:b"/>
+ <to uri="seda:c"/>
+ <to uri="seda:d"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml
new file mode 100644
index 0000000..f3939e5
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <unmarshal>
+ <tidyMarkup/>
+ </unmarshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml
new file mode 100644
index 0000000..5ade532
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <loadBalance>
+ <topic/>
+ <to uri="seda:b"/>
+ <to uri="seda:c"/>
+ <to uri="seda:d"/>
+ </loadBalance>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml
new file mode 100644
index 0000000..7ee7d50
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml
@@ -0,0 +1,30 @@
+<?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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="seda:a"/>
+ <pipeline>
+ <marshal>
+ <secureXML/>
+ </marshal>
+ <to uri="seda:b"/>
+ </pipeline>
+ </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithXStreamDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithXStreamDataFormat.xml
... 1358 lines suppressed ...