You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/04/14 10:52:55 UTC
[1/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Repository: camel
Updated Branches:
refs/heads/master d72696455 -> 6b42a3534
Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/6b42a353
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/6b42a353
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/6b42a353
Branch: refs/heads/master
Commit: 6b42a3534120f58180e6194e6bf4f1a284707abc
Parents: c66be7a
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Apr 14 12:17:14 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Apr 14 12:52:40 2017 +0200
----------------------------------------------------------------------
platforms/camel-catalog/pom.xml | 40 ++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/6b42a353/platforms/camel-catalog/pom.xml
----------------------------------------------------------------------
diff --git a/platforms/camel-catalog/pom.xml b/platforms/camel-catalog/pom.xml
index 2be82e0..6c71fcb 100644
--- a/platforms/camel-catalog/pom.xml
+++ b/platforms/camel-catalog/pom.xml
@@ -92,7 +92,7 @@
<executions>
<execution>
<id>copy-resources</id>
- <phase>process-sources</phase>
+ <phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
@@ -101,7 +101,7 @@
<overwrite>true</overwrite>
<resources>
<resource>
- <directory>../../camel-core/src/main/java/org/apache/camel/catalog</directory>
+ <directory>../../camel-core/src/main/java/org/apache/camel/runtimecatalog</directory>
<!-- the following files are maintained in camel-core and not here, so they are copied over -->
<includes>
<include>AbstractCamelCatalog.java</include>
@@ -123,6 +123,42 @@
</execution>
</executions>
</plugin>
+ <!-- rename runtimecatalog to catalog which is the package name we use here -->
+ <plugin>
+ <groupId>com.google.code.maven-replacer-plugin</groupId>
+ <artifactId>replacer</artifactId>
+ <version>1.5.3</version>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>replace</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <includes>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/CatalogHelper.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/TimePatternConverter.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java</include>
+ <include>${basedir}/src/main/java/org/apache/camel/catalog/URISupport.java</include>
+ </includes>
+ <replacements>
+ <replacement>
+ <token>org.apache.camel.runtimecatalog</token>
+ <value>org.apache.camel.catalog</value>
+ </replacement>
+ </replacements>
+ </configuration>
+ </plugin>
<!-- generate and include all components in the catalog -->
<plugin>
[3/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
new file mode 100644
index 0000000..1e69269
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaHelper.java
@@ -0,0 +1,424 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class JSonSchemaHelper {
+
+ // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number
+ private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
+ private static final String QUOT = """;
+
+ private JSonSchemaHelper() {
+ }
+
+ /**
+ * Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
+ *
+ * @param group the group to parse from such as <tt>component</tt>, <tt>componentProperties</tt>, or <tt>properties</tt>.
+ * @param json the json
+ * @return a list of all the rows, where each row is a set of key value pairs with metadata
+ */
+ public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
+ List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
+ if (json == null) {
+ return answer;
+ }
+
+ boolean found = false;
+
+ // parse line by line
+ String[] lines = json.split("\n");
+ for (String line : lines) {
+ // we need to find the group first
+ if (!found) {
+ String s = line.trim();
+ found = s.startsWith("\"" + group + "\":") && s.endsWith("{");
+ continue;
+ }
+
+ // we should stop when we end the group
+ if (line.equals(" },") || line.equals(" }")) {
+ break;
+ }
+
+ // need to safe encode \" so we can parse the line
+ line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');
+
+ Map<String, String> row = new LinkedHashMap<String, String>();
+ Matcher matcher = PATTERN.matcher(line);
+
+ String key;
+ if (parseProperties) {
+ // when parsing properties the first key is given as name, so the first parsed token is the value of the name
+ key = "name";
+ } else {
+ key = null;
+ }
+ while (matcher.find()) {
+ if (key == null) {
+ key = matcher.group(1);
+ } else {
+ String value = matcher.group(1);
+ if (value != null) {
+ // its text based
+ value = value.trim();
+ // decode
+ value = value.replaceAll(QUOT, "\"");
+ value = decodeJson(value);
+ }
+ if (value == null) {
+ // not text then its maybe an enum?
+ value = matcher.group(2);
+ if (value != null) {
+ // its an enum so strip out " and trim spaces after comma
+ value = value.replaceAll("\"", "");
+ value = value.replaceAll(", ", ",");
+ value = value.trim();
+ }
+ }
+ if (value == null) {
+ // not text then its maybe a boolean?
+ value = matcher.group(3);
+ }
+ if (value == null) {
+ // not text then its maybe a integer?
+ value = matcher.group(4);
+ }
+ if (value != null) {
+ row.put(key, value);
+ }
+ // reset
+ key = null;
+ }
+ }
+ if (!row.isEmpty()) {
+ answer.add(row);
+ }
+ }
+
+ return answer;
+ }
+
+ private static String decodeJson(String value) {
+ // json encodes a \ as \\ so we need to decode from \\ back to \
+ if ("\\\\".equals(value)) {
+ value = "\\";
+ }
+ return value;
+ }
+
+ public static boolean isComponentLenientProperties(List<Map<String, String>> rows) {
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("lenientProperties")) {
+ return "true".equals(row.get("lenientProperties"));
+ }
+ }
+ return false;
+ }
+
+ public static boolean isComponentConsumerOnly(List<Map<String, String>> rows) {
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("consumerOnly")) {
+ return "true".equals(row.get("consumerOnly"));
+ }
+ }
+ return false;
+ }
+
+ public static boolean isComponentProducerOnly(List<Map<String, String>> rows) {
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("producerOnly")) {
+ return "true".equals(row.get("producerOnly"));
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyConsumerOnly(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String labels = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("label")) {
+ labels = row.get("label");
+ }
+ if (found) {
+ return labels != null && labels.contains("consumer");
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyProducerOnly(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String labels = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("label")) {
+ labels = row.get("label");
+ }
+ if (found) {
+ return labels != null && labels.contains("producer");
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyRequired(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ boolean required = false;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("required")) {
+ required = "true".equals(row.get("required"));
+ }
+ if (found) {
+ return required;
+ }
+ }
+ return false;
+ }
+
+ public static String getPropertyKind(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String kind = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("kind")) {
+ kind = row.get("kind");
+ }
+ if (found) {
+ return kind;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isPropertyBoolean(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String type = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("type")) {
+ type = row.get("type");
+ }
+ if (found) {
+ return "boolean".equals(type);
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyInteger(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String type = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("type")) {
+ type = row.get("type");
+ }
+ if (found) {
+ return "integer".equals(type);
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyNumber(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String type = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("type")) {
+ type = row.get("type");
+ }
+ if (found) {
+ return "number".equals(type);
+ }
+ }
+ return false;
+ }
+
+ public static boolean isPropertyObject(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String type = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("type")) {
+ type = row.get("type");
+ }
+ if (found) {
+ return "object".equals(type);
+ }
+ }
+ return false;
+ }
+
+ public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String defaultValue = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("defaultValue")) {
+ defaultValue = row.get("defaultValue");
+ }
+ if (found) {
+ return defaultValue;
+ }
+ }
+ return null;
+ }
+
+ public static String stripOptionalPrefixFromName(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String optionalPrefix = null;
+ boolean found = false;
+ if (row.containsKey("optionalPrefix")) {
+ optionalPrefix = row.get("optionalPrefix");
+ }
+ if (row.containsKey("name")) {
+ if (optionalPrefix != null && name.startsWith(optionalPrefix)) {
+ name = name.substring(optionalPrefix.length());
+ // try again
+ return stripOptionalPrefixFromName(rows, name);
+ } else {
+ found = name.equals(row.get("name"));
+ }
+ }
+ if (found) {
+ return name;
+ }
+ }
+ return name;
+ }
+
+ public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String enums = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("enum")) {
+ enums = row.get("enum");
+ }
+ if (found) {
+ return enums;
+ }
+ }
+ return null;
+ }
+
+ public static String getPropertyPrefix(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String prefix = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("prefix")) {
+ prefix = row.get("prefix");
+ }
+ if (found) {
+ return prefix;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isPropertyMultiValue(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ boolean multiValue = false;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ found = name.equals(row.get("name"));
+ }
+ if (row.containsKey("multiValue")) {
+ multiValue = "true".equals(row.get("multiValue"));
+ }
+ if (found) {
+ return multiValue;
+ }
+ }
+ return false;
+ }
+
+ public static String getPropertyNameFromNameWithPrefix(List<Map<String, String>> rows, String name) {
+ for (Map<String, String> row : rows) {
+ String propertyName = null;
+ boolean found = false;
+ if (row.containsKey("name")) {
+ propertyName = row.get("name");
+ }
+ if (row.containsKey("prefix")) {
+ String preifx = row.get("prefix");
+ found = name.startsWith(preifx);
+ }
+ if (found) {
+ return propertyName;
+ }
+ }
+ return null;
+ }
+
+ public static Map<String, String> getRow(List<Map<String, String>> rows, String key) {
+ for (Map<String, String> row : rows) {
+ if (key.equals(row.get("name"))) {
+ return row;
+ }
+ }
+ return null;
+ }
+
+ public static Set<String> getNames(List<Map<String, String>> rows) {
+ Set<String> answer = new LinkedHashSet<String>();
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("name")) {
+ answer.add(row.get("name"));
+ }
+ }
+ return answer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
new file mode 100644
index 0000000..dbd6f45
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/JSonSchemaResolver.java
@@ -0,0 +1,64 @@
+/**
+ * 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.runtimecatalog;
+
+/**
+ * Pluggable resolver to load JSon schema files for components, data formats, languages etc.
+ */
+public interface JSonSchemaResolver {
+
+ /**
+ * Returns the component information as JSon format.
+ *
+ * @param name the component name
+ * @return component details in JSon
+ */
+ String getComponentJSonSchema(String name);
+
+ /**
+ * Returns the data format information as JSon format.
+ *
+ * @param name the data format name
+ * @return data format details in JSon
+ */
+ String getDataFormatJSonSchema(String name);
+
+ /**
+ * Returns the language information as JSon format.
+ *
+ * @param name the language name
+ * @return language details in JSon
+ */
+ String getLanguageJSonSchema(String name);
+
+ /**
+ * Returns the other (miscellaneous) information as JSon format.
+ *
+ * @param name the other (miscellaneous) name
+ * @return other (miscellaneous) details in JSon
+ */
+ String getOtherJSonSchema(String name);
+
+ /**
+ * Returns the model information as JSon format.
+ *
+ * @param name the model name
+ * @return model details in JSon
+ */
+ String getModelJSonSchema(String name);
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
new file mode 100644
index 0000000..dbb5525
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/LanguageValidationResult.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.runtimecatalog;
+
+import java.io.Serializable;
+
+/**
+ * Validation result of parsing a language expression or predicate
+ */
+public class LanguageValidationResult implements Serializable {
+ private final String text;
+ private String error;
+ private String shortError;
+ private int index;
+
+ public LanguageValidationResult(String text) {
+ this.text = text;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public boolean isSuccess() {
+ return error == null;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public String getShortError() {
+ return shortError;
+ }
+
+ public void setShortError(String shortError) {
+ this.shortError = shortError;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
new file mode 100644
index 0000000..86c4b53
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalog.java
@@ -0,0 +1,234 @@
+/**
+ * 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.runtimecatalog;
+
+import java.net.URISyntaxException;
+import java.util.Map;
+
+import org.apache.camel.StaticService;
+
+/**
+ * Runtime based CamelCatalog which are included in camel-core that can provided limit CamelCatalog capabilities
+ */
+public interface RuntimeCamelCatalog extends StaticService {
+
+ /**
+ * Returns the component information as JSon format.
+ *
+ * @param name the component name
+ * @return component details in JSon
+ */
+ String componentJSonSchema(String name);
+
+ /**
+ * Returns the data format information as JSon format.
+ *
+ * @param name the data format name
+ * @return data format details in JSon
+ */
+ String dataFormatJSonSchema(String name);
+
+ /**
+ * Returns the language information as JSon format.
+ *
+ * @param name the language name
+ * @return language details in JSon
+ */
+ String languageJSonSchema(String name);
+
+ /**
+ * Returns the model information as JSon format.
+ *
+ * @param name the model name
+ * @return model details in JSon
+ */
+ String modelJSonSchema(String name);
+
+ /**
+ * Parses the endpoint uri and constructs a key/value properties of each option
+ *
+ * @param uri the endpoint uri
+ * @return properties as key value pairs of each endpoint option
+ */
+ Map<String, String> endpointProperties(String uri) throws URISyntaxException;
+
+ /**
+ * Parses the endpoint uri and constructs a key/value properties of only the lenient properties (eg custom options)
+ * <p/>
+ * For example using the HTTP components to provide query parameters in the endpoint uri.
+ *
+ * @param uri the endpoint uri
+ * @return properties as key value pairs of each lenient properties
+ */
+ Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException;
+
+ /**
+ * Validates the pattern whether its a valid time pattern.
+ *
+ * @param pattern the pattern such as 5000, 5s, 5sec, 4min, 4m30s, 1h, etc.
+ * @return <tt>true</tt> if valid, <tt>false</tt> if invalid
+ */
+ boolean validateTimePattern(String pattern);
+
+ /**
+ * Validates the properties for the given scheme against component and endpoint
+ *
+ * @param scheme the endpoint scheme
+ * @param properties the endpoint properties
+ * @return validation result
+ */
+ EndpointValidationResult validateProperties(String scheme, Map<String, String> properties);
+
+ /**
+ * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+ *
+ * @param uri the endpoint uri
+ * @return validation result
+ */
+ EndpointValidationResult validateEndpointProperties(String uri);
+
+ /**
+ * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+ * <p/>
+ * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
+ * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
+ * but in the uri because of using lenient properties.
+ * For example using the HTTP components to provide query parameters in the endpoint uri.
+ *
+ * @param uri the endpoint uri
+ * @param ignoreLenientProperties whether to ignore components that uses lenient properties.
+ * @return validation result
+ */
+ EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties);
+
+ /**
+ * Parses and validates the endpoint uri and constructs a key/value properties of each option.
+ * <p/>
+ * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
+ * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
+ * but in the uri because of using lenient properties.
+ * For example using the HTTP components to provide query parameters in the endpoint uri.
+ *
+ * @param uri the endpoint uri
+ * @param ignoreLenientProperties whether to ignore components that uses lenient properties.
+ * @param consumerOnly whether the endpoint is only used as a consumer
+ * @param producerOnly whether the endpoint is only used as a producer
+ * @return validation result
+ */
+ EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly);
+
+ /**
+ * Parses and validates the simple expression.
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+ *
+ * @param simple the simple expression
+ * @return validation result
+ * @deprecated use {@link #validateSimpleExpression(ClassLoader, String)}
+ */
+ @Deprecated
+ SimpleValidationResult validateSimpleExpression(String simple);
+
+ /**
+ * Parses and validates the simple expression.
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+ *
+ * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+ * @param simple the simple expression
+ * @return validation result
+ */
+ SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple);
+
+ /**
+ * Parses and validates the simple predicate
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+ *
+ * @param simple the simple predicate
+ * @return validation result
+ * @deprecated use {@link #validateSimplePredicate(ClassLoader, String)}
+ */
+ @Deprecated
+ SimpleValidationResult validateSimplePredicate(String simple);
+
+ /**
+ * Parses and validates the simple predicate
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
+ *
+ * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+ * @param simple the simple predicate
+ * @return validation result
+ */
+ SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple);
+
+ /**
+ * Parses and validates the language as a predicate
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
+ *
+ * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+ * @param language the name of the language
+ * @param text the predicate text
+ * @return validation result
+ */
+ LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text);
+
+ /**
+ * Parses and validates the language as an expression
+ * <p/>
+ * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
+ *
+ * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
+ * @param language the name of the language
+ * @param text the expression text
+ * @return validation result
+ */
+ LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
+
+ /**
+ * Returns the component name from the given endpoint uri
+ *
+ * @param uri the endpoint uri
+ * @return the component name (aka scheme), or <tt>null</tt> if not possible to determine
+ */
+ String endpointComponentName(String uri);
+
+ /**
+ * Creates an endpoint uri in Java style from the information from the properties
+ *
+ * @param scheme the endpoint schema
+ * @param properties the properties as key value pairs
+ * @param encode whether to URL encode the returned uri or not
+ * @return the constructed endpoint uri
+ * @throws java.net.URISyntaxException is thrown if there is encoding error
+ */
+ String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
+
+ /**
+ * Creates an endpoint uri in XML style (eg escape & as &l;) from the information from the properties
+ *
+ * @param scheme the endpoint schema
+ * @param properties the properties as key value pairs
+ * @param encode whether to URL encode the returned uri or not
+ * @return the constructed endpoint uri
+ * @throws java.net.URISyntaxException is thrown if there is encoding error
+ */
+ String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
new file mode 100644
index 0000000..1b8dd0e
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SimpleValidationResult.java
@@ -0,0 +1,32 @@
+/**
+ * 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.runtimecatalog;
+
+/**
+ * To be backwards compatible, but favor using {@link LanguageValidationResult} instead.
+ */
+public class SimpleValidationResult extends LanguageValidationResult {
+
+ public SimpleValidationResult(String text) {
+ super(text);
+ }
+
+ public String getSimple() {
+ return getText();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
new file mode 100644
index 0000000..e29afc6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/SuggestionStrategy.java
@@ -0,0 +1,34 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.Set;
+
+/**
+ * Strategy to provide suggestions for unknown endpoint options
+ */
+public interface SuggestionStrategy {
+
+ /**
+ * Provides a list of valid option names for a did you mean function.
+ *
+ * @param names valid names
+ * @param unknownOption unknown option name
+ * @return a list of suggested names (did you mean)
+ */
+ String[] suggestEndpointOptions(Set<String> names, String unknownOption);
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
new file mode 100644
index 0000000..ed5585c
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/TimePatternConverter.java
@@ -0,0 +1,120 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is a copy from camel-core so we can use it independent to validate uris with time patterns
+ */
+public final class TimePatternConverter {
+ private static final Pattern NUMBERS_ONLY_STRING_PATTERN = Pattern.compile("^[-]?(\\d)+$", Pattern.CASE_INSENSITIVE);
+ private static final Pattern HOUR_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))h(our(s)?)?", Pattern.CASE_INSENSITIVE);
+ private static final Pattern MINUTES_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))m(in(ute(s)?)?)?", Pattern.CASE_INSENSITIVE);
+ private static final Pattern SECONDS_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))s(ec(ond)?(s)?)?", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Utility classes should not have a public constructor.
+ */
+ private TimePatternConverter() {
+ }
+
+ public static long toMilliSeconds(String source) throws IllegalArgumentException {
+ long milliseconds = 0;
+ boolean foundFlag = false;
+
+ checkCorrectnessOfPattern(source);
+ Matcher matcher;
+
+ matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
+ if (matcher.find()) {
+ // Note: This will also be used for regular numeric strings.
+ // This String -> long converter will be used for all strings.
+ milliseconds = Long.valueOf(source);
+ } else {
+ matcher = createMatcher(HOUR_REGEX_PATTERN, source);
+ if (matcher.find()) {
+ milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)));
+ foundFlag = true;
+ }
+
+ matcher = createMatcher(MINUTES_REGEX_PATTERN, source);
+ if (matcher.find()) {
+ long minutes = Long.valueOf(matcher.group(1));
+ if ((minutes > 59) && foundFlag) {
+ throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
+ }
+ foundFlag = true;
+ milliseconds = milliseconds + (60000 * minutes);
+ }
+
+ matcher = createMatcher(SECONDS_REGEX_PATTERN, source);
+ if (matcher.find()) {
+ long seconds = Long.valueOf(matcher.group(1));
+ if ((seconds > 59) && foundFlag) {
+ throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
+ }
+ foundFlag = true;
+ milliseconds = milliseconds + (1000 * seconds);
+ }
+
+ // No pattern matched... initiating fallback check and conversion (if required).
+ // The source at this point may contain illegal values or special characters
+ if (!foundFlag) {
+ milliseconds = Long.valueOf(source);
+ }
+ }
+
+ return milliseconds;
+ }
+
+ private static void checkCorrectnessOfPattern(String source) {
+ //replace only numbers once
+ Matcher matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
+ String replaceSource = matcher.replaceFirst("");
+
+ //replace hour string once
+ matcher = createMatcher(HOUR_REGEX_PATTERN, replaceSource);
+ if (matcher.find() && matcher.find()) {
+ throw new IllegalArgumentException("Hours should not be specified more then once: " + source);
+ }
+ replaceSource = matcher.replaceFirst("");
+
+ //replace minutes once
+ matcher = createMatcher(MINUTES_REGEX_PATTERN, replaceSource);
+ if (matcher.find() && matcher.find()) {
+ throw new IllegalArgumentException("Minutes should not be specified more then once: " + source);
+ }
+ replaceSource = matcher.replaceFirst("");
+
+ //replace seconds once
+ matcher = createMatcher(SECONDS_REGEX_PATTERN, replaceSource);
+ if (matcher.find() && matcher.find()) {
+ throw new IllegalArgumentException("Seconds should not be specified more then once: " + source);
+ }
+ replaceSource = matcher.replaceFirst("");
+
+ if (replaceSource.length() > 0) {
+ throw new IllegalArgumentException("Illegal characters: " + source);
+ }
+ }
+
+ private static Matcher createMatcher(Pattern pattern, String source) {
+ return pattern.matcher(source);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
new file mode 100644
index 0000000..8389590
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/URISupport.java
@@ -0,0 +1,392 @@
+/**
+ * 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.runtimecatalog;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Copied from org.apache.camel.util.URISupport
+ */
+public final class URISupport {
+
+ public static final String RAW_TOKEN_START = "RAW(";
+ public static final String RAW_TOKEN_END = ")";
+
+ private static final String CHARSET = "UTF-8";
+
+ private URISupport() {
+ // Helper class
+ }
+
+ /**
+ * Normalizes the URI so unsafe characters is encoded
+ *
+ * @param uri the input uri
+ * @return as URI instance
+ * @throws URISyntaxException is thrown if syntax error in the input uri
+ */
+ public static URI normalizeUri(String uri) throws URISyntaxException {
+ return new URI(UnsafeUriCharactersEncoder.encode(uri, true));
+ }
+
+ public static Map<String, Object> extractProperties(Map<String, Object> properties, String optionPrefix) {
+ Map<String, Object> rc = new LinkedHashMap<String, Object>(properties.size());
+
+ for (Iterator<Map.Entry<String, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
+ Map.Entry<String, Object> entry = it.next();
+ String name = entry.getKey();
+ if (name.startsWith(optionPrefix)) {
+ Object value = properties.get(name);
+ name = name.substring(optionPrefix.length());
+ rc.put(name, value);
+ it.remove();
+ }
+ }
+
+ return rc;
+ }
+
+ /**
+ * Strips the query parameters from the uri
+ *
+ * @param uri the uri
+ * @return the uri without the query parameter
+ */
+ public static String stripQuery(String uri) {
+ int idx = uri.indexOf('?');
+ if (idx > -1) {
+ uri = uri.substring(0, idx);
+ }
+ return uri;
+ }
+
+ /**
+ * Parses the query parameters of the uri (eg the query part).
+ *
+ * @param uri the uri
+ * @return the parameters, or an empty map if no parameters (eg never null)
+ * @throws URISyntaxException is thrown if uri has invalid syntax.
+ */
+ public static Map<String, Object> parseParameters(URI uri) throws URISyntaxException {
+ String query = uri.getQuery();
+ if (query == null) {
+ String schemeSpecificPart = uri.getSchemeSpecificPart();
+ int idx = schemeSpecificPart.indexOf('?');
+ if (idx < 0) {
+ // return an empty map
+ return new LinkedHashMap<String, Object>(0);
+ } else {
+ query = schemeSpecificPart.substring(idx + 1);
+ }
+ } else {
+ query = stripPrefix(query, "?");
+ }
+ return parseQuery(query);
+ }
+
+ /**
+ * Strips the prefix from the value.
+ * <p/>
+ * Returns the value as-is if not starting with the prefix.
+ *
+ * @param value the value
+ * @param prefix the prefix to remove from value
+ * @return the value without the prefix
+ */
+ public static String stripPrefix(String value, String prefix) {
+ if (value != null && value.startsWith(prefix)) {
+ return value.substring(prefix.length());
+ }
+ return value;
+ }
+
+ /**
+ * Parses the query part of the uri (eg the parameters).
+ * <p/>
+ * The URI parameters will by default be URI encoded. However you can define a parameter
+ * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
+ * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
+ *
+ * @param uri the uri
+ * @return the parameters, or an empty map if no parameters (eg never null)
+ * @throws URISyntaxException is thrown if uri has invalid syntax.
+ * @see #RAW_TOKEN_START
+ * @see #RAW_TOKEN_END
+ */
+ public static Map<String, Object> parseQuery(String uri) throws URISyntaxException {
+ return parseQuery(uri, false);
+ }
+
+ /**
+ * Parses the query part of the uri (eg the parameters).
+ * <p/>
+ * The URI parameters will by default be URI encoded. However you can define a parameter
+ * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
+ * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
+ *
+ * @param uri the uri
+ * @param useRaw whether to force using raw values
+ * @return the parameters, or an empty map if no parameters (eg never null)
+ * @throws URISyntaxException is thrown if uri has invalid syntax.
+ * @see #RAW_TOKEN_START
+ * @see #RAW_TOKEN_END
+ */
+ public static Map<String, Object> parseQuery(String uri, boolean useRaw) throws URISyntaxException {
+ // must check for trailing & as the uri.split("&") will ignore those
+ if (uri != null && uri.endsWith("&")) {
+ throw new URISyntaxException(uri, "Invalid uri syntax: Trailing & marker found. "
+ + "Check the uri and remove the trailing & marker.");
+ }
+
+ if (isEmpty(uri)) {
+ // return an empty map
+ return new LinkedHashMap<String, Object>(0);
+ }
+
+ // need to parse the uri query parameters manually as we cannot rely on splitting by &,
+ // as & can be used in a parameter value as well.
+
+ try {
+ // use a linked map so the parameters is in the same order
+ Map<String, Object> rc = new LinkedHashMap<String, Object>();
+
+ boolean isKey = true;
+ boolean isValue = false;
+ boolean isRaw = false;
+ StringBuilder key = new StringBuilder();
+ StringBuilder value = new StringBuilder();
+
+ // parse the uri parameters char by char
+ for (int i = 0; i < uri.length(); i++) {
+ // current char
+ char ch = uri.charAt(i);
+ // look ahead of the next char
+ char next;
+ if (i <= uri.length() - 2) {
+ next = uri.charAt(i + 1);
+ } else {
+ next = '\u0000';
+ }
+
+ // are we a raw value
+ isRaw = value.toString().startsWith(RAW_TOKEN_START);
+
+ // if we are in raw mode, then we keep adding until we hit the end marker
+ if (isRaw) {
+ if (isKey) {
+ key.append(ch);
+ } else if (isValue) {
+ value.append(ch);
+ }
+
+ // we only end the raw marker if its )& or at the end of the value
+
+ boolean end = ch == RAW_TOKEN_END.charAt(0) && (next == '&' || next == '\u0000');
+ if (end) {
+ // raw value end, so add that as a parameter, and reset flags
+ addParameter(key.toString(), value.toString(), rc, useRaw || isRaw);
+ key.setLength(0);
+ value.setLength(0);
+ isKey = true;
+ isValue = false;
+ isRaw = false;
+ // skip to next as we are in raw mode and have already added the value
+ i++;
+ }
+ continue;
+ }
+
+ // if its a key and there is a = sign then the key ends and we are in value mode
+ if (isKey && ch == '=') {
+ isKey = false;
+ isValue = true;
+ isRaw = false;
+ continue;
+ }
+
+ // the & denote parameter is ended
+ if (ch == '&') {
+ // parameter is ended, as we hit & separator
+ String aKey = key.toString();
+ // the key may be a placeholder of options which we then do not know what is
+ boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
+ if (validKey) {
+ addParameter(aKey, value.toString(), rc, useRaw || isRaw);
+ }
+ key.setLength(0);
+ value.setLength(0);
+ isKey = true;
+ isValue = false;
+ isRaw = false;
+ continue;
+ }
+
+ // regular char so add it to the key or value
+ if (isKey) {
+ key.append(ch);
+ } else if (isValue) {
+ value.append(ch);
+ }
+ }
+
+ // any left over parameters, then add that
+ if (key.length() > 0) {
+ String aKey = key.toString();
+ // the key may be a placeholder of options which we then do not know what is
+ boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
+ if (validKey) {
+ addParameter(aKey, value.toString(), rc, useRaw || isRaw);
+ }
+ }
+
+ return rc;
+
+ } catch (UnsupportedEncodingException e) {
+ URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
+ se.initCause(e);
+ throw se;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void addParameter(String name, String value, Map<String, Object> map, boolean isRaw) throws UnsupportedEncodingException {
+ name = URLDecoder.decode(name, CHARSET);
+ if (!isRaw) {
+ // need to replace % with %25
+ value = URLDecoder.decode(value.replaceAll("%", "%25"), CHARSET);
+ }
+
+ // does the key already exist?
+ if (map.containsKey(name)) {
+ // yes it does, so make sure we can support multiple values, but using a list
+ // to hold the multiple values
+ Object existing = map.get(name);
+ List<String> list;
+ if (existing instanceof List) {
+ list = (List<String>) existing;
+ } else {
+ // create a new list to hold the multiple values
+ list = new ArrayList<String>();
+ String s = existing != null ? existing.toString() : null;
+ if (s != null) {
+ list.add(s);
+ }
+ }
+ list.add(value);
+ map.put(name, list);
+ } else {
+ map.put(name, value);
+ }
+ }
+
+ /**
+ * Assembles a query from the given map.
+ *
+ * @param options the map with the options (eg key/value pairs)
+ * @param ampersand to use & for Java code, and & for XML
+ * @return a query string with <tt>key1=value&key2=value2&...</tt>, or an empty string if there is no options.
+ * @throws URISyntaxException is thrown if uri has invalid syntax.
+ */
+ public static String createQueryString(Map<String, String> options, String ampersand, boolean encode) throws URISyntaxException {
+ try {
+ if (options.size() > 0) {
+ StringBuilder rc = new StringBuilder();
+ boolean first = true;
+ for (Object o : options.keySet()) {
+ if (first) {
+ first = false;
+ } else {
+ rc.append(ampersand);
+ }
+
+ String key = (String) o;
+ Object value = options.get(key);
+
+ // use the value as a String
+ String s = value != null ? value.toString() : null;
+ appendQueryStringParameter(key, s, rc, encode);
+ }
+ return rc.toString();
+ } else {
+ return "";
+ }
+ } catch (UnsupportedEncodingException e) {
+ URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
+ se.initCause(e);
+ throw se;
+ }
+ }
+
+ private static void appendQueryStringParameter(String key, String value, StringBuilder rc, boolean encode) throws UnsupportedEncodingException {
+ if (encode) {
+ rc.append(URLEncoder.encode(key, CHARSET));
+ } else {
+ rc.append(key);
+ }
+ // only append if value is not null
+ if (value != null) {
+ rc.append("=");
+ if (value.startsWith(RAW_TOKEN_START) && value.endsWith(RAW_TOKEN_END)) {
+ // do not encode RAW parameters
+ rc.append(value);
+ } else {
+ if (encode) {
+ rc.append(URLEncoder.encode(value, CHARSET));
+ } else {
+ rc.append(value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests whether the value is <tt>null</tt> or an empty string.
+ *
+ * @param value the value, if its a String it will be tested for text length as well
+ * @return true if empty
+ */
+ public static boolean isEmpty(Object value) {
+ return !isNotEmpty(value);
+ }
+
+ /**
+ * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
+ *
+ * @param value the value, if its a String it will be tested for text length as well
+ * @return true if <b>not</b> empty
+ */
+ public static boolean isNotEmpty(Object value) {
+ if (value == null) {
+ return false;
+ } else if (value instanceof String) {
+ String text = (String) value;
+ return text.trim().length() > 0;
+ } else {
+ return true;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
new file mode 100644
index 0000000..a11c810
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/UnsafeUriCharactersEncoder.java
@@ -0,0 +1,206 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Encoder for unsafe URI characters.
+ * <p/>
+ * A good source for details is <a href="http://en.wikipedia.org/wiki/Url_encode">wikipedia url encode</a> article.
+ */
+public final class UnsafeUriCharactersEncoder {
+ private static BitSet unsafeCharactersRfc1738;
+ private static BitSet unsafeCharactersHttp;
+ private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
+ 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'};
+ private static final Pattern RAW_PATTERN = Pattern.compile("RAW\\([^\\)]+\\)");
+
+ static {
+ unsafeCharactersRfc1738 = new BitSet(256);
+ unsafeCharactersRfc1738.set(' ');
+ unsafeCharactersRfc1738.set('"');
+ unsafeCharactersRfc1738.set('<');
+ unsafeCharactersRfc1738.set('>');
+ unsafeCharactersRfc1738.set('#');
+ unsafeCharactersRfc1738.set('%');
+ unsafeCharactersRfc1738.set('{');
+ unsafeCharactersRfc1738.set('}');
+ unsafeCharactersRfc1738.set('|');
+ unsafeCharactersRfc1738.set('\\');
+ unsafeCharactersRfc1738.set('^');
+ unsafeCharactersRfc1738.set('~');
+ unsafeCharactersRfc1738.set('[');
+ unsafeCharactersRfc1738.set(']');
+ unsafeCharactersRfc1738.set('`');
+ }
+
+ static {
+ unsafeCharactersHttp = new BitSet(256);
+ unsafeCharactersHttp.set(' ');
+ unsafeCharactersHttp.set('"');
+ unsafeCharactersHttp.set('<');
+ unsafeCharactersHttp.set('>');
+ unsafeCharactersHttp.set('#');
+ unsafeCharactersHttp.set('%');
+ unsafeCharactersHttp.set('{');
+ unsafeCharactersHttp.set('}');
+ unsafeCharactersHttp.set('|');
+ unsafeCharactersHttp.set('\\');
+ unsafeCharactersHttp.set('^');
+ unsafeCharactersHttp.set('~');
+ unsafeCharactersHttp.set('`');
+ }
+
+ private UnsafeUriCharactersEncoder() {
+ // util class
+ }
+
+ public static String encode(String s) {
+ return encode(s, unsafeCharactersRfc1738);
+ }
+
+ public static String encodeHttpURI(String s) {
+ return encode(s, unsafeCharactersHttp);
+ }
+
+ public static String encode(String s, BitSet unsafeCharacters) {
+ return encode(s, unsafeCharacters, false);
+ }
+
+ public static String encode(String s, boolean checkRaw) {
+ return encode(s, unsafeCharactersRfc1738, checkRaw);
+ }
+
+ public static String encodeHttpURI(String s, boolean checkRaw) {
+ return encode(s, unsafeCharactersHttp, checkRaw);
+ }
+
+ private static List<Pair> checkRAW(String s) {
+ Matcher matcher = RAW_PATTERN.matcher(s);
+ List<Pair> answer = new ArrayList<Pair>();
+ // Check all occurrences
+ while (matcher.find()) {
+ answer.add(new Pair(matcher.start(), matcher.end()));
+ }
+ return answer;
+ }
+
+ private static boolean isRaw(int index, List<Pair> pairs) {
+ for (Pair pair : pairs) {
+ if (index < pair.left) {
+ return false;
+ } else {
+ if (index >= pair.left) {
+ if (index <= pair.right) {
+ return true;
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static class Pair {
+ int left;
+ int right;
+
+ Pair(int left, int right) {
+ this.left = left;
+ this.right = right;
+ }
+ }
+
+ // Just skip the encode for isRAW part
+ public static String encode(String s, BitSet unsafeCharacters, boolean checkRaw) {
+ List<Pair> rawPairs;
+ if (checkRaw) {
+ rawPairs = checkRAW(s);
+ } else {
+ rawPairs = new ArrayList<Pair>();
+ }
+
+ int n = s == null ? 0 : s.length();
+ if (n == 0) {
+ return s;
+ }
+
+ // First check whether we actually need to encode
+ char chars[] = s.toCharArray();
+ for (int i = 0;;) {
+ // just deal with the ascii character
+ if (chars[i] > 0 && chars[i] < 128) {
+ if (unsafeCharacters.get(chars[i])) {
+ break;
+ }
+ }
+ if (++i >= chars.length) {
+ return s;
+ }
+ }
+
+ // okay there are some unsafe characters so we do need to encode
+ // see details at: http://en.wikipedia.org/wiki/Url_encode
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < chars.length; i++) {
+ char ch = chars[i];
+ if (ch > 0 && ch < 128 && unsafeCharacters.get(ch)) {
+ // special for % sign as it may be a decimal encoded value
+ if (ch == '%') {
+ char next = i + 1 < chars.length ? chars[i + 1] : ' ';
+ char next2 = i + 2 < chars.length ? chars[i + 2] : ' ';
+
+ if (isHexDigit(next) && isHexDigit(next2) && !isRaw(i, rawPairs)) {
+ // its already encoded (decimal encoded) so just append as is
+ sb.append(ch);
+ } else {
+ // must escape then, as its an unsafe character
+ appendEscape(sb, (byte) ch);
+ }
+ } else {
+ // must escape then, as its an unsafe character
+ appendEscape(sb, (byte) ch);
+ }
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ private static void appendEscape(StringBuilder sb, byte b) {
+ sb.append('%');
+ sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
+ sb.append(HEX_DIGITS[(b >> 0) & 0x0f]);
+ }
+
+ private static boolean isHexDigit(char ch) {
+ for (char hex : HEX_DIGITS) {
+ if (hex == ch) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html b/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
new file mode 100644
index 0000000..2f15a04
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/package.html
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<html>
+<head>
+</head>
+<body>
+
+Runtime Camel Catalog
+
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java b/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
index fd22f55..a32c109 100644
--- a/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
@@ -37,8 +37,8 @@ import org.apache.camel.PollingConsumer;
import org.apache.camel.Processor;
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.Route;
-import org.apache.camel.catalog.DefaultRuntimeCamelCatalog;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.DefaultRuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.BrowsableEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -523,7 +523,7 @@ public final class EndpointHelper {
* @param uri the endpoint uri
* @return a map for each option in the uri with the corresponding information from the json
* @throws Exception is thrown in case of error
- * @deprecated use {@link org.apache.camel.catalog.RuntimeCamelCatalog#endpointProperties(String)}
+ * @deprecated use {@link org.apache.camel.runtimecatalog.RuntimeCamelCatalog#endpointProperties(String)}
*/
@Deprecated
public static Map<String, Object> endpointProperties(CamelContext camelContext, String uri) throws Exception {
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
deleted file mode 100644
index ed7e997..0000000
--- a/camel-core/src/test/java/org/apache/camel/catalog/AbstractCamelCatalogTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * 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.catalog;
-
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.mock;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-
-public class AbstractCamelCatalogTest {
-
- AbstractCamelCatalog catalog = new AbstractCamelCatalog() {
- };
-
- JSonSchemaResolver resolver;
-
- @Before
- public void setupMockCatalog() {
- resolver = mock(JSonSchemaResolver.class);
-
- catalog.setJSonSchemaResolver(resolver);
- }
-
- @Test
- public void shouldConstructEndpointUris() throws URISyntaxException {
- expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
- + " \"component\": {\n"//
- + " \"syntax\": \"comp:param1:param2\"\n"//
- + " }\n"//
- + "}");
-
- replay(resolver);
-
- final Map<String, String> properties = new HashMap<>();
- properties.put("param1", "value1");
- properties.put("param2", "value2");
- properties.put("param3", "value3");
-
- final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
- assertEquals("comp:value1:value2?param3=value3", endpointUri);
- }
-
- @Test
- public void shouldConstructEndpointUrisWithPropertyPlaceholders() throws URISyntaxException {
- expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
- + " \"component\": {\n"//
- + " \"syntax\": \"comp:param1:param2\"\n"//
- + " }\n"//
- + "}");
-
- replay(resolver);
-
- final Map<String, String> properties = new HashMap<>();
- properties.put("param1", "{{prop1}}");
- properties.put("param2", "{{prop2}}");
- properties.put("param3", "{{prop3}}");
-
- final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
- assertEquals("comp:{{prop1}}:{{prop2}}?param3={{prop3}}", endpointUri);
- }
-
- @Test
- public void shouldConstructEndpointUrisWhenValuesContainTokens() throws URISyntaxException {
- expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
- + " \"component\": {\n"//
- + " \"syntax\": \"comp:param1:param2\"\n"//
- + " }\n"//
- + "}");
-
- replay(resolver);
-
- final Map<String, String> properties = new HashMap<>();
- properties.put("param1", "{value1}");
- properties.put("param2", "/value2/");
- properties.put("param3", "/value3/{param}");
-
- final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
-
- assertEquals("comp:{value1}:/value2/?param3=/value3/{param}", endpointUri);
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
deleted file mode 100644
index 78e51a2..0000000
--- a/camel-core/src/test/java/org/apache/camel/catalog/RuntimeCamelCatalogTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.impl.DefaultCamelContext;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class RuntimeCamelCatalogTest {
-
- static RuntimeCamelCatalog catalog;
-
- private static final Logger LOG = LoggerFactory.getLogger(RuntimeCamelCatalogTest.class);
-
- @BeforeClass
- public static void createCamelCatalog() {
- catalog = new DefaultRuntimeCamelCatalog(new DefaultCamelContext());
- }
-
- @Test
- public void testFromCamelContext() throws Exception {
- String schema = new DefaultCamelContext().getRuntimeCamelCatalog().modelJSonSchema("choice");
- assertNotNull(schema);
- }
-
- @Test
- public void testJsonSchema() throws Exception {
- String schema = catalog.modelJSonSchema("aggregate");
- assertNotNull(schema);
-
- // lets make it possible to find bean/method using both names
- schema = catalog.modelJSonSchema("method");
- assertNotNull(schema);
- schema = catalog.modelJSonSchema("bean");
- assertNotNull(schema);
- }
-
- @Test
- public void testAsEndpointUriMapFile() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("directoryName", "src/data/inbox");
- map.put("noop", "true");
- map.put("delay", "5000");
-
- String uri = catalog.asEndpointUri("file", map, true);
- assertEquals("file:src/data/inbox?delay=5000&noop=true", uri);
-
- String uri2 = catalog.asEndpointUriXml("file", map, true);
- assertEquals("file:src/data/inbox?delay=5000&noop=true", uri2);
- }
-
- @Test
- public void testAsEndpointUriTimer() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("timerName", "foo");
- map.put("period", "5000");
-
- String uri = catalog.asEndpointUri("timer", map, true);
- assertEquals("timer:foo?period=5000", uri);
- }
-
- @Test
- public void testAsEndpointUriPropertiesPlaceholders() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("timerName", "foo");
- map.put("period", "{{howoften}}");
- map.put("repeatCount", "5");
-
- String uri = catalog.asEndpointUri("timer", map, true);
- assertEquals("timer:foo?period=%7B%7Bhowoften%7D%7D&repeatCount=5", uri);
-
- uri = catalog.asEndpointUri("timer", map, false);
- assertEquals("timer:foo?period={{howoften}}&repeatCount=5", uri);
- }
-
- @Test
- public void testAsEndpointUriBeanLookup() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("resourceUri", "foo.xslt");
- map.put("converter", "#myConverter");
-
- String uri = catalog.asEndpointUri("xslt", map, true);
- assertEquals("xslt:foo.xslt?converter=%23myConverter", uri);
-
- uri = catalog.asEndpointUri("xslt", map, false);
- assertEquals("xslt:foo.xslt?converter=#myConverter", uri);
- }
-
- @Test
- public void testEndpointPropertiesPlaceholders() throws Exception {
- Map<String, String> map = catalog.endpointProperties("timer:foo?period={{howoften}}&repeatCount=5");
- assertNotNull(map);
- assertEquals(3, map.size());
-
- assertEquals("foo", map.get("timerName"));
- assertEquals("{{howoften}}", map.get("period"));
- assertEquals("5", map.get("repeatCount"));
- }
-
- @Test
- public void testAsEndpointUriLog() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("loggerName", "foo");
- map.put("loggerLevel", "WARN");
- map.put("multiline", "true");
- map.put("showAll", "true");
- map.put("showBody", "false");
- map.put("showBodyType", "false");
- map.put("showExchangePattern", "false");
- map.put("style", "Tab");
-
- assertEquals("log:foo?loggerLevel=WARN&multiline=true&showAll=true&style=Tab", catalog.asEndpointUri("log", map, false));
- }
-
- @Test
- public void testAsEndpointUriLogShort() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("loggerName", "foo");
- map.put("loggerLevel", "DEBUG");
-
- assertEquals("log:foo?loggerLevel=DEBUG", catalog.asEndpointUri("log", map, false));
- }
-
- @Test
- public void testAsEndpointUriWithplaceholder() throws Exception {
- Map<String, String> map = new HashMap<String, String>();
- map.put("name", "foo");
- map.put("blockWhenFull", "{{block}}");
- assertEquals("seda:foo?blockWhenFull={{block}}", catalog.asEndpointUri("seda", map, false));
- }
-
- @Test
- public void testEndpointPropertiesSedaRequired() throws Exception {
- Map<String, String> map = catalog.endpointProperties("seda:foo");
- assertNotNull(map);
- assertEquals(1, map.size());
-
- assertEquals("foo", map.get("name"));
-
- map = catalog.endpointProperties("seda:foo?blockWhenFull=true");
- assertNotNull(map);
- assertEquals(2, map.size());
-
- assertEquals("foo", map.get("name"));
- assertEquals("true", map.get("blockWhenFull"));
- }
-
- @Test
- public void validateProperties() throws Exception {
- // valid
- EndpointValidationResult result = catalog.validateEndpointProperties("log:mylog");
- assertTrue(result.isSuccess());
-
- // unknown
- result = catalog.validateEndpointProperties("log:mylog?level=WARN&foo=bar");
- assertFalse(result.isSuccess());
- assertTrue(result.getUnknown().contains("foo"));
- assertEquals(1, result.getNumberOfErrors());
-
- // enum
- result = catalog.validateEndpointProperties("seda:foo?waitForTaskToComplete=blah");
- assertFalse(result.isSuccess());
- assertEquals("blah", result.getInvalidEnum().get("waitForTaskToComplete"));
- assertEquals(1, result.getNumberOfErrors());
-
- // reference okay
- result = catalog.validateEndpointProperties("seda:foo?queue=#queue");
- assertTrue(result.isSuccess());
- assertEquals(0, result.getNumberOfErrors());
-
- // unknown component
- result = catalog.validateEndpointProperties("foo:bar?me=you");
- assertFalse(result.isSuccess());
- assertTrue(result.getUnknownComponent().equals("foo"));
- assertEquals(1, result.getNumberOfErrors());
-
- // invalid boolean but default value
- result = catalog.validateEndpointProperties("log:output?showAll=ggg");
- assertFalse(result.isSuccess());
- assertEquals("ggg", result.getInvalidBoolean().get("showAll"));
- assertEquals(1, result.getNumberOfErrors());
-
- // dataset
- result = catalog.validateEndpointProperties("dataset:foo?minRate=50");
- assertTrue(result.isSuccess());
-
- // time pattern
- result = catalog.validateEndpointProperties("timer://foo?fixedRate=true&delay=0&period=2s");
- assertTrue(result.isSuccess());
-
- // reference lookup
- result = catalog.validateEndpointProperties("timer://foo?fixedRate=#fixed&delay=#myDelay");
- assertTrue(result.isSuccess());
-
- // optional consumer. prefix
- result = catalog.validateEndpointProperties("file:inbox?consumer.delay=5000&consumer.greedy=true");
- assertTrue(result.isSuccess());
-
- // optional without consumer. prefix
- result = catalog.validateEndpointProperties("file:inbox?delay=5000&greedy=true");
- assertTrue(result.isSuccess());
-
- // mixed optional without consumer. prefix
- result = catalog.validateEndpointProperties("file:inbox?delay=5000&consumer.greedy=true");
- assertTrue(result.isSuccess());
-
- // prefix
- result = catalog.validateEndpointProperties("file:inbox?delay=5000&scheduler.foo=123&scheduler.bar=456");
- assertTrue(result.isSuccess());
-
- // stub
- result = catalog.validateEndpointProperties("stub:foo?me=123&you=456");
- assertTrue(result.isSuccess());
-
- // lenient on
- result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar");
- assertTrue(result.isSuccess());
-
- // lenient off
- result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar", true);
- assertFalse(result.isSuccess());
- assertTrue(result.getUnknown().contains("foo"));
-
- // data format
- result = catalog.validateEndpointProperties("dataformat:string:marshal?charset=utf-8", true);
- assertTrue(result.isSuccess());
-
- // incapable to parse
- result = catalog.validateEndpointProperties("{{getFtpUrl}}?recursive=true");
- assertFalse(result.isSuccess());
- assertTrue(result.getIncapable() != null);
- }
-
- @Test
- public void validatePropertiesSummary() throws Exception {
- EndpointValidationResult result = catalog.validateEndpointProperties("yammer:MESSAGES?blah=yada&accessToken=aaa&consumerKey=&useJson=no&initialDelay=five&pollStrategy=myStrategy");
- assertFalse(result.isSuccess());
- String reason = result.summaryErrorMessage(true);
- LOG.info(reason);
-
- result = catalog.validateEndpointProperties("jms:unknown:myqueue");
- assertFalse(result.isSuccess());
- reason = result.summaryErrorMessage(false);
- LOG.info(reason);
- }
-
- @Test
- public void validateTimePattern() throws Exception {
- assertTrue(catalog.validateTimePattern("0"));
- assertTrue(catalog.validateTimePattern("500"));
- assertTrue(catalog.validateTimePattern("10000"));
- assertTrue(catalog.validateTimePattern("5s"));
- assertTrue(catalog.validateTimePattern("5sec"));
- assertTrue(catalog.validateTimePattern("5secs"));
- assertTrue(catalog.validateTimePattern("3m"));
- assertTrue(catalog.validateTimePattern("3min"));
- assertTrue(catalog.validateTimePattern("3minutes"));
- assertTrue(catalog.validateTimePattern("5m15s"));
- assertTrue(catalog.validateTimePattern("1h"));
- assertTrue(catalog.validateTimePattern("1hour"));
- assertTrue(catalog.validateTimePattern("2hours"));
-
- assertFalse(catalog.validateTimePattern("bla"));
- assertFalse(catalog.validateTimePattern("2year"));
- assertFalse(catalog.validateTimePattern("60darn"));
- }
-
- @Test
- public void testEndpointComponentName() throws Exception {
- String name = catalog.endpointComponentName("jms:queue:foo");
- assertEquals("jms", name);
- }
-
- @Test
- public void testSimpleExpression() throws Exception {
- SimpleValidationResult result = catalog.validateSimpleExpression(null, "${body}");
- assertTrue(result.isSuccess());
- assertEquals("${body}", result.getSimple());
-
- result = catalog.validateSimpleExpression(null, "${body");
- assertFalse(result.isSuccess());
- assertEquals("${body", result.getSimple());
- LOG.info(result.getError());
- assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 5"));
- assertEquals("expected symbol functionEnd but was eol", result.getShortError());
- assertEquals(5, result.getIndex());
- }
-
- @Test
- public void testSimplePredicate() throws Exception {
- SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} == 'abc'");
- assertTrue(result.isSuccess());
- assertEquals("${body} == 'abc'", result.getSimple());
-
- result = catalog.validateSimplePredicate(null, "${body} > ${header.size");
- assertFalse(result.isSuccess());
- assertEquals("${body} > ${header.size", result.getSimple());
- LOG.info(result.getError());
- assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 22"));
- assertEquals("expected symbol functionEnd but was eol", result.getShortError());
- assertEquals(22, result.getIndex());
- }
-
- @Test
- public void testSimplePredicatePlaceholder() throws Exception {
- SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} contains '{{danger}}'");
- assertTrue(result.isSuccess());
- assertEquals("${body} contains '{{danger}}'", result.getSimple());
-
- result = catalog.validateSimplePredicate(null, "${bdy} contains '{{danger}}'");
- assertFalse(result.isSuccess());
- assertEquals("${bdy} contains '{{danger}}'", result.getSimple());
- LOG.info(result.getError());
- assertTrue(result.getError().startsWith("Unknown function: bdy at location 0"));
- assertTrue(result.getError().contains("'{{danger}}'"));
- assertEquals("Unknown function: bdy", result.getShortError());
- assertEquals(0, result.getIndex());
- }
-
- @Test
- public void testValidateLanguage() throws Exception {
- LanguageValidationResult result = catalog.validateLanguageExpression(null, "simple", "${body}");
- assertTrue(result.isSuccess());
- assertEquals("${body}", result.getText());
-
- result = catalog.validateLanguageExpression(null, "header", "foo");
- assertTrue(result.isSuccess());
- assertEquals("foo", result.getText());
-
- result = catalog.validateLanguagePredicate(null, "simple", "${body} > 10");
- assertTrue(result.isSuccess());
- assertEquals("${body} > 10", result.getText());
-
- result = catalog.validateLanguagePredicate(null, "header", "bar");
- assertTrue(result.isSuccess());
- assertEquals("bar", result.getText());
-
- result = catalog.validateLanguagePredicate(null, "foobar", "bar");
- assertFalse(result.isSuccess());
- assertEquals("Unknown language foobar", result.getError());
- }
-
- @Test
- public void testValidateEndpointConsumerOnly() throws Exception {
- String uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true";
- EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, true, false);
- assertTrue(result.isSuccess());
-
- uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true&fileExist=Append";
- result = catalog.validateEndpointProperties(uri, false, true, false);
- assertFalse(result.isSuccess());
-
- assertEquals("fileExist", result.getNotConsumerOnly().iterator().next());
- }
-
- @Test
- public void testValidateEndpointProducerOnly() throws Exception {
- String uri = "file:outbox?bufferSize=4096&fileExist=Append";
- EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, false, true);
- assertTrue(result.isSuccess());
-
- uri = "file:outbox?bufferSize=4096&fileExist=Append&delete=true";
- result = catalog.validateEndpointProperties(uri, false, false, true);
- assertFalse(result.isSuccess());
-
- assertEquals("delete", result.getNotProducerOnly().iterator().next());
- }
-
-}
[2/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
new file mode 100644
index 0000000..309fb8e
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/runtimecatalog/AbstractCamelCatalogTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.runtimecatalog;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.mock;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+
+public class AbstractCamelCatalogTest {
+
+ AbstractCamelCatalog catalog = new AbstractCamelCatalog() {
+ };
+
+ JSonSchemaResolver resolver;
+
+ @Before
+ public void setupMockCatalog() {
+ resolver = mock(JSonSchemaResolver.class);
+
+ catalog.setJSonSchemaResolver(resolver);
+ }
+
+ @Test
+ public void shouldConstructEndpointUris() throws URISyntaxException {
+ expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+ + " \"component\": {\n"//
+ + " \"syntax\": \"comp:param1:param2\"\n"//
+ + " }\n"//
+ + "}");
+
+ replay(resolver);
+
+ final Map<String, String> properties = new HashMap<>();
+ properties.put("param1", "value1");
+ properties.put("param2", "value2");
+ properties.put("param3", "value3");
+
+ final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+ assertEquals("comp:value1:value2?param3=value3", endpointUri);
+ }
+
+ @Test
+ public void shouldConstructEndpointUrisWithPropertyPlaceholders() throws URISyntaxException {
+ expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+ + " \"component\": {\n"//
+ + " \"syntax\": \"comp:param1:param2\"\n"//
+ + " }\n"//
+ + "}");
+
+ replay(resolver);
+
+ final Map<String, String> properties = new HashMap<>();
+ properties.put("param1", "{{prop1}}");
+ properties.put("param2", "{{prop2}}");
+ properties.put("param3", "{{prop3}}");
+
+ final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+ assertEquals("comp:{{prop1}}:{{prop2}}?param3={{prop3}}", endpointUri);
+ }
+
+ @Test
+ public void shouldConstructEndpointUrisWhenValuesContainTokens() throws URISyntaxException {
+ expect(resolver.getComponentJSonSchema("comp")).andReturn("{\n"//
+ + " \"component\": {\n"//
+ + " \"syntax\": \"comp:param1:param2\"\n"//
+ + " }\n"//
+ + "}");
+
+ replay(resolver);
+
+ final Map<String, String> properties = new HashMap<>();
+ properties.put("param1", "{value1}");
+ properties.put("param2", "/value2/");
+ properties.put("param3", "/value3/{param}");
+
+ final String endpointUri = catalog.doAsEndpointUri("comp", properties, "&", false);
+
+ assertEquals("comp:{value1}:/value2/?param3=/value3/{param}", endpointUri);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java b/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
new file mode 100644
index 0000000..dfdd5c5
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/runtimecatalog/RuntimeCamelCatalogTest.java
@@ -0,0 +1,393 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class RuntimeCamelCatalogTest {
+
+ static RuntimeCamelCatalog catalog;
+
+ private static final Logger LOG = LoggerFactory.getLogger(RuntimeCamelCatalogTest.class);
+
+ @BeforeClass
+ public static void createCamelCatalog() {
+ catalog = new DefaultRuntimeCamelCatalog(new DefaultCamelContext());
+ }
+
+ @Test
+ public void testFromCamelContext() throws Exception {
+ String schema = new DefaultCamelContext().getRuntimeCamelCatalog().modelJSonSchema("choice");
+ assertNotNull(schema);
+ }
+
+ @Test
+ public void testJsonSchema() throws Exception {
+ String schema = catalog.modelJSonSchema("aggregate");
+ assertNotNull(schema);
+
+ // lets make it possible to find bean/method using both names
+ schema = catalog.modelJSonSchema("method");
+ assertNotNull(schema);
+ schema = catalog.modelJSonSchema("bean");
+ assertNotNull(schema);
+ }
+
+ @Test
+ public void testAsEndpointUriMapFile() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("directoryName", "src/data/inbox");
+ map.put("noop", "true");
+ map.put("delay", "5000");
+
+ String uri = catalog.asEndpointUri("file", map, true);
+ assertEquals("file:src/data/inbox?delay=5000&noop=true", uri);
+
+ String uri2 = catalog.asEndpointUriXml("file", map, true);
+ assertEquals("file:src/data/inbox?delay=5000&noop=true", uri2);
+ }
+
+ @Test
+ public void testAsEndpointUriTimer() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("timerName", "foo");
+ map.put("period", "5000");
+
+ String uri = catalog.asEndpointUri("timer", map, true);
+ assertEquals("timer:foo?period=5000", uri);
+ }
+
+ @Test
+ public void testAsEndpointUriPropertiesPlaceholders() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("timerName", "foo");
+ map.put("period", "{{howoften}}");
+ map.put("repeatCount", "5");
+
+ String uri = catalog.asEndpointUri("timer", map, true);
+ assertEquals("timer:foo?period=%7B%7Bhowoften%7D%7D&repeatCount=5", uri);
+
+ uri = catalog.asEndpointUri("timer", map, false);
+ assertEquals("timer:foo?period={{howoften}}&repeatCount=5", uri);
+ }
+
+ @Test
+ public void testAsEndpointUriBeanLookup() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("resourceUri", "foo.xslt");
+ map.put("converter", "#myConverter");
+
+ String uri = catalog.asEndpointUri("xslt", map, true);
+ assertEquals("xslt:foo.xslt?converter=%23myConverter", uri);
+
+ uri = catalog.asEndpointUri("xslt", map, false);
+ assertEquals("xslt:foo.xslt?converter=#myConverter", uri);
+ }
+
+ @Test
+ public void testEndpointPropertiesPlaceholders() throws Exception {
+ Map<String, String> map = catalog.endpointProperties("timer:foo?period={{howoften}}&repeatCount=5");
+ assertNotNull(map);
+ assertEquals(3, map.size());
+
+ assertEquals("foo", map.get("timerName"));
+ assertEquals("{{howoften}}", map.get("period"));
+ assertEquals("5", map.get("repeatCount"));
+ }
+
+ @Test
+ public void testAsEndpointUriLog() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("loggerName", "foo");
+ map.put("loggerLevel", "WARN");
+ map.put("multiline", "true");
+ map.put("showAll", "true");
+ map.put("showBody", "false");
+ map.put("showBodyType", "false");
+ map.put("showExchangePattern", "false");
+ map.put("style", "Tab");
+
+ assertEquals("log:foo?loggerLevel=WARN&multiline=true&showAll=true&style=Tab", catalog.asEndpointUri("log", map, false));
+ }
+
+ @Test
+ public void testAsEndpointUriLogShort() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("loggerName", "foo");
+ map.put("loggerLevel", "DEBUG");
+
+ assertEquals("log:foo?loggerLevel=DEBUG", catalog.asEndpointUri("log", map, false));
+ }
+
+ @Test
+ public void testAsEndpointUriWithplaceholder() throws Exception {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("name", "foo");
+ map.put("blockWhenFull", "{{block}}");
+ assertEquals("seda:foo?blockWhenFull={{block}}", catalog.asEndpointUri("seda", map, false));
+ }
+
+ @Test
+ public void testEndpointPropertiesSedaRequired() throws Exception {
+ Map<String, String> map = catalog.endpointProperties("seda:foo");
+ assertNotNull(map);
+ assertEquals(1, map.size());
+
+ assertEquals("foo", map.get("name"));
+
+ map = catalog.endpointProperties("seda:foo?blockWhenFull=true");
+ assertNotNull(map);
+ assertEquals(2, map.size());
+
+ assertEquals("foo", map.get("name"));
+ assertEquals("true", map.get("blockWhenFull"));
+ }
+
+ @Test
+ public void validateProperties() throws Exception {
+ // valid
+ EndpointValidationResult result = catalog.validateEndpointProperties("log:mylog");
+ assertTrue(result.isSuccess());
+
+ // unknown
+ result = catalog.validateEndpointProperties("log:mylog?level=WARN&foo=bar");
+ assertFalse(result.isSuccess());
+ assertTrue(result.getUnknown().contains("foo"));
+ assertEquals(1, result.getNumberOfErrors());
+
+ // enum
+ result = catalog.validateEndpointProperties("seda:foo?waitForTaskToComplete=blah");
+ assertFalse(result.isSuccess());
+ assertEquals("blah", result.getInvalidEnum().get("waitForTaskToComplete"));
+ assertEquals(1, result.getNumberOfErrors());
+
+ // reference okay
+ result = catalog.validateEndpointProperties("seda:foo?queue=#queue");
+ assertTrue(result.isSuccess());
+ assertEquals(0, result.getNumberOfErrors());
+
+ // unknown component
+ result = catalog.validateEndpointProperties("foo:bar?me=you");
+ assertFalse(result.isSuccess());
+ assertTrue(result.getUnknownComponent().equals("foo"));
+ assertEquals(1, result.getNumberOfErrors());
+
+ // invalid boolean but default value
+ result = catalog.validateEndpointProperties("log:output?showAll=ggg");
+ assertFalse(result.isSuccess());
+ assertEquals("ggg", result.getInvalidBoolean().get("showAll"));
+ assertEquals(1, result.getNumberOfErrors());
+
+ // dataset
+ result = catalog.validateEndpointProperties("dataset:foo?minRate=50");
+ assertTrue(result.isSuccess());
+
+ // time pattern
+ result = catalog.validateEndpointProperties("timer://foo?fixedRate=true&delay=0&period=2s");
+ assertTrue(result.isSuccess());
+
+ // reference lookup
+ result = catalog.validateEndpointProperties("timer://foo?fixedRate=#fixed&delay=#myDelay");
+ assertTrue(result.isSuccess());
+
+ // optional consumer. prefix
+ result = catalog.validateEndpointProperties("file:inbox?consumer.delay=5000&consumer.greedy=true");
+ assertTrue(result.isSuccess());
+
+ // optional without consumer. prefix
+ result = catalog.validateEndpointProperties("file:inbox?delay=5000&greedy=true");
+ assertTrue(result.isSuccess());
+
+ // mixed optional without consumer. prefix
+ result = catalog.validateEndpointProperties("file:inbox?delay=5000&consumer.greedy=true");
+ assertTrue(result.isSuccess());
+
+ // prefix
+ result = catalog.validateEndpointProperties("file:inbox?delay=5000&scheduler.foo=123&scheduler.bar=456");
+ assertTrue(result.isSuccess());
+
+ // stub
+ result = catalog.validateEndpointProperties("stub:foo?me=123&you=456");
+ assertTrue(result.isSuccess());
+
+ // lenient on
+ result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar");
+ assertTrue(result.isSuccess());
+
+ // lenient off
+ result = catalog.validateEndpointProperties("dataformat:string:marshal?foo=bar", true);
+ assertFalse(result.isSuccess());
+ assertTrue(result.getUnknown().contains("foo"));
+
+ // data format
+ result = catalog.validateEndpointProperties("dataformat:string:marshal?charset=utf-8", true);
+ assertTrue(result.isSuccess());
+
+ // incapable to parse
+ result = catalog.validateEndpointProperties("{{getFtpUrl}}?recursive=true");
+ assertFalse(result.isSuccess());
+ assertTrue(result.getIncapable() != null);
+ }
+
+ @Test
+ public void validatePropertiesSummary() throws Exception {
+ EndpointValidationResult result = catalog.validateEndpointProperties("yammer:MESSAGES?blah=yada&accessToken=aaa&consumerKey=&useJson=no&initialDelay=five&pollStrategy=myStrategy");
+ assertFalse(result.isSuccess());
+ String reason = result.summaryErrorMessage(true);
+ LOG.info(reason);
+
+ result = catalog.validateEndpointProperties("jms:unknown:myqueue");
+ assertFalse(result.isSuccess());
+ reason = result.summaryErrorMessage(false);
+ LOG.info(reason);
+ }
+
+ @Test
+ public void validateTimePattern() throws Exception {
+ assertTrue(catalog.validateTimePattern("0"));
+ assertTrue(catalog.validateTimePattern("500"));
+ assertTrue(catalog.validateTimePattern("10000"));
+ assertTrue(catalog.validateTimePattern("5s"));
+ assertTrue(catalog.validateTimePattern("5sec"));
+ assertTrue(catalog.validateTimePattern("5secs"));
+ assertTrue(catalog.validateTimePattern("3m"));
+ assertTrue(catalog.validateTimePattern("3min"));
+ assertTrue(catalog.validateTimePattern("3minutes"));
+ assertTrue(catalog.validateTimePattern("5m15s"));
+ assertTrue(catalog.validateTimePattern("1h"));
+ assertTrue(catalog.validateTimePattern("1hour"));
+ assertTrue(catalog.validateTimePattern("2hours"));
+
+ assertFalse(catalog.validateTimePattern("bla"));
+ assertFalse(catalog.validateTimePattern("2year"));
+ assertFalse(catalog.validateTimePattern("60darn"));
+ }
+
+ @Test
+ public void testEndpointComponentName() throws Exception {
+ String name = catalog.endpointComponentName("jms:queue:foo");
+ assertEquals("jms", name);
+ }
+
+ @Test
+ public void testSimpleExpression() throws Exception {
+ SimpleValidationResult result = catalog.validateSimpleExpression(null, "${body}");
+ assertTrue(result.isSuccess());
+ assertEquals("${body}", result.getSimple());
+
+ result = catalog.validateSimpleExpression(null, "${body");
+ assertFalse(result.isSuccess());
+ assertEquals("${body", result.getSimple());
+ LOG.info(result.getError());
+ assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 5"));
+ assertEquals("expected symbol functionEnd but was eol", result.getShortError());
+ assertEquals(5, result.getIndex());
+ }
+
+ @Test
+ public void testSimplePredicate() throws Exception {
+ SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} == 'abc'");
+ assertTrue(result.isSuccess());
+ assertEquals("${body} == 'abc'", result.getSimple());
+
+ result = catalog.validateSimplePredicate(null, "${body} > ${header.size");
+ assertFalse(result.isSuccess());
+ assertEquals("${body} > ${header.size", result.getSimple());
+ LOG.info(result.getError());
+ assertTrue(result.getError().startsWith("expected symbol functionEnd but was eol at location 22"));
+ assertEquals("expected symbol functionEnd but was eol", result.getShortError());
+ assertEquals(22, result.getIndex());
+ }
+
+ @Test
+ public void testSimplePredicatePlaceholder() throws Exception {
+ SimpleValidationResult result = catalog.validateSimplePredicate(null, "${body} contains '{{danger}}'");
+ assertTrue(result.isSuccess());
+ assertEquals("${body} contains '{{danger}}'", result.getSimple());
+
+ result = catalog.validateSimplePredicate(null, "${bdy} contains '{{danger}}'");
+ assertFalse(result.isSuccess());
+ assertEquals("${bdy} contains '{{danger}}'", result.getSimple());
+ LOG.info(result.getError());
+ assertTrue(result.getError().startsWith("Unknown function: bdy at location 0"));
+ assertTrue(result.getError().contains("'{{danger}}'"));
+ assertEquals("Unknown function: bdy", result.getShortError());
+ assertEquals(0, result.getIndex());
+ }
+
+ @Test
+ public void testValidateLanguage() throws Exception {
+ LanguageValidationResult result = catalog.validateLanguageExpression(null, "simple", "${body}");
+ assertTrue(result.isSuccess());
+ assertEquals("${body}", result.getText());
+
+ result = catalog.validateLanguageExpression(null, "header", "foo");
+ assertTrue(result.isSuccess());
+ assertEquals("foo", result.getText());
+
+ result = catalog.validateLanguagePredicate(null, "simple", "${body} > 10");
+ assertTrue(result.isSuccess());
+ assertEquals("${body} > 10", result.getText());
+
+ result = catalog.validateLanguagePredicate(null, "header", "bar");
+ assertTrue(result.isSuccess());
+ assertEquals("bar", result.getText());
+
+ result = catalog.validateLanguagePredicate(null, "foobar", "bar");
+ assertFalse(result.isSuccess());
+ assertEquals("Unknown language foobar", result.getError());
+ }
+
+ @Test
+ public void testValidateEndpointConsumerOnly() throws Exception {
+ String uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true";
+ EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, true, false);
+ assertTrue(result.isSuccess());
+
+ uri = "file:inbox?bufferSize=4096&readLock=changed&delete=true&fileExist=Append";
+ result = catalog.validateEndpointProperties(uri, false, true, false);
+ assertFalse(result.isSuccess());
+
+ assertEquals("fileExist", result.getNotConsumerOnly().iterator().next());
+ }
+
+ @Test
+ public void testValidateEndpointProducerOnly() throws Exception {
+ String uri = "file:outbox?bufferSize=4096&fileExist=Append";
+ EndpointValidationResult result = catalog.validateEndpointProperties(uri, false, false, true);
+ assertTrue(result.isSuccess());
+
+ uri = "file:outbox?bufferSize=4096&fileExist=Append&delete=true";
+ result = catalog.validateEndpointProperties(uri, false, false, true);
+ assertFalse(result.isSuccess());
+
+ assertEquals("delete", result.getNotProducerOnly().iterator().next());
+ }
+
+}
[4/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
new file mode 100644
index 0000000..0420708
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/AbstractCamelCatalog.java
@@ -0,0 +1,1294 @@
+/**
+ * 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.runtimecatalog;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+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.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.camel.runtimecatalog.CatalogHelper.after;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getNames;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyDefaultValue;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyEnum;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyKind;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyNameFromNameWithPrefix;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getPropertyPrefix;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.getRow;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentConsumerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentLenientProperties;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isComponentProducerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyBoolean;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyConsumerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyInteger;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyMultiValue;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyNumber;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyObject;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyProducerOnly;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.isPropertyRequired;
+import static org.apache.camel.runtimecatalog.JSonSchemaHelper.stripOptionalPrefixFromName;
+import static org.apache.camel.runtimecatalog.URISupport.createQueryString;
+import static org.apache.camel.runtimecatalog.URISupport.isEmpty;
+import static org.apache.camel.runtimecatalog.URISupport.normalizeUri;
+import static org.apache.camel.runtimecatalog.URISupport.stripQuery;
+
+/**
+ * Base class for both the runtime RuntimeCamelCatalog from camel-core and the complete CamelCatalog from camel-catalog.
+ */
+public abstract class AbstractCamelCatalog {
+
+ // CHECKSTYLE:OFF
+
+ private static final Pattern SYNTAX_PATTERN = Pattern.compile("(\\w+)");
+
+ private SuggestionStrategy suggestionStrategy;
+ private JSonSchemaResolver jsonSchemaResolver;
+
+ public SuggestionStrategy getSuggestionStrategy() {
+ return suggestionStrategy;
+ }
+
+ public void setSuggestionStrategy(SuggestionStrategy suggestionStrategy) {
+ this.suggestionStrategy = suggestionStrategy;
+ }
+
+ public JSonSchemaResolver getJSonSchemaResolver() {
+ return jsonSchemaResolver;
+ }
+
+ public void setJSonSchemaResolver(JSonSchemaResolver resolver) {
+ this.jsonSchemaResolver = resolver;
+ }
+
+ public boolean validateTimePattern(String pattern) {
+ return validateInteger(pattern);
+ }
+
+ public EndpointValidationResult validateEndpointProperties(String uri) {
+ return validateEndpointProperties(uri, false, false, false);
+ }
+
+ public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties) {
+ return validateEndpointProperties(uri, ignoreLenientProperties, false, false);
+ }
+
+ public EndpointValidationResult validateProperties(String scheme, Map<String, String> properties) {
+ EndpointValidationResult result = new EndpointValidationResult(scheme);
+
+ String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+ List<Map<String, String>> componentProps = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
+
+ // endpoint options have higher priority so remove those from component
+ // that may clash
+ componentProps.stream()
+ .filter(c -> rows.stream().noneMatch(e -> Objects.equals(e.get("name"), c.get("name"))))
+ .forEach(rows::add);
+
+ boolean lenient = Boolean.getBoolean(properties.getOrDefault("lenient", "false"));
+
+ // the dataformat component refers to a data format so lets add the properties for the selected
+ // data format to the list of rows
+ if ("dataformat".equals(scheme)) {
+ String dfName = properties.get("name");
+ if (dfName != null) {
+ String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
+ List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
+ if (dfRows != null && !dfRows.isEmpty()) {
+ rows.addAll(dfRows);
+ }
+ }
+ }
+
+ for (Map.Entry<String, String> property : properties.entrySet()) {
+ String value = property.getValue();
+ String originalName = property.getKey();
+ String name = property.getKey();
+ // the name may be using an optional prefix, so lets strip that because the options
+ // in the schema are listed without the prefix
+ name = stripOptionalPrefixFromName(rows, name);
+ // the name may be using a prefix, so lets see if we can find the real property name
+ String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
+ if (propertyName != null) {
+ name = propertyName;
+ }
+
+ String prefix = getPropertyPrefix(rows, name);
+ String kind = getPropertyKind(rows, name);
+ boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
+ boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
+ boolean lookup = value.startsWith("#") && value.length() > 1;
+ // we cannot evaluate multi values as strict as the others, as we don't know their expected types
+ boolean multiValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
+
+ Map<String, String> row = getRow(rows, name);
+ if (row == null) {
+ // unknown option
+
+ // only add as error if the component is not lenient properties, or not stub component
+ // and the name is not a property placeholder for one or more values
+ if (!namePlaceholder && !"stub".equals(scheme)) {
+ if (lenient) {
+ // as if we are lenient then the option is a dynamic extra option which we cannot validate
+ result.addLenient(name);
+ } else {
+ // its unknown
+ result.addUnknown(name);
+ if (suggestionStrategy != null) {
+ String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
+ if (suggestions != null) {
+ result.addUnknownSuggestions(name, suggestions);
+ }
+ }
+ }
+ }
+ } else {
+ /* TODO: we may need to add something in the properties to know if they are related to a producer or consumer
+ if ("parameter".equals(kind)) {
+ // consumer only or producer only mode for parameters
+ if (consumerOnly) {
+ boolean producer = isPropertyProducerOnly(rows, name);
+ if (producer) {
+ // the option is only for producer so you cannot use it in consumer mode
+ result.addNotConsumerOnly(name);
+ }
+ } else if (producerOnly) {
+ boolean consumer = isPropertyConsumerOnly(rows, name);
+ if (consumer) {
+ // the option is only for consumer so you cannot use it in producer mode
+ result.addNotProducerOnly(name);
+ }
+ }
+ }
+ */
+
+ // default value
+ String defaultValue = getPropertyDefaultValue(rows, name);
+ if (defaultValue != null) {
+ result.addDefaultValue(name, defaultValue);
+ }
+
+ // is required but the value is empty
+ boolean required = isPropertyRequired(rows, name);
+ if (required && isEmpty(value)) {
+ result.addRequired(name);
+ }
+
+ // is enum but the value is not within the enum range
+ // but we can only check if the value is not a placeholder
+ String enums = getPropertyEnum(rows, name);
+ if (!multiValue && !valuePlaceholder && !lookup && enums != null) {
+ String[] choices = enums.split(",");
+ boolean found = false;
+ for (String s : choices) {
+ if (value.equalsIgnoreCase(s)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ result.addInvalidEnum(name, value);
+ result.addInvalidEnumChoices(name, choices);
+ if (suggestionStrategy != null) {
+ Set<String> names = new LinkedHashSet<>();
+ names.addAll(Arrays.asList(choices));
+ String[] suggestions = suggestionStrategy.suggestEndpointOptions(names, value);
+ if (suggestions != null) {
+ result.addInvalidEnumSuggestions(name, suggestions);
+ }
+ }
+
+ }
+ }
+
+ // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
+ if (!multiValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
+ // must start with # and be at least 2 characters
+ if (!value.startsWith("#") || value.length() <= 1) {
+ result.addInvalidReference(name, value);
+ }
+ }
+
+ // is boolean
+ if (!multiValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
+ // value must be a boolean
+ boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
+ if (!bool) {
+ result.addInvalidBoolean(name, value);
+ }
+ }
+
+ // is integer
+ if (!multiValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
+ // value must be an integer
+ boolean valid = validateInteger(value);
+ if (!valid) {
+ result.addInvalidInteger(name, value);
+ }
+ }
+
+ // is number
+ if (!multiValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
+ // value must be an number
+ boolean valid = false;
+ try {
+ valid = !Double.valueOf(value).isNaN() || !Float.valueOf(value).isNaN();
+ } catch (Exception e) {
+ // ignore
+ }
+ if (!valid) {
+ result.addInvalidNumber(name, value);
+ }
+ }
+ }
+ }
+
+ // now check if all required values are there, and that a default value does not exists
+ for (Map<String, String> row : rows) {
+ String name = row.get("name");
+ boolean required = isPropertyRequired(rows, name);
+ if (required) {
+ String value = properties.get(name);
+ if (isEmpty(value)) {
+ value = getPropertyDefaultValue(rows, name);
+ }
+ if (isEmpty(value)) {
+ result.addRequired(name);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly) {
+ EndpointValidationResult result = new EndpointValidationResult(uri);
+
+ Map<String, String> properties;
+ List<Map<String, String>> rows;
+ boolean lenientProperties;
+ String scheme;
+
+ try {
+ String json = null;
+
+ // parse the uri
+ URI u = normalizeUri(uri);
+ scheme = u.getScheme();
+
+ if (scheme != null) {
+ json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+ }
+ if (json == null) {
+ // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
+ if (uri.startsWith("{{")) {
+ result.addIncapable(uri);
+ } else if (scheme != null) {
+ result.addUnknownComponent(scheme);
+ } else {
+ result.addUnknownComponent(uri);
+ }
+ return result;
+ }
+
+ rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+
+ // is the component capable of both consumer and producer?
+ boolean canConsumeAndProduce = false;
+ if (!isComponentConsumerOnly(rows) && !isComponentProducerOnly(rows)) {
+ canConsumeAndProduce = true;
+ }
+
+ if (canConsumeAndProduce && consumerOnly) {
+ // lenient properties is not support in consumer only mode if the component can do both of them
+ lenientProperties = false;
+ } else {
+ // only enable lenient properties if we should not ignore
+ lenientProperties = !ignoreLenientProperties && isComponentLenientProperties(rows);
+ }
+ rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+ properties = endpointProperties(uri);
+ } catch (URISyntaxException e) {
+ if (uri.startsWith("{{")) {
+ // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
+ result.addIncapable(uri);
+ } else {
+ result.addSyntaxError(e.getMessage());
+ }
+
+ return result;
+ }
+
+ // the dataformat component refers to a data format so lets add the properties for the selected
+ // data format to the list of rows
+ if ("dataformat".equals(scheme)) {
+ String dfName = properties.get("name");
+ if (dfName != null) {
+ String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
+ List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
+ if (dfRows != null && !dfRows.isEmpty()) {
+ rows.addAll(dfRows);
+ }
+ }
+ }
+
+ for (Map.Entry<String, String> property : properties.entrySet()) {
+ String value = property.getValue();
+ String originalName = property.getKey();
+ String name = property.getKey();
+ // the name may be using an optional prefix, so lets strip that because the options
+ // in the schema are listed without the prefix
+ name = stripOptionalPrefixFromName(rows, name);
+ // the name may be using a prefix, so lets see if we can find the real property name
+ String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
+ if (propertyName != null) {
+ name = propertyName;
+ }
+
+ String prefix = getPropertyPrefix(rows, name);
+ String kind = getPropertyKind(rows, name);
+ boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
+ boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
+ boolean lookup = value.startsWith("#") && value.length() > 1;
+ // we cannot evaluate multi values as strict as the others, as we don't know their expected types
+ boolean mulitValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
+
+ Map<String, String> row = getRow(rows, name);
+ if (row == null) {
+ // unknown option
+
+ // only add as error if the component is not lenient properties, or not stub component
+ // and the name is not a property placeholder for one or more values
+ if (!namePlaceholder && !"stub".equals(scheme)) {
+ if (lenientProperties) {
+ // as if we are lenient then the option is a dynamic extra option which we cannot validate
+ result.addLenient(name);
+ } else {
+ // its unknown
+ result.addUnknown(name);
+ if (suggestionStrategy != null) {
+ String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
+ if (suggestions != null) {
+ result.addUnknownSuggestions(name, suggestions);
+ }
+ }
+ }
+ }
+ } else {
+ if ("parameter".equals(kind)) {
+ // consumer only or producer only mode for parameters
+ if (consumerOnly) {
+ boolean producer = isPropertyProducerOnly(rows, name);
+ if (producer) {
+ // the option is only for producer so you cannot use it in consumer mode
+ result.addNotConsumerOnly(name);
+ }
+ } else if (producerOnly) {
+ boolean consumer = isPropertyConsumerOnly(rows, name);
+ if (consumer) {
+ // the option is only for consumer so you cannot use it in producer mode
+ result.addNotProducerOnly(name);
+ }
+ }
+ }
+
+ // default value
+ String defaultValue = getPropertyDefaultValue(rows, name);
+ if (defaultValue != null) {
+ result.addDefaultValue(name, defaultValue);
+ }
+
+ // is required but the value is empty
+ boolean required = isPropertyRequired(rows, name);
+ if (required && isEmpty(value)) {
+ result.addRequired(name);
+ }
+
+ // is enum but the value is not within the enum range
+ // but we can only check if the value is not a placeholder
+ String enums = getPropertyEnum(rows, name);
+ if (!mulitValue && !valuePlaceholder && !lookup && enums != null) {
+ String[] choices = enums.split(",");
+ boolean found = false;
+ for (String s : choices) {
+ if (value.equalsIgnoreCase(s)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ result.addInvalidEnum(name, value);
+ result.addInvalidEnumChoices(name, choices);
+ if (suggestionStrategy != null) {
+ Set<String> names = new LinkedHashSet<>();
+ names.addAll(Arrays.asList(choices));
+ String[] suggestions = suggestionStrategy.suggestEndpointOptions(names, value);
+ if (suggestions != null) {
+ result.addInvalidEnumSuggestions(name, suggestions);
+ }
+ }
+
+ }
+ }
+
+ // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
+ if (!mulitValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
+ // must start with # and be at least 2 characters
+ if (!value.startsWith("#") || value.length() <= 1) {
+ result.addInvalidReference(name, value);
+ }
+ }
+
+ // is boolean
+ if (!mulitValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
+ // value must be a boolean
+ boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
+ if (!bool) {
+ result.addInvalidBoolean(name, value);
+ }
+ }
+
+ // is integer
+ if (!mulitValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
+ // value must be an integer
+ boolean valid = validateInteger(value);
+ if (!valid) {
+ result.addInvalidInteger(name, value);
+ }
+ }
+
+ // is number
+ if (!mulitValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
+ // value must be an number
+ boolean valid = false;
+ try {
+ valid = !Double.valueOf(value).isNaN() || !Float.valueOf(value).isNaN();
+ } catch (Exception e) {
+ // ignore
+ }
+ if (!valid) {
+ result.addInvalidNumber(name, value);
+ }
+ }
+ }
+ }
+
+ // now check if all required values are there, and that a default value does not exists
+ for (Map<String, String> row : rows) {
+ String name = row.get("name");
+ boolean required = isPropertyRequired(rows, name);
+ if (required) {
+ String value = properties.get(name);
+ if (isEmpty(value)) {
+ value = getPropertyDefaultValue(rows, name);
+ }
+ if (isEmpty(value)) {
+ result.addRequired(name);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public Map<String, String> endpointProperties(String uri) throws URISyntaxException {
+ // need to normalize uri first
+ URI u = normalizeUri(uri);
+ String scheme = u.getScheme();
+
+ String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+ if (json == null) {
+ throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+ }
+
+ // grab the syntax
+ String syntax = null;
+ String alternativeSyntax = null;
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("syntax")) {
+ syntax = row.get("syntax");
+ }
+ if (row.containsKey("alternativeSyntax")) {
+ alternativeSyntax = row.get("alternativeSyntax");
+ }
+ }
+ if (syntax == null) {
+ throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
+ }
+
+ // only if we support alternative syntax, and the uri contains the username and password in the authority
+ // part of the uri, then we would need some special logic to capture that information and strip those
+ // details from the uri, so we can continue parsing the uri using the normal syntax
+ Map<String, String> userInfoOptions = new LinkedHashMap<String, String>();
+ if (alternativeSyntax != null && alternativeSyntax.contains("@")) {
+ // clip the scheme from the syntax
+ alternativeSyntax = after(alternativeSyntax, ":");
+ // trim so only userinfo
+ int idx = alternativeSyntax.indexOf("@");
+ String fields = alternativeSyntax.substring(0, idx);
+ String[] names = fields.split(":");
+
+ // grab authority part and grab username and/or password
+ String authority = u.getAuthority();
+ if (authority != null && authority.contains("@")) {
+ String username = null;
+ String password = null;
+
+ // grab unserinfo part before @
+ String userInfo = authority.substring(0, authority.indexOf("@"));
+ String[] parts = userInfo.split(":");
+ if (parts.length == 2) {
+ username = parts[0];
+ password = parts[1];
+ } else {
+ // only username
+ username = userInfo;
+ }
+
+ // remember the username and/or password which we add later to the options
+ if (names.length == 2) {
+ userInfoOptions.put(names[0], username);
+ if (password != null) {
+ // password is optional
+ userInfoOptions.put(names[1], password);
+ }
+ }
+ }
+ }
+
+ // clip the scheme from the syntax
+ syntax = after(syntax, ":");
+ // clip the scheme from the uri
+ uri = after(uri, ":");
+ String uriPath = stripQuery(uri);
+
+ // strip user info from uri path
+ if (!userInfoOptions.isEmpty()) {
+ int idx = uriPath.indexOf('@');
+ if (idx > -1) {
+ uriPath = uriPath.substring(idx + 1);
+ }
+ }
+
+ // strip double slash in the start
+ if (uriPath != null && uriPath.startsWith("//")) {
+ uriPath = uriPath.substring(2);
+ }
+
+ // parse the syntax and find the names of each option
+ Matcher matcher = SYNTAX_PATTERN.matcher(syntax);
+ List<String> word = new ArrayList<String>();
+ while (matcher.find()) {
+ String s = matcher.group(1);
+ if (!scheme.equals(s)) {
+ word.add(s);
+ }
+ }
+ // parse the syntax and find each token between each option
+ String[] tokens = SYNTAX_PATTERN.split(syntax);
+
+ // find the position where each option start/end
+ List<String> word2 = new ArrayList<String>();
+ int prev = 0;
+ int prevPath = 0;
+
+ // special for activemq/jms where the enum for destinationType causes a token issue as it includes a colon
+ // for 'temp:queue' and 'temp:topic' values
+ if ("activemq".equals(scheme) || "jms".equals(scheme)) {
+ if (uriPath.startsWith("temp:")) {
+ prevPath = 5;
+ }
+ }
+
+ for (String token : tokens) {
+ if (token.isEmpty()) {
+ continue;
+ }
+
+ // special for some tokens where :// can be used also, eg http://foo
+ int idx = -1;
+ int len = 0;
+ if (":".equals(token)) {
+ idx = uriPath.indexOf("://", prevPath);
+ len = 3;
+ }
+ if (idx == -1) {
+ idx = uriPath.indexOf(token, prevPath);
+ len = token.length();
+ }
+
+ if (idx > 0) {
+ String option = uriPath.substring(prev, idx);
+ word2.add(option);
+ prev = idx + len;
+ prevPath = prev;
+ }
+ }
+ // special for last or if we did not add anyone
+ if (prev > 0 || word2.isEmpty()) {
+ String option = uriPath.substring(prev);
+ word2.add(option);
+ }
+
+ rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+ boolean defaultValueAdded = false;
+
+ // now parse the uri to know which part isw what
+ Map<String, String> options = new LinkedHashMap<String, String>();
+
+ // include the username and password from the userinfo section
+ if (!userInfoOptions.isEmpty()) {
+ options.putAll(userInfoOptions);
+ }
+
+ // word contains the syntax path elements
+ Iterator<String> it = word2.iterator();
+ for (int i = 0; i < word.size(); i++) {
+ String key = word.get(i);
+
+ boolean allOptions = word.size() == word2.size();
+ boolean required = isPropertyRequired(rows, key);
+ String defaultValue = getPropertyDefaultValue(rows, key);
+
+ // we have all options so no problem
+ if (allOptions) {
+ String value = it.next();
+ options.put(key, value);
+ } else {
+ // we have a little problem as we do not not have all options
+ if (!required) {
+ String value = null;
+
+ boolean last = i == word.size() - 1;
+ if (last) {
+ // if its the last value then use it instead of the default value
+ value = it.hasNext() ? it.next() : null;
+ if (value != null) {
+ options.put(key, value);
+ } else {
+ value = defaultValue;
+ }
+ }
+ if (value != null) {
+ options.put(key, value);
+ defaultValueAdded = true;
+ }
+ } else {
+ String value = it.hasNext() ? it.next() : null;
+ if (value != null) {
+ options.put(key, value);
+ }
+ }
+ }
+ }
+
+ Map<String, String> answer = new LinkedHashMap<String, String>();
+
+ // remove all options which are using default values and are not required
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+
+ if (defaultValueAdded) {
+ boolean required = isPropertyRequired(rows, key);
+ String defaultValue = getPropertyDefaultValue(rows, key);
+
+ if (!required && defaultValue != null) {
+ if (defaultValue.equals(value)) {
+ continue;
+ }
+ }
+ }
+
+ // we should keep this in the answer
+ answer.put(key, value);
+ }
+
+ // now parse the uri parameters
+ Map<String, Object> parameters = URISupport.parseParameters(u);
+
+ // and covert the values to String so its JMX friendly
+ while (!parameters.isEmpty()) {
+ Map.Entry<String, Object> entry = parameters.entrySet().iterator().next();
+ String key = entry.getKey();
+ String value = entry.getValue() != null ? entry.getValue().toString() : "";
+
+ boolean multiValued = isPropertyMultiValue(rows, key);
+ if (multiValued) {
+ String prefix = getPropertyPrefix(rows, key);
+ // extra all the multi valued options
+ Map<String, Object> values = URISupport.extractProperties(parameters, prefix);
+ // build a string with the extra multi valued options with the prefix and & as separator
+ CollectionStringBuffer csb = new CollectionStringBuffer("&");
+ for (Map.Entry<String, Object> multi : values.entrySet()) {
+ String line = prefix + multi.getKey() + "=" + (multi.getValue() != null ? multi.getValue().toString() : "");
+ csb.append(line);
+ }
+ // append the extra multi-values to the existing (which contains the first multi value)
+ if (!csb.isEmpty()) {
+ value = value + "&" + csb.toString();
+ }
+ }
+
+ answer.put(key, value);
+ // remove the parameter as we run in a while loop until no more parameters
+ parameters.remove(key);
+ }
+
+ return answer;
+ }
+
+ public Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException {
+ // need to normalize uri first
+
+ // parse the uri
+ URI u = normalizeUri(uri);
+ String scheme = u.getScheme();
+
+ String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+ if (json == null) {
+ throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+ }
+
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+ // now parse the uri parameters
+ Map<String, Object> parameters = URISupport.parseParameters(u);
+
+ // all the known options
+ Set<String> names = getNames(rows);
+
+ Map<String, String> answer = new LinkedHashMap<>();
+
+ // and covert the values to String so its JMX friendly
+ parameters.forEach((k, v) -> {
+ String key = k;
+ String value = v != null ? v.toString() : "";
+
+ // is the key a prefix property
+ int dot = key.indexOf('.');
+ if (dot != -1) {
+ String prefix = key.substring(0, dot + 1); // include dot in prefix
+ String option = getPropertyNameFromNameWithPrefix(rows, prefix);
+ if (option == null || !isPropertyMultiValue(rows, option)) {
+ answer.put(key, value);
+ }
+ } else if (!names.contains(key)) {
+ answer.put(key, value);
+ }
+ });
+
+ return answer;
+ }
+
+ public String endpointComponentName(String uri) {
+ if (uri != null) {
+ int idx = uri.indexOf(":");
+ if (idx > 0) {
+ return uri.substring(0, idx);
+ }
+ }
+ return null;
+ }
+
+ public String asEndpointUri(String scheme, String json, boolean encode) throws URISyntaxException {
+ return doAsEndpointUri(scheme, json, "&", encode);
+ }
+
+ public String asEndpointUriXml(String scheme, String json, boolean encode) throws URISyntaxException {
+ return doAsEndpointUri(scheme, json, "&", encode);
+ }
+
+ private String doAsEndpointUri(String scheme, String json, String ampersand, boolean encode) throws URISyntaxException {
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+ Map<String, String> copy = new HashMap<String, String>();
+ for (Map<String, String> row : rows) {
+ String name = row.get("name");
+ String required = row.get("required");
+ String value = row.get("value");
+ String defaultValue = row.get("defaultValue");
+
+ // only add if either required, or the value is != default value
+ String valueToAdd = null;
+ if ("true".equals(required)) {
+ valueToAdd = value != null ? value : defaultValue;
+ if (valueToAdd == null) {
+ valueToAdd = "";
+ }
+ } else {
+ // if we have a value and no default then add it
+ if (value != null && defaultValue == null) {
+ valueToAdd = value;
+ }
+ // otherwise only add if the value is != default value
+ if (value != null && defaultValue != null && !value.equals(defaultValue)) {
+ valueToAdd = value;
+ }
+ }
+
+ if (valueToAdd != null) {
+ copy.put(name, valueToAdd);
+ }
+ }
+
+ return doAsEndpointUri(scheme, copy, ampersand, encode);
+ }
+
+ public String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
+ return doAsEndpointUri(scheme, properties, "&", encode);
+ }
+
+ public String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
+ return doAsEndpointUri(scheme, properties, "&", encode);
+ }
+
+ String doAsEndpointUri(String scheme, Map<String, String> properties, String ampersand, boolean encode) throws URISyntaxException {
+ String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
+ if (json == null) {
+ throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
+ }
+
+ // grab the syntax
+ String syntax = null;
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("syntax")) {
+ syntax = row.get("syntax");
+ break;
+ }
+ }
+ if (syntax == null) {
+ throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
+ }
+
+ // do any properties filtering which can be needed for some special components
+ properties = filterProperties(scheme, properties);
+
+ rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+
+ // clip the scheme from the syntax
+ syntax = after(syntax, ":");
+
+ String originalSyntax = syntax;
+
+ // build at first according to syntax (use a tree map as we want the uri options sorted)
+ Map<String, String> copy = new TreeMap<String, String>();
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue() != null ? entry.getValue() : "";
+ if (syntax != null && syntax.contains(key)) {
+ syntax = syntax.replace(key, value);
+ } else {
+ copy.put(key, value);
+ }
+ }
+
+ // do we have all the options the original syntax needs (easy way)
+ String[] keys = syntaxKeys(originalSyntax);
+ boolean hasAllKeys = properties.keySet().containsAll(Arrays.asList(keys));
+
+ // build endpoint uri
+ StringBuilder sb = new StringBuilder();
+ sb.append(scheme);
+ sb.append(":");
+
+ if (hasAllKeys) {
+ // we have all the keys for the syntax so we can build the uri the easy way
+ sb.append(syntax);
+
+ if (!copy.isEmpty()) {
+ boolean hasQuestionmark = sb.toString().contains("?");
+ // the last option may already contain a ? char, if so we should use & instead of ?
+ sb.append(hasQuestionmark ? ampersand : '?');
+ String query = createQueryString(copy, ampersand, encode);
+ sb.append(query);
+ }
+ } else {
+ // TODO: revisit this and see if we can do this in another way
+ // oh darn some options is missing, so we need a complex way of building the uri
+
+ // the tokens between the options in the path
+ String[] tokens = syntax.split("\\w+");
+
+ // parse the syntax into each options
+ Matcher matcher = SYNTAX_PATTERN.matcher(originalSyntax);
+ List<String> options = new ArrayList<String>();
+ while (matcher.find()) {
+ String s = matcher.group(1);
+ options.add(s);
+ }
+
+ // need to preserve {{ and }} from the syntax
+ // (we need to use words only as its provisional placeholders)
+ syntax = syntax.replaceAll("\\{\\{", "BEGINCAMELPLACEHOLDER");
+ syntax = syntax.replaceAll("\\}\\}", "ENDCAMELPLACEHOLDER");
+
+ // parse the syntax into each options
+ Matcher matcher2 = SYNTAX_PATTERN.matcher(syntax);
+ List<String> options2 = new ArrayList<String>();
+ while (matcher2.find()) {
+ String s = matcher2.group(1);
+ s = s.replaceAll("BEGINCAMELPLACEHOLDER", "\\{\\{");
+ s = s.replaceAll("ENDCAMELPLACEHOLDER", "\\}\\}");
+ options2.add(s);
+ }
+
+ // build the endpoint
+ int range = 0;
+ boolean first = true;
+ boolean hasQuestionmark = false;
+ for (int i = 0; i < options.size(); i++) {
+ String key = options.get(i);
+ String key2 = options2.get(i);
+ String token = null;
+ if (tokens.length > i) {
+ token = tokens[i];
+ }
+
+ boolean contains = properties.containsKey(key);
+ if (!contains) {
+ // if the key are similar we have no explicit value and can try to find a default value if the option is required
+ if (isPropertyRequired(rows, key)) {
+ String value = getPropertyDefaultValue(rows, key);
+ if (value != null) {
+ properties.put(key, value);
+ key2 = value;
+ }
+ }
+ }
+
+ // was the option provided?
+ if (properties.containsKey(key)) {
+ if (!first && token != null) {
+ sb.append(token);
+ }
+ hasQuestionmark |= key.contains("?") || (token != null && token.contains("?"));
+ sb.append(key2);
+ first = false;
+ }
+ range++;
+ }
+ // append any extra options that was in surplus for the last
+ while (range < options2.size()) {
+ String token = null;
+ if (tokens.length > range) {
+ token = tokens[range];
+ }
+ String key2 = options2.get(range);
+ sb.append(token);
+ sb.append(key2);
+ hasQuestionmark |= key2.contains("?") || (token != null && token.contains("?"));
+ range++;
+ }
+
+
+ if (!copy.isEmpty()) {
+ // the last option may already contain a ? char, if so we should use & instead of ?
+ sb.append(hasQuestionmark ? ampersand : '?');
+ String query = createQueryString(copy, ampersand, encode);
+ sb.append(query);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ @Deprecated
+ private static String[] syntaxTokens(String syntax) {
+ // build tokens between the words
+ List<String> tokens = new ArrayList<>();
+ // preserve backwards behavior which had an empty token first
+ tokens.add("");
+
+ String current = "";
+ for (int i = 0; i < syntax.length(); i++) {
+ char ch = syntax.charAt(i);
+ if (Character.isLetterOrDigit(ch)) {
+ // reset for new current tokens
+ if (current.length() > 0) {
+ tokens.add(current);
+ current = "";
+ }
+ } else {
+ current += ch;
+ }
+ }
+ // anything left over?
+ if (current.length() > 0) {
+ tokens.add(current);
+ }
+
+ return tokens.toArray(new String[tokens.size()]);
+ }
+
+ private static String[] syntaxKeys(String syntax) {
+ // build tokens between the separators
+ List<String> tokens = new ArrayList<>();
+
+ String current = "";
+ for (int i = 0; i < syntax.length(); i++) {
+ char ch = syntax.charAt(i);
+ if (Character.isLetterOrDigit(ch)) {
+ current += ch;
+ } else {
+ // reset for new current tokens
+ if (current.length() > 0) {
+ tokens.add(current);
+ current = "";
+ }
+ }
+ }
+ // anything left over?
+ if (current.length() > 0) {
+ tokens.add(current);
+ }
+
+ return tokens.toArray(new String[tokens.size()]);
+ }
+
+ public SimpleValidationResult validateSimpleExpression(String simple) {
+ return doValidateSimple(null, simple, false);
+ }
+
+ public SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple) {
+ return doValidateSimple(classLoader, simple, false);
+ }
+
+ public SimpleValidationResult validateSimplePredicate(String simple) {
+ return doValidateSimple(null, simple, true);
+ }
+
+ public SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple) {
+ return doValidateSimple(classLoader, simple, true);
+ }
+
+ private SimpleValidationResult doValidateSimple(ClassLoader classLoader, String simple, boolean predicate) {
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+
+ // if there are {{ }}} property placeholders then we need to resolve them to something else
+ // as the simple parse cannot resolve them before parsing as we dont run the actual Camel application
+ // with property placeholders setup so we need to dummy this by replace the {{ }} to something else
+ // therefore we use an more unlikely character: {{XXX}} to ~^XXX^~
+ String resolved = simple.replaceAll("\\{\\{(.+)\\}\\}", "~^$1^~");
+
+ SimpleValidationResult answer = new SimpleValidationResult(simple);
+
+ Object instance = null;
+ Class clazz = null;
+ try {
+ clazz = classLoader.loadClass("org.apache.camel.language.simple.SimpleLanguage");
+ instance = clazz.newInstance();
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (clazz != null && instance != null) {
+ Throwable cause = null;
+ try {
+ if (predicate) {
+ instance.getClass().getMethod("createPredicate", String.class).invoke(instance, resolved);
+ } else {
+ instance.getClass().getMethod("createExpression", String.class).invoke(instance, resolved);
+ }
+ } catch (InvocationTargetException e) {
+ cause = e.getTargetException();
+ } catch (Exception e) {
+ cause = e;
+ }
+
+ if (cause != null) {
+
+ // reverse ~^XXX^~ back to {{XXX}}
+ String errMsg = cause.getMessage();
+ errMsg = errMsg.replaceAll("\\~\\^(.+)\\^\\~", "{{$1}}");
+
+ answer.setError(errMsg);
+
+ // is it simple parser exception then we can grab the index where the problem is
+ if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")
+ || cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleParserException")) {
+ try {
+ // we need to grab the index field from those simple parser exceptions
+ Method method = cause.getClass().getMethod("getIndex");
+ Object result = method.invoke(cause);
+ if (result != null) {
+ int index = (int) result;
+ answer.setIndex(index);
+ }
+ } catch (Throwable i) {
+ // ignore
+ }
+ }
+
+ // we need to grab the short message field from this simple syntax exception
+ if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")) {
+ try {
+ Method method = cause.getClass().getMethod("getShortMessage");
+ Object result = method.invoke(cause);
+ if (result != null) {
+ String msg = (String) result;
+ answer.setShortError(msg);
+ }
+ } catch (Throwable i) {
+ // ignore
+ }
+
+ if (answer.getShortError() == null) {
+ // fallback and try to make existing message short instead
+ String msg = answer.getError();
+ // grab everything before " at location " which would be regarded as the short message
+ int idx = msg.indexOf(" at location ");
+ if (idx > 0) {
+ msg = msg.substring(0, idx);
+ answer.setShortError(msg);
+ }
+ }
+ }
+ }
+ }
+
+ return answer;
+ }
+
+ public LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text) {
+ return doValidateLanguage(classLoader, language, text, true);
+ }
+
+ public LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text) {
+ return doValidateLanguage(classLoader, language, text, false);
+ }
+
+ private LanguageValidationResult doValidateLanguage(ClassLoader classLoader, String language, String text, boolean predicate) {
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+
+ SimpleValidationResult answer = new SimpleValidationResult(text);
+
+ String json = jsonSchemaResolver.getLanguageJSonSchema(language);
+ if (json == null) {
+ answer.setError("Unknown language " + language);
+ return answer;
+ }
+
+ List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
+ String className = null;
+ for (Map<String, String> row : rows) {
+ if (row.containsKey("javaType")) {
+ className = row.get("javaType");
+ }
+ }
+
+ if (className == null) {
+ answer.setError("Cannot find javaType for language " + language);
+ return answer;
+ }
+
+ Object instance = null;
+ Class clazz = null;
+ try {
+ clazz = classLoader.loadClass(className);
+ instance = clazz.newInstance();
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (clazz != null && instance != null) {
+ Throwable cause = null;
+ try {
+ if (predicate) {
+ instance.getClass().getMethod("createPredicate", String.class).invoke(instance, text);
+ } else {
+ instance.getClass().getMethod("createExpression", String.class).invoke(instance, text);
+ }
+ } catch (InvocationTargetException e) {
+ cause = e.getTargetException();
+ } catch (Exception e) {
+ cause = e;
+ }
+
+ if (cause != null) {
+ answer.setError(cause.getMessage());
+ }
+ }
+
+ return answer;
+ }
+
+ /**
+ * Special logic for log endpoints to deal when showAll=true
+ */
+ private Map<String, String> filterProperties(String scheme, Map<String, String> options) {
+ if ("log".equals(scheme)) {
+ String showAll = options.get("showAll");
+ if ("true".equals(showAll)) {
+ Map<String, String> filtered = new LinkedHashMap<String, String>();
+ // remove all the other showXXX options when showAll=true
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ String key = entry.getKey();
+ boolean skip = key.startsWith("show") && !key.equals("showAll");
+ if (!skip) {
+ filtered.put(key, entry.getValue());
+ }
+ }
+ return filtered;
+ }
+ }
+ // use as-is
+ return options;
+ }
+
+ private static boolean validateInteger(String value) {
+ boolean valid = false;
+ try {
+ valid = Integer.valueOf(value) != null;
+ } catch (Exception e) {
+ // ignore
+ }
+ if (!valid) {
+ // it may be a time pattern, such as 5s for 5 seconds = 5000
+ try {
+ TimePatternConverter.toMilliSeconds(value);
+ valid = true;
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ return valid;
+ }
+
+ // CHECKSTYLE:ON
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
new file mode 100644
index 0000000..d3a448c
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CamelContextJSonSchemaResolver.java
@@ -0,0 +1,80 @@
+/**
+ * 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.runtimecatalog;
+
+import java.io.IOException;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Uses runtime {@link CamelContext} to resolve the JSon schema files.
+ */
+public class CamelContextJSonSchemaResolver implements JSonSchemaResolver {
+
+ private final CamelContext camelContext;
+
+ public CamelContextJSonSchemaResolver(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ @Override
+ public String getComponentJSonSchema(String name) {
+ try {
+ return camelContext.getComponentParameterJsonSchema(name);
+ } catch (IOException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ @Override
+ public String getDataFormatJSonSchema(String name) {
+ try {
+ return camelContext.getDataFormatParameterJsonSchema(name);
+ } catch (IOException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ @Override
+ public String getLanguageJSonSchema(String name) {
+ try {
+ return camelContext.getLanguageParameterJsonSchema(name);
+ } catch (IOException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ @Override
+ public String getOtherJSonSchema(String name) {
+ // not supported
+ return null;
+ }
+
+ @Override
+ public String getModelJSonSchema(String name) {
+ try {
+ return camelContext.getEipParameterJsonSchema(name);
+ } catch (IOException e) {
+ // ignore
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
new file mode 100644
index 0000000..1b224df
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CatalogHelper.java
@@ -0,0 +1,179 @@
+/**
+ * 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.runtimecatalog;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.List;
+
+public final class CatalogHelper {
+
+ private CatalogHelper() {
+ }
+
+ /**
+ * Loads the entire stream into memory as a String and returns it.
+ * <p/>
+ * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
+ * terminator at the of the text.
+ * <p/>
+ * Warning, don't use for crazy big streams :)
+ */
+ public static void loadLines(InputStream in, List<String> lines) throws IOException {
+ try (final InputStreamReader isr = new InputStreamReader(in);
+ final BufferedReader reader = new LineNumberReader(isr)) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ }
+ }
+
+ /**
+ * Loads the entire stream into memory as a String and returns it.
+ * <p/>
+ * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
+ * terminator at the of the text.
+ * <p/>
+ * Warning, don't use for crazy big streams :)
+ */
+ public static String loadText(InputStream in) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ try (final InputStreamReader isr = new InputStreamReader(in);
+ final BufferedReader reader = new LineNumberReader(isr)) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ builder.append(line);
+ builder.append("\n");
+ }
+ return builder.toString();
+ }
+ }
+
+ /**
+ * Matches the name with the pattern.
+ *
+ * @param name the name
+ * @param pattern the pattern
+ * @return <tt>true</tt> if matched, or <tt>false</tt> if not
+ */
+ public static boolean matchWildcard(String name, String pattern) {
+ // we have wildcard support in that hence you can match with: file* to match any file endpoints
+ if (pattern.endsWith("*") && name.startsWith(pattern.substring(0, pattern.length() - 1))) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the string after the given token
+ *
+ * @param text the text
+ * @param after the token
+ * @return the text after the token, or <tt>null</tt> if text does not contain the token
+ */
+ public static String after(String text, String after) {
+ if (!text.contains(after)) {
+ return null;
+ }
+ return text.substring(text.indexOf(after) + after.length());
+ }
+
+ /**
+ * Returns the string before the given token
+ *
+ * @param text the text
+ * @param before the token
+ * @return the text before the token, or <tt>null</tt> if text does not contain the token
+ */
+ public static String before(String text, String before) {
+ if (!text.contains(before)) {
+ return null;
+ }
+ return text.substring(0, text.indexOf(before));
+ }
+
+ /**
+ * Returns the string between the given tokens
+ *
+ * @param text the text
+ * @param after the before token
+ * @param before the after token
+ * @return the text between the tokens, or <tt>null</tt> if text does not contain the tokens
+ */
+ public static String between(String text, String after, String before) {
+ text = after(text, after);
+ if (text == null) {
+ return null;
+ }
+ return before(text, before);
+ }
+
+ /**
+ * Tests whether the value is <tt>null</tt> or an empty string.
+ *
+ * @param value the value, if its a String it will be tested for text length as well
+ * @return true if empty
+ */
+ public static boolean isEmpty(Object value) {
+ return !isNotEmpty(value);
+ }
+
+ /**
+ * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
+ *
+ * @param value the value, if its a String it will be tested for text length as well
+ * @return true if <b>not</b> empty
+ */
+ public static boolean isNotEmpty(Object value) {
+ if (value == null) {
+ return false;
+ } else if (value instanceof String) {
+ String text = (String) value;
+ return text.trim().length() > 0;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Removes all leading and ending quotes (single and double) from the string
+ *
+ * @param s the string
+ * @return the string without leading and ending quotes (single and double)
+ */
+ public static String removeLeadingAndEndingQuotes(String s) {
+ if (isEmpty(s)) {
+ return s;
+ }
+
+ String copy = s.trim();
+ if (copy.startsWith("'") && copy.endsWith("'")) {
+ return copy.substring(1, copy.length() - 1);
+ }
+ if (copy.startsWith("\"") && copy.endsWith("\"")) {
+ return copy.substring(1, copy.length() - 1);
+ }
+
+ // no quotes, so return as-is
+ return s;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
new file mode 100644
index 0000000..f6484b8
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/CollectionStringBuffer.java
@@ -0,0 +1,57 @@
+/**
+ * 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.runtimecatalog;
+
+public class CollectionStringBuffer {
+ private final StringBuilder buffer = new StringBuilder();
+ private String separator;
+ private boolean first = true;
+
+ public CollectionStringBuffer() {
+ this(", ");
+ }
+
+ public CollectionStringBuffer(String separator) {
+ this.separator = separator;
+ }
+
+ @Override
+ public String toString() {
+ return buffer.toString();
+ }
+
+ public void append(Object value) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(separator);
+ }
+ buffer.append(value);
+ }
+
+ public String getSeparator() {
+ return separator;
+ }
+
+ public void setSeparator(String separator) {
+ this.separator = separator;
+ }
+
+ public boolean isEmpty() {
+ return first;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
new file mode 100644
index 0000000..7648e64
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/DefaultRuntimeCamelCatalog.java
@@ -0,0 +1,136 @@
+/**
+ * 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.runtimecatalog;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Default {@link RuntimeCamelCatalog}.
+ */
+public class DefaultRuntimeCamelCatalog extends AbstractCamelCatalog implements RuntimeCamelCatalog {
+
+ // cache of operation -> result
+ private final Map<String, Object> cache = new HashMap<String, Object>();
+ private boolean caching;
+
+ /**
+ * Creates the {@link RuntimeCamelCatalog} without caching enabled.
+ *
+ * @param camelContext the camel context
+ */
+ public DefaultRuntimeCamelCatalog(CamelContext camelContext) {
+ this(camelContext, false);
+ }
+
+ /**
+ * Creates the {@link RuntimeCamelCatalog}
+ *
+ * @param camelContext the camel context
+ * @param caching whether to use cache
+ */
+ public DefaultRuntimeCamelCatalog(CamelContext camelContext, boolean caching) {
+ this.caching = caching;
+ setJSonSchemaResolver(new CamelContextJSonSchemaResolver(camelContext));
+ }
+
+ @Override
+ public void start() throws Exception {
+ // noop
+ }
+
+ @Override
+ public void stop() throws Exception {
+ cache.clear();
+ }
+
+ @Override
+ public String modelJSonSchema(String name) {
+ String answer = null;
+ if (caching) {
+ answer = (String) cache.get("model-" + name);
+ }
+
+ if (answer == null) {
+ answer = getJSonSchemaResolver().getModelJSonSchema(name);
+ if (caching) {
+ cache.put("model-" + name, answer);
+ }
+ }
+
+ return answer;
+ }
+
+ @Override
+ public String componentJSonSchema(String name) {
+ String answer = null;
+ if (caching) {
+ answer = (String) cache.get("component-" + name);
+ }
+
+ if (answer == null) {
+ answer = getJSonSchemaResolver().getComponentJSonSchema(name);
+ if (caching) {
+ cache.put("component-" + name, answer);
+ }
+ }
+
+ return answer;
+ }
+
+ @Override
+ public String dataFormatJSonSchema(String name) {
+ String answer = null;
+ if (caching) {
+ answer = (String) cache.get("dataformat-" + name);
+ }
+
+ if (answer == null) {
+ answer = getJSonSchemaResolver().getDataFormatJSonSchema(name);
+ if (caching) {
+ cache.put("dataformat-" + name, answer);
+ }
+ }
+
+ return answer;
+ }
+
+ @Override
+ public String languageJSonSchema(String name) {
+ // if we try to look method then its in the bean.json file
+ if ("method".equals(name)) {
+ name = "bean";
+ }
+
+ String answer = null;
+ if (caching) {
+ answer = (String) cache.get("language-" + name);
+ }
+
+ if (answer == null) {
+ answer = getJSonSchemaResolver().getLanguageJSonSchema(name);
+ if (caching) {
+ cache.put("language-" + name, answer);
+ }
+ }
+
+ return answer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java b/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
new file mode 100644
index 0000000..7d1c657
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/runtimecatalog/EndpointValidationResult.java
@@ -0,0 +1,451 @@
+/**
+ * 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.runtimecatalog;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.camel.runtimecatalog.URISupport.isEmpty;
+
+/**
+ * Details result of validating endpoint uri.
+ */
+public class EndpointValidationResult implements Serializable {
+
+ private final String uri;
+ private int errors;
+
+ // general
+ private String syntaxError;
+ private String unknownComponent;
+ private String incapable;
+
+ // options
+ private Set<String> unknown;
+ private Map<String, String[]> unknownSuggestions;
+ private Set<String> lenient;
+ private Set<String> notConsumerOnly;
+ private Set<String> notProducerOnly;
+ private Set<String> required;
+ private Map<String, String> invalidEnum;
+ private Map<String, String[]> invalidEnumChoices;
+ private Map<String, String[]> invalidEnumSuggestions;
+ private Map<String, String> invalidReference;
+ private Map<String, String> invalidBoolean;
+ private Map<String, String> invalidInteger;
+ private Map<String, String> invalidNumber;
+ private Map<String, String> defaultValues;
+
+ public EndpointValidationResult() {
+ this(null);
+ }
+
+ public EndpointValidationResult(String uri) {
+ this.uri = uri;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public boolean hasErrors() {
+ return errors > 0;
+ }
+
+ public int getNumberOfErrors() {
+ return errors;
+ }
+
+ public boolean isSuccess() {
+ boolean ok = syntaxError == null && unknownComponent == null && incapable == null
+ && unknown == null && required == null;
+ if (ok) {
+ ok = notConsumerOnly == null && notProducerOnly == null;
+ }
+ if (ok) {
+ ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
+ && invalidBoolean == null && invalidInteger == null && invalidNumber == null;
+ }
+ return ok;
+ }
+
+ public void addSyntaxError(String syntaxError) {
+ this.syntaxError = syntaxError;
+ errors++;
+ }
+
+ public void addIncapable(String uri) {
+ this.incapable = uri;
+ errors++;
+ }
+
+ public void addUnknownComponent(String name) {
+ this.unknownComponent = name;
+ errors++;
+ }
+
+ public void addUnknown(String name) {
+ if (unknown == null) {
+ unknown = new LinkedHashSet<String>();
+ }
+ if (!unknown.contains(name)) {
+ unknown.add(name);
+ errors++;
+ }
+ }
+
+ public void addUnknownSuggestions(String name, String[] suggestions) {
+ if (unknownSuggestions == null) {
+ unknownSuggestions = new LinkedHashMap<String, String[]>();
+ }
+ unknownSuggestions.put(name, suggestions);
+ }
+
+ public void addLenient(String name) {
+ if (lenient == null) {
+ lenient = new LinkedHashSet<String>();
+ }
+ if (!lenient.contains(name)) {
+ lenient.add(name);
+ }
+ }
+
+ public void addRequired(String name) {
+ if (required == null) {
+ required = new LinkedHashSet<String>();
+ }
+ if (!required.contains(name)) {
+ required.add(name);
+ errors++;
+ }
+ }
+
+ public void addInvalidEnum(String name, String value) {
+ if (invalidEnum == null) {
+ invalidEnum = new LinkedHashMap<String, String>();
+ }
+ if (!invalidEnum.containsKey(name)) {
+ invalidEnum.put(name, value);
+ errors++;
+ }
+ }
+
+ public void addInvalidEnumChoices(String name, String[] choices) {
+ if (invalidEnumChoices == null) {
+ invalidEnumChoices = new LinkedHashMap<String, String[]>();
+ }
+ invalidEnumChoices.put(name, choices);
+ }
+
+ public void addInvalidEnumSuggestions(String name, String[] suggestions) {
+ if (invalidEnumSuggestions == null) {
+ invalidEnumSuggestions = new LinkedHashMap<String, String[]>();
+ }
+ invalidEnumSuggestions.put(name, suggestions);
+ }
+
+ public void addInvalidReference(String name, String value) {
+ if (invalidReference == null) {
+ invalidReference = new LinkedHashMap<String, String>();
+ }
+ if (!invalidReference.containsKey(name)) {
+ invalidReference.put(name, value);
+ errors++;
+ }
+ }
+
+ public void addInvalidBoolean(String name, String value) {
+ if (invalidBoolean == null) {
+ invalidBoolean = new LinkedHashMap<String, String>();
+ }
+ if (!invalidBoolean.containsKey(name)) {
+ invalidBoolean.put(name, value);
+ errors++;
+ }
+ }
+
+ public void addInvalidInteger(String name, String value) {
+ if (invalidInteger == null) {
+ invalidInteger = new LinkedHashMap<String, String>();
+ }
+ if (!invalidInteger.containsKey(name)) {
+ invalidInteger.put(name, value);
+ errors++;
+ }
+ }
+
+ public void addInvalidNumber(String name, String value) {
+ if (invalidNumber == null) {
+ invalidNumber = new LinkedHashMap<String, String>();
+ }
+ if (!invalidNumber.containsKey(name)) {
+ invalidNumber.put(name, value);
+ errors++;
+ }
+ }
+
+ public void addDefaultValue(String name, String value) {
+ if (defaultValues == null) {
+ defaultValues = new LinkedHashMap<String, String>();
+ }
+ defaultValues.put(name, value);
+ }
+
+ public void addNotConsumerOnly(String name) {
+ if (notConsumerOnly == null) {
+ notConsumerOnly = new LinkedHashSet<String>();
+ }
+ if (!notConsumerOnly.contains(name)) {
+ notConsumerOnly.add(name);
+ errors++;
+ }
+ }
+
+ public void addNotProducerOnly(String name) {
+ if (notProducerOnly == null) {
+ notProducerOnly = new LinkedHashSet<String>();
+ }
+ if (!notProducerOnly.contains(name)) {
+ notProducerOnly.add(name);
+ errors++;
+ }
+ }
+
+ public String getSyntaxError() {
+ return syntaxError;
+ }
+
+ public String getIncapable() {
+ return incapable;
+ }
+
+ public Set<String> getUnknown() {
+ return unknown;
+ }
+
+ public Set<String> getLenient() {
+ return lenient;
+ }
+
+ public Map<String, String[]> getUnknownSuggestions() {
+ return unknownSuggestions;
+ }
+
+ public String getUnknownComponent() {
+ return unknownComponent;
+ }
+
+ public Set<String> getRequired() {
+ return required;
+ }
+
+ public Map<String, String> getInvalidEnum() {
+ return invalidEnum;
+ }
+
+ public Map<String, String[]> getInvalidEnumChoices() {
+ return invalidEnumChoices;
+ }
+
+ public List<String> getEnumChoices(String optionName) {
+ if (invalidEnumChoices != null) {
+ String[] enums = invalidEnumChoices.get(optionName);
+ if (enums != null) {
+ return Arrays.asList(enums);
+ }
+ }
+
+ return Collections.emptyList();
+ }
+
+ public Map<String, String> getInvalidReference() {
+ return invalidReference;
+ }
+
+ public Map<String, String> getInvalidBoolean() {
+ return invalidBoolean;
+ }
+
+ public Map<String, String> getInvalidInteger() {
+ return invalidInteger;
+ }
+
+ public Map<String, String> getInvalidNumber() {
+ return invalidNumber;
+ }
+
+ public Map<String, String> getDefaultValues() {
+ return defaultValues;
+ }
+
+ public Set<String> getNotConsumerOnly() {
+ return notConsumerOnly;
+ }
+
+ public Set<String> getNotProducerOnly() {
+ return notProducerOnly;
+ }
+
+ /**
+ * A human readable summary of the validation errors.
+ *
+ * @param includeHeader whether to include a header
+ * @return the summary, or <tt>null</tt> if no validation errors
+ */
+ public String summaryErrorMessage(boolean includeHeader) {
+ if (isSuccess()) {
+ return null;
+ }
+
+ if (incapable != null) {
+ return "\tIncapable of parsing uri: " + incapable;
+ } else if (syntaxError != null) {
+ return "\tSyntax error: " + syntaxError;
+ } else if (unknownComponent != null) {
+ return "\tUnknown component: " + unknownComponent;
+ }
+
+ // for each invalid option build a reason message
+ Map<String, String> options = new LinkedHashMap<String, String>();
+ if (unknown != null) {
+ for (String name : unknown) {
+ if (unknownSuggestions != null && unknownSuggestions.containsKey(name)) {
+ String[] suggestions = unknownSuggestions.get(name);
+ if (suggestions != null && suggestions.length > 0) {
+ String str = Arrays.asList(suggestions).toString();
+ options.put(name, "Unknown option. Did you mean: " + str);
+ } else {
+ options.put(name, "Unknown option");
+ }
+ } else {
+ options.put(name, "Unknown option");
+ }
+ }
+ }
+ if (notConsumerOnly != null) {
+ for (String name : notConsumerOnly) {
+ options.put(name, "Option not applicable in consumer only mode");
+ }
+ }
+ if (notProducerOnly != null) {
+ for (String name : notProducerOnly) {
+ options.put(name, "Option not applicable in producer only mode");
+ }
+ }
+ if (required != null) {
+ for (String name : required) {
+ options.put(name, "Missing required option");
+ }
+ }
+ if (invalidEnum != null) {
+ for (Map.Entry<String, String> entry : invalidEnum.entrySet()) {
+ String name = entry.getKey();
+ String[] choices = invalidEnumChoices.get(name);
+ String defaultValue = defaultValues != null ? defaultValues.get(entry.getKey()) : null;
+ String str = Arrays.asList(choices).toString();
+ String msg = "Invalid enum value: " + entry.getValue() + ". Possible values: " + str;
+ if (invalidEnumSuggestions != null) {
+ String[] suggestions = invalidEnumSuggestions.get(name);
+ if (suggestions != null && suggestions.length > 0) {
+ str = Arrays.asList(suggestions).toString();
+ msg += ". Did you mean: " + str;
+ }
+ }
+ if (defaultValue != null) {
+ msg += ". Default value: " + defaultValue;
+ }
+
+ options.put(entry.getKey(), msg);
+ }
+ }
+ if (invalidReference != null) {
+ for (Map.Entry<String, String> entry : invalidReference.entrySet()) {
+ boolean empty = isEmpty(entry.getValue());
+ if (empty) {
+ options.put(entry.getKey(), "Empty reference value");
+ } else if (!entry.getValue().startsWith("#")) {
+ options.put(entry.getKey(), "Invalid reference value: " + entry.getValue() + " must start with #");
+ } else {
+ options.put(entry.getKey(), "Invalid reference value: " + entry.getValue());
+ }
+ }
+ }
+ if (invalidBoolean != null) {
+ for (Map.Entry<String, String> entry : invalidBoolean.entrySet()) {
+ boolean empty = isEmpty(entry.getValue());
+ if (empty) {
+ options.put(entry.getKey(), "Empty boolean value");
+ } else {
+ options.put(entry.getKey(), "Invalid boolean value: " + entry.getValue());
+ }
+ }
+ }
+ if (invalidInteger != null) {
+ for (Map.Entry<String, String> entry : invalidInteger.entrySet()) {
+ boolean empty = isEmpty(entry.getValue());
+ if (empty) {
+ options.put(entry.getKey(), "Empty integer value");
+ } else {
+ options.put(entry.getKey(), "Invalid integer value: " + entry.getValue());
+ }
+ }
+ }
+ if (invalidNumber != null) {
+ for (Map.Entry<String, String> entry : invalidNumber.entrySet()) {
+ boolean empty = isEmpty(entry.getValue());
+ if (empty) {
+ options.put(entry.getKey(), "Empty number value");
+ } else {
+ options.put(entry.getKey(), "Invalid number value: " + entry.getValue());
+ }
+ }
+ }
+
+ // build a table with the error summary nicely formatted
+ // lets use 24 as min length
+ int maxLen = 24;
+ for (String key : options.keySet()) {
+ maxLen = Math.max(maxLen, key.length());
+ }
+ String format = "%" + maxLen + "s %s";
+
+ // build the human error summary
+ StringBuilder sb = new StringBuilder();
+ if (includeHeader) {
+ sb.append("Endpoint validator error\n");
+ sb.append("---------------------------------------------------------------------------------------------------------------------------------------\n");
+ sb.append("\n");
+ }
+ if (uri != null) {
+ sb.append("\t").append(uri).append("\n");
+ } else {
+ sb.append("\n");
+ }
+ for (Map.Entry<String, String> option : options.entrySet()) {
+ String out = String.format(format, option.getKey(), option.getValue());
+ sb.append("\n\t").append(out);
+ }
+
+ return sb.toString();
+ }
+}
[5/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
deleted file mode 100644
index 9bb98f0..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/EndpointValidationResult.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.camel.catalog.URISupport.isEmpty;
-
-/**
- * Details result of validating endpoint uri.
- */
-public class EndpointValidationResult implements Serializable {
-
- private final String uri;
- private int errors;
-
- // general
- private String syntaxError;
- private String unknownComponent;
- private String incapable;
-
- // options
- private Set<String> unknown;
- private Map<String, String[]> unknownSuggestions;
- private Set<String> lenient;
- private Set<String> notConsumerOnly;
- private Set<String> notProducerOnly;
- private Set<String> required;
- private Map<String, String> invalidEnum;
- private Map<String, String[]> invalidEnumChoices;
- private Map<String, String[]> invalidEnumSuggestions;
- private Map<String, String> invalidReference;
- private Map<String, String> invalidBoolean;
- private Map<String, String> invalidInteger;
- private Map<String, String> invalidNumber;
- private Map<String, String> defaultValues;
-
- public EndpointValidationResult() {
- this(null);
- }
-
- public EndpointValidationResult(String uri) {
- this.uri = uri;
- }
-
- public String getUri() {
- return uri;
- }
-
- public boolean hasErrors() {
- return errors > 0;
- }
-
- public int getNumberOfErrors() {
- return errors;
- }
-
- public boolean isSuccess() {
- boolean ok = syntaxError == null && unknownComponent == null && incapable == null
- && unknown == null && required == null;
- if (ok) {
- ok = notConsumerOnly == null && notProducerOnly == null;
- }
- if (ok) {
- ok = invalidEnum == null && invalidEnumChoices == null && invalidReference == null
- && invalidBoolean == null && invalidInteger == null && invalidNumber == null;
- }
- return ok;
- }
-
- public void addSyntaxError(String syntaxError) {
- this.syntaxError = syntaxError;
- errors++;
- }
-
- public void addIncapable(String uri) {
- this.incapable = uri;
- errors++;
- }
-
- public void addUnknownComponent(String name) {
- this.unknownComponent = name;
- errors++;
- }
-
- public void addUnknown(String name) {
- if (unknown == null) {
- unknown = new LinkedHashSet<String>();
- }
- if (!unknown.contains(name)) {
- unknown.add(name);
- errors++;
- }
- }
-
- public void addUnknownSuggestions(String name, String[] suggestions) {
- if (unknownSuggestions == null) {
- unknownSuggestions = new LinkedHashMap<String, String[]>();
- }
- unknownSuggestions.put(name, suggestions);
- }
-
- public void addLenient(String name) {
- if (lenient == null) {
- lenient = new LinkedHashSet<String>();
- }
- if (!lenient.contains(name)) {
- lenient.add(name);
- }
- }
-
- public void addRequired(String name) {
- if (required == null) {
- required = new LinkedHashSet<String>();
- }
- if (!required.contains(name)) {
- required.add(name);
- errors++;
- }
- }
-
- public void addInvalidEnum(String name, String value) {
- if (invalidEnum == null) {
- invalidEnum = new LinkedHashMap<String, String>();
- }
- if (!invalidEnum.containsKey(name)) {
- invalidEnum.put(name, value);
- errors++;
- }
- }
-
- public void addInvalidEnumChoices(String name, String[] choices) {
- if (invalidEnumChoices == null) {
- invalidEnumChoices = new LinkedHashMap<String, String[]>();
- }
- invalidEnumChoices.put(name, choices);
- }
-
- public void addInvalidEnumSuggestions(String name, String[] suggestions) {
- if (invalidEnumSuggestions == null) {
- invalidEnumSuggestions = new LinkedHashMap<String, String[]>();
- }
- invalidEnumSuggestions.put(name, suggestions);
- }
-
- public void addInvalidReference(String name, String value) {
- if (invalidReference == null) {
- invalidReference = new LinkedHashMap<String, String>();
- }
- if (!invalidReference.containsKey(name)) {
- invalidReference.put(name, value);
- errors++;
- }
- }
-
- public void addInvalidBoolean(String name, String value) {
- if (invalidBoolean == null) {
- invalidBoolean = new LinkedHashMap<String, String>();
- }
- if (!invalidBoolean.containsKey(name)) {
- invalidBoolean.put(name, value);
- errors++;
- }
- }
-
- public void addInvalidInteger(String name, String value) {
- if (invalidInteger == null) {
- invalidInteger = new LinkedHashMap<String, String>();
- }
- if (!invalidInteger.containsKey(name)) {
- invalidInteger.put(name, value);
- errors++;
- }
- }
-
- public void addInvalidNumber(String name, String value) {
- if (invalidNumber == null) {
- invalidNumber = new LinkedHashMap<String, String>();
- }
- if (!invalidNumber.containsKey(name)) {
- invalidNumber.put(name, value);
- errors++;
- }
- }
-
- public void addDefaultValue(String name, String value) {
- if (defaultValues == null) {
- defaultValues = new LinkedHashMap<String, String>();
- }
- defaultValues.put(name, value);
- }
-
- public void addNotConsumerOnly(String name) {
- if (notConsumerOnly == null) {
- notConsumerOnly = new LinkedHashSet<String>();
- }
- if (!notConsumerOnly.contains(name)) {
- notConsumerOnly.add(name);
- errors++;
- }
- }
-
- public void addNotProducerOnly(String name) {
- if (notProducerOnly == null) {
- notProducerOnly = new LinkedHashSet<String>();
- }
- if (!notProducerOnly.contains(name)) {
- notProducerOnly.add(name);
- errors++;
- }
- }
-
- public String getSyntaxError() {
- return syntaxError;
- }
-
- public String getIncapable() {
- return incapable;
- }
-
- public Set<String> getUnknown() {
- return unknown;
- }
-
- public Set<String> getLenient() {
- return lenient;
- }
-
- public Map<String, String[]> getUnknownSuggestions() {
- return unknownSuggestions;
- }
-
- public String getUnknownComponent() {
- return unknownComponent;
- }
-
- public Set<String> getRequired() {
- return required;
- }
-
- public Map<String, String> getInvalidEnum() {
- return invalidEnum;
- }
-
- public Map<String, String[]> getInvalidEnumChoices() {
- return invalidEnumChoices;
- }
-
- public List<String> getEnumChoices(String optionName) {
- if (invalidEnumChoices != null) {
- String[] enums = invalidEnumChoices.get(optionName);
- if (enums != null) {
- return Arrays.asList(enums);
- }
- }
-
- return Collections.emptyList();
- }
-
- public Map<String, String> getInvalidReference() {
- return invalidReference;
- }
-
- public Map<String, String> getInvalidBoolean() {
- return invalidBoolean;
- }
-
- public Map<String, String> getInvalidInteger() {
- return invalidInteger;
- }
-
- public Map<String, String> getInvalidNumber() {
- return invalidNumber;
- }
-
- public Map<String, String> getDefaultValues() {
- return defaultValues;
- }
-
- public Set<String> getNotConsumerOnly() {
- return notConsumerOnly;
- }
-
- public Set<String> getNotProducerOnly() {
- return notProducerOnly;
- }
-
- /**
- * A human readable summary of the validation errors.
- *
- * @param includeHeader whether to include a header
- * @return the summary, or <tt>null</tt> if no validation errors
- */
- public String summaryErrorMessage(boolean includeHeader) {
- if (isSuccess()) {
- return null;
- }
-
- if (incapable != null) {
- return "\tIncapable of parsing uri: " + incapable;
- } else if (syntaxError != null) {
- return "\tSyntax error: " + syntaxError;
- } else if (unknownComponent != null) {
- return "\tUnknown component: " + unknownComponent;
- }
-
- // for each invalid option build a reason message
- Map<String, String> options = new LinkedHashMap<String, String>();
- if (unknown != null) {
- for (String name : unknown) {
- if (unknownSuggestions != null && unknownSuggestions.containsKey(name)) {
- String[] suggestions = unknownSuggestions.get(name);
- if (suggestions != null && suggestions.length > 0) {
- String str = Arrays.asList(suggestions).toString();
- options.put(name, "Unknown option. Did you mean: " + str);
- } else {
- options.put(name, "Unknown option");
- }
- } else {
- options.put(name, "Unknown option");
- }
- }
- }
- if (notConsumerOnly != null) {
- for (String name : notConsumerOnly) {
- options.put(name, "Option not applicable in consumer only mode");
- }
- }
- if (notProducerOnly != null) {
- for (String name : notProducerOnly) {
- options.put(name, "Option not applicable in producer only mode");
- }
- }
- if (required != null) {
- for (String name : required) {
- options.put(name, "Missing required option");
- }
- }
- if (invalidEnum != null) {
- for (Map.Entry<String, String> entry : invalidEnum.entrySet()) {
- String name = entry.getKey();
- String[] choices = invalidEnumChoices.get(name);
- String defaultValue = defaultValues != null ? defaultValues.get(entry.getKey()) : null;
- String str = Arrays.asList(choices).toString();
- String msg = "Invalid enum value: " + entry.getValue() + ". Possible values: " + str;
- if (invalidEnumSuggestions != null) {
- String[] suggestions = invalidEnumSuggestions.get(name);
- if (suggestions != null && suggestions.length > 0) {
- str = Arrays.asList(suggestions).toString();
- msg += ". Did you mean: " + str;
- }
- }
- if (defaultValue != null) {
- msg += ". Default value: " + defaultValue;
- }
-
- options.put(entry.getKey(), msg);
- }
- }
- if (invalidReference != null) {
- for (Map.Entry<String, String> entry : invalidReference.entrySet()) {
- boolean empty = isEmpty(entry.getValue());
- if (empty) {
- options.put(entry.getKey(), "Empty reference value");
- } else if (!entry.getValue().startsWith("#")) {
- options.put(entry.getKey(), "Invalid reference value: " + entry.getValue() + " must start with #");
- } else {
- options.put(entry.getKey(), "Invalid reference value: " + entry.getValue());
- }
- }
- }
- if (invalidBoolean != null) {
- for (Map.Entry<String, String> entry : invalidBoolean.entrySet()) {
- boolean empty = isEmpty(entry.getValue());
- if (empty) {
- options.put(entry.getKey(), "Empty boolean value");
- } else {
- options.put(entry.getKey(), "Invalid boolean value: " + entry.getValue());
- }
- }
- }
- if (invalidInteger != null) {
- for (Map.Entry<String, String> entry : invalidInteger.entrySet()) {
- boolean empty = isEmpty(entry.getValue());
- if (empty) {
- options.put(entry.getKey(), "Empty integer value");
- } else {
- options.put(entry.getKey(), "Invalid integer value: " + entry.getValue());
- }
- }
- }
- if (invalidNumber != null) {
- for (Map.Entry<String, String> entry : invalidNumber.entrySet()) {
- boolean empty = isEmpty(entry.getValue());
- if (empty) {
- options.put(entry.getKey(), "Empty number value");
- } else {
- options.put(entry.getKey(), "Invalid number value: " + entry.getValue());
- }
- }
- }
-
- // build a table with the error summary nicely formatted
- // lets use 24 as min length
- int maxLen = 24;
- for (String key : options.keySet()) {
- maxLen = Math.max(maxLen, key.length());
- }
- String format = "%" + maxLen + "s %s";
-
- // build the human error summary
- StringBuilder sb = new StringBuilder();
- if (includeHeader) {
- sb.append("Endpoint validator error\n");
- sb.append("---------------------------------------------------------------------------------------------------------------------------------------\n");
- sb.append("\n");
- }
- if (uri != null) {
- sb.append("\t").append(uri).append("\n");
- } else {
- sb.append("\n");
- }
- for (Map.Entry<String, String> option : options.entrySet()) {
- String out = String.format(format, option.getKey(), option.getValue());
- sb.append("\n\t").append(out);
- }
-
- return sb.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java b/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
deleted file mode 100644
index 774facd..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaHelper.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public final class JSonSchemaHelper {
-
- // 0 = text, 1 = enum, 2 = boolean, 3 = integer or number
- private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
- private static final String QUOT = """;
-
- private JSonSchemaHelper() {
- }
-
- /**
- * Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
- *
- * @param group the group to parse from such as <tt>component</tt>, <tt>componentProperties</tt>, or <tt>properties</tt>.
- * @param json the json
- * @return a list of all the rows, where each row is a set of key value pairs with metadata
- */
- public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
- List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
- if (json == null) {
- return answer;
- }
-
- boolean found = false;
-
- // parse line by line
- String[] lines = json.split("\n");
- for (String line : lines) {
- // we need to find the group first
- if (!found) {
- String s = line.trim();
- found = s.startsWith("\"" + group + "\":") && s.endsWith("{");
- continue;
- }
-
- // we should stop when we end the group
- if (line.equals(" },") || line.equals(" }")) {
- break;
- }
-
- // need to safe encode \" so we can parse the line
- line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');
-
- Map<String, String> row = new LinkedHashMap<String, String>();
- Matcher matcher = PATTERN.matcher(line);
-
- String key;
- if (parseProperties) {
- // when parsing properties the first key is given as name, so the first parsed token is the value of the name
- key = "name";
- } else {
- key = null;
- }
- while (matcher.find()) {
- if (key == null) {
- key = matcher.group(1);
- } else {
- String value = matcher.group(1);
- if (value != null) {
- // its text based
- value = value.trim();
- // decode
- value = value.replaceAll(QUOT, "\"");
- value = decodeJson(value);
- }
- if (value == null) {
- // not text then its maybe an enum?
- value = matcher.group(2);
- if (value != null) {
- // its an enum so strip out " and trim spaces after comma
- value = value.replaceAll("\"", "");
- value = value.replaceAll(", ", ",");
- value = value.trim();
- }
- }
- if (value == null) {
- // not text then its maybe a boolean?
- value = matcher.group(3);
- }
- if (value == null) {
- // not text then its maybe a integer?
- value = matcher.group(4);
- }
- if (value != null) {
- row.put(key, value);
- }
- // reset
- key = null;
- }
- }
- if (!row.isEmpty()) {
- answer.add(row);
- }
- }
-
- return answer;
- }
-
- private static String decodeJson(String value) {
- // json encodes a \ as \\ so we need to decode from \\ back to \
- if ("\\\\".equals(value)) {
- value = "\\";
- }
- return value;
- }
-
- public static boolean isComponentLenientProperties(List<Map<String, String>> rows) {
- for (Map<String, String> row : rows) {
- if (row.containsKey("lenientProperties")) {
- return "true".equals(row.get("lenientProperties"));
- }
- }
- return false;
- }
-
- public static boolean isComponentConsumerOnly(List<Map<String, String>> rows) {
- for (Map<String, String> row : rows) {
- if (row.containsKey("consumerOnly")) {
- return "true".equals(row.get("consumerOnly"));
- }
- }
- return false;
- }
-
- public static boolean isComponentProducerOnly(List<Map<String, String>> rows) {
- for (Map<String, String> row : rows) {
- if (row.containsKey("producerOnly")) {
- return "true".equals(row.get("producerOnly"));
- }
- }
- return false;
- }
-
- public static boolean isPropertyConsumerOnly(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String labels = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("label")) {
- labels = row.get("label");
- }
- if (found) {
- return labels != null && labels.contains("consumer");
- }
- }
- return false;
- }
-
- public static boolean isPropertyProducerOnly(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String labels = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("label")) {
- labels = row.get("label");
- }
- if (found) {
- return labels != null && labels.contains("producer");
- }
- }
- return false;
- }
-
- public static boolean isPropertyRequired(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- boolean required = false;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("required")) {
- required = "true".equals(row.get("required"));
- }
- if (found) {
- return required;
- }
- }
- return false;
- }
-
- public static String getPropertyKind(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String kind = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("kind")) {
- kind = row.get("kind");
- }
- if (found) {
- return kind;
- }
- }
- return null;
- }
-
- public static boolean isPropertyBoolean(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String type = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("type")) {
- type = row.get("type");
- }
- if (found) {
- return "boolean".equals(type);
- }
- }
- return false;
- }
-
- public static boolean isPropertyInteger(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String type = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("type")) {
- type = row.get("type");
- }
- if (found) {
- return "integer".equals(type);
- }
- }
- return false;
- }
-
- public static boolean isPropertyNumber(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String type = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("type")) {
- type = row.get("type");
- }
- if (found) {
- return "number".equals(type);
- }
- }
- return false;
- }
-
- public static boolean isPropertyObject(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String type = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("type")) {
- type = row.get("type");
- }
- if (found) {
- return "object".equals(type);
- }
- }
- return false;
- }
-
- public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String defaultValue = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("defaultValue")) {
- defaultValue = row.get("defaultValue");
- }
- if (found) {
- return defaultValue;
- }
- }
- return null;
- }
-
- public static String stripOptionalPrefixFromName(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String optionalPrefix = null;
- boolean found = false;
- if (row.containsKey("optionalPrefix")) {
- optionalPrefix = row.get("optionalPrefix");
- }
- if (row.containsKey("name")) {
- if (optionalPrefix != null && name.startsWith(optionalPrefix)) {
- name = name.substring(optionalPrefix.length());
- // try again
- return stripOptionalPrefixFromName(rows, name);
- } else {
- found = name.equals(row.get("name"));
- }
- }
- if (found) {
- return name;
- }
- }
- return name;
- }
-
- public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String enums = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("enum")) {
- enums = row.get("enum");
- }
- if (found) {
- return enums;
- }
- }
- return null;
- }
-
- public static String getPropertyPrefix(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String prefix = null;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("prefix")) {
- prefix = row.get("prefix");
- }
- if (found) {
- return prefix;
- }
- }
- return null;
- }
-
- public static boolean isPropertyMultiValue(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- boolean multiValue = false;
- boolean found = false;
- if (row.containsKey("name")) {
- found = name.equals(row.get("name"));
- }
- if (row.containsKey("multiValue")) {
- multiValue = "true".equals(row.get("multiValue"));
- }
- if (found) {
- return multiValue;
- }
- }
- return false;
- }
-
- public static String getPropertyNameFromNameWithPrefix(List<Map<String, String>> rows, String name) {
- for (Map<String, String> row : rows) {
- String propertyName = null;
- boolean found = false;
- if (row.containsKey("name")) {
- propertyName = row.get("name");
- }
- if (row.containsKey("prefix")) {
- String preifx = row.get("prefix");
- found = name.startsWith(preifx);
- }
- if (found) {
- return propertyName;
- }
- }
- return null;
- }
-
- public static Map<String, String> getRow(List<Map<String, String>> rows, String key) {
- for (Map<String, String> row : rows) {
- if (key.equals(row.get("name"))) {
- return row;
- }
- }
- return null;
- }
-
- public static Set<String> getNames(List<Map<String, String>> rows) {
- Set<String> answer = new LinkedHashSet<String>();
- for (Map<String, String> row : rows) {
- if (row.containsKey("name")) {
- answer.add(row.get("name"));
- }
- }
- return answer;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
deleted file mode 100644
index 9bf09cc..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * 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.catalog;
-
-/**
- * Pluggable resolver to load JSon schema files for components, data formats, languages etc.
- */
-public interface JSonSchemaResolver {
-
- /**
- * Returns the component information as JSon format.
- *
- * @param name the component name
- * @return component details in JSon
- */
- String getComponentJSonSchema(String name);
-
- /**
- * Returns the data format information as JSon format.
- *
- * @param name the data format name
- * @return data format details in JSon
- */
- String getDataFormatJSonSchema(String name);
-
- /**
- * Returns the language information as JSon format.
- *
- * @param name the language name
- * @return language details in JSon
- */
- String getLanguageJSonSchema(String name);
-
- /**
- * Returns the other (miscellaneous) information as JSon format.
- *
- * @param name the other (miscellaneous) name
- * @return other (miscellaneous) details in JSon
- */
- String getOtherJSonSchema(String name);
-
- /**
- * Returns the model information as JSon format.
- *
- * @param name the model name
- * @return model details in JSon
- */
- String getModelJSonSchema(String name);
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
deleted file mode 100644
index 4a977eb..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/LanguageValidationResult.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.Serializable;
-
-/**
- * Validation result of parsing a language expression or predicate
- */
-public class LanguageValidationResult implements Serializable {
- private final String text;
- private String error;
- private String shortError;
- private int index;
-
- public LanguageValidationResult(String text) {
- this.text = text;
- }
-
- public String getText() {
- return text;
- }
-
- public boolean isSuccess() {
- return error == null;
- }
-
- public void setError(String error) {
- this.error = error;
- }
-
- public String getError() {
- return error;
- }
-
- public String getShortError() {
- return shortError;
- }
-
- public void setShortError(String shortError) {
- this.shortError = shortError;
- }
-
- public int getIndex() {
- return index;
- }
-
- public void setIndex(int index) {
- this.index = index;
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
deleted file mode 100644
index b46edab..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/RuntimeCamelCatalog.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * 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.catalog;
-
-import java.net.URISyntaxException;
-import java.util.Map;
-
-import org.apache.camel.StaticService;
-
-/**
- * Runtime based CamelCatalog which are included in camel-core that can provided limit CamelCatalog capabilities
- */
-public interface RuntimeCamelCatalog extends StaticService {
-
- /**
- * Returns the component information as JSon format.
- *
- * @param name the component name
- * @return component details in JSon
- */
- String componentJSonSchema(String name);
-
- /**
- * Returns the data format information as JSon format.
- *
- * @param name the data format name
- * @return data format details in JSon
- */
- String dataFormatJSonSchema(String name);
-
- /**
- * Returns the language information as JSon format.
- *
- * @param name the language name
- * @return language details in JSon
- */
- String languageJSonSchema(String name);
-
- /**
- * Returns the model information as JSon format.
- *
- * @param name the model name
- * @return model details in JSon
- */
- String modelJSonSchema(String name);
-
- /**
- * Parses the endpoint uri and constructs a key/value properties of each option
- *
- * @param uri the endpoint uri
- * @return properties as key value pairs of each endpoint option
- */
- Map<String, String> endpointProperties(String uri) throws URISyntaxException;
-
- /**
- * Parses the endpoint uri and constructs a key/value properties of only the lenient properties (eg custom options)
- * <p/>
- * For example using the HTTP components to provide query parameters in the endpoint uri.
- *
- * @param uri the endpoint uri
- * @return properties as key value pairs of each lenient properties
- */
- Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException;
-
- /**
- * Validates the pattern whether its a valid time pattern.
- *
- * @param pattern the pattern such as 5000, 5s, 5sec, 4min, 4m30s, 1h, etc.
- * @return <tt>true</tt> if valid, <tt>false</tt> if invalid
- */
- boolean validateTimePattern(String pattern);
-
- /**
- * Validates the properties for the given scheme against component and endpoint
- *
- * @param scheme the endpoint scheme
- * @param properties the endpoint properties
- * @return validation result
- */
- EndpointValidationResult validateProperties(String scheme, Map<String, String> properties);
-
- /**
- * Parses and validates the endpoint uri and constructs a key/value properties of each option.
- *
- * @param uri the endpoint uri
- * @return validation result
- */
- EndpointValidationResult validateEndpointProperties(String uri);
-
- /**
- * Parses and validates the endpoint uri and constructs a key/value properties of each option.
- * <p/>
- * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
- * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
- * but in the uri because of using lenient properties.
- * For example using the HTTP components to provide query parameters in the endpoint uri.
- *
- * @param uri the endpoint uri
- * @param ignoreLenientProperties whether to ignore components that uses lenient properties.
- * @return validation result
- */
- EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties);
-
- /**
- * Parses and validates the endpoint uri and constructs a key/value properties of each option.
- * <p/>
- * The option ignoreLenientProperties can be used to ignore components that uses lenient properties.
- * When this is true, then the uri validation is stricter but would fail on properties that are not part of the component
- * but in the uri because of using lenient properties.
- * For example using the HTTP components to provide query parameters in the endpoint uri.
- *
- * @param uri the endpoint uri
- * @param ignoreLenientProperties whether to ignore components that uses lenient properties.
- * @param consumerOnly whether the endpoint is only used as a consumer
- * @param producerOnly whether the endpoint is only used as a producer
- * @return validation result
- */
- EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly);
-
- /**
- * Parses and validates the simple expression.
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
- *
- * @param simple the simple expression
- * @return validation result
- * @deprecated use {@link #validateSimpleExpression(ClassLoader, String)}
- */
- @Deprecated
- SimpleValidationResult validateSimpleExpression(String simple);
-
- /**
- * Parses and validates the simple expression.
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
- *
- * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
- * @param simple the simple expression
- * @return validation result
- */
- SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple);
-
- /**
- * Parses and validates the simple predicate
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
- *
- * @param simple the simple predicate
- * @return validation result
- * @deprecated use {@link #validateSimplePredicate(ClassLoader, String)}
- */
- @Deprecated
- SimpleValidationResult validateSimplePredicate(String simple);
-
- /**
- * Parses and validates the simple predicate
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> on the classpath
- *
- * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
- * @param simple the simple predicate
- * @return validation result
- */
- SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple);
-
- /**
- * Parses and validates the language as a predicate
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
- *
- * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
- * @param language the name of the language
- * @param text the predicate text
- * @return validation result
- */
- LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text);
-
- /**
- * Parses and validates the language as an expression
- * <p/>
- * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
- *
- * @param classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for using default classloader
- * @param language the name of the language
- * @param text the expression text
- * @return validation result
- */
- LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text);
-
- /**
- * Returns the component name from the given endpoint uri
- *
- * @param uri the endpoint uri
- * @return the component name (aka scheme), or <tt>null</tt> if not possible to determine
- */
- String endpointComponentName(String uri);
-
- /**
- * Creates an endpoint uri in Java style from the information from the properties
- *
- * @param scheme the endpoint schema
- * @param properties the properties as key value pairs
- * @param encode whether to URL encode the returned uri or not
- * @return the constructed endpoint uri
- * @throws java.net.URISyntaxException is thrown if there is encoding error
- */
- String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
-
- /**
- * Creates an endpoint uri in XML style (eg escape & as &l;) from the information from the properties
- *
- * @param scheme the endpoint schema
- * @param properties the properties as key value pairs
- * @param encode whether to URL encode the returned uri or not
- * @return the constructed endpoint uri
- * @throws java.net.URISyntaxException is thrown if there is encoding error
- */
- String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException;
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java b/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
deleted file mode 100644
index 5c86f23..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/SimpleValidationResult.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * 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.catalog;
-
-/**
- * To be backwards compatible, but favor using {@link LanguageValidationResult} instead.
- */
-public class SimpleValidationResult extends LanguageValidationResult {
-
- public SimpleValidationResult(String text) {
- super(text);
- }
-
- public String getSimple() {
- return getText();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java b/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
deleted file mode 100644
index 057d372..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/SuggestionStrategy.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.Set;
-
-/**
- * Strategy to provide suggestions for unknown endpoint options
- */
-public interface SuggestionStrategy {
-
- /**
- * Provides a list of valid option names for a did you mean function.
- *
- * @param names valid names
- * @param unknownOption unknown option name
- * @return a list of suggested names (did you mean)
- */
- String[] suggestEndpointOptions(Set<String> names, String unknownOption);
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java b/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
deleted file mode 100644
index 4ed843a..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/TimePatternConverter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This class is a copy from camel-core so we can use it independent to validate uris with time patterns
- */
-public final class TimePatternConverter {
- private static final Pattern NUMBERS_ONLY_STRING_PATTERN = Pattern.compile("^[-]?(\\d)+$", Pattern.CASE_INSENSITIVE);
- private static final Pattern HOUR_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))h(our(s)?)?", Pattern.CASE_INSENSITIVE);
- private static final Pattern MINUTES_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))m(in(ute(s)?)?)?", Pattern.CASE_INSENSITIVE);
- private static final Pattern SECONDS_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))s(ec(ond)?(s)?)?", Pattern.CASE_INSENSITIVE);
-
- /**
- * Utility classes should not have a public constructor.
- */
- private TimePatternConverter() {
- }
-
- public static long toMilliSeconds(String source) throws IllegalArgumentException {
- long milliseconds = 0;
- boolean foundFlag = false;
-
- checkCorrectnessOfPattern(source);
- Matcher matcher;
-
- matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
- if (matcher.find()) {
- // Note: This will also be used for regular numeric strings.
- // This String -> long converter will be used for all strings.
- milliseconds = Long.valueOf(source);
- } else {
- matcher = createMatcher(HOUR_REGEX_PATTERN, source);
- if (matcher.find()) {
- milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)));
- foundFlag = true;
- }
-
- matcher = createMatcher(MINUTES_REGEX_PATTERN, source);
- if (matcher.find()) {
- long minutes = Long.valueOf(matcher.group(1));
- if ((minutes > 59) && foundFlag) {
- throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
- }
- foundFlag = true;
- milliseconds = milliseconds + (60000 * minutes);
- }
-
- matcher = createMatcher(SECONDS_REGEX_PATTERN, source);
- if (matcher.find()) {
- long seconds = Long.valueOf(matcher.group(1));
- if ((seconds > 59) && foundFlag) {
- throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
- }
- foundFlag = true;
- milliseconds = milliseconds + (1000 * seconds);
- }
-
- // No pattern matched... initiating fallback check and conversion (if required).
- // The source at this point may contain illegal values or special characters
- if (!foundFlag) {
- milliseconds = Long.valueOf(source);
- }
- }
-
- return milliseconds;
- }
-
- private static void checkCorrectnessOfPattern(String source) {
- //replace only numbers once
- Matcher matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
- String replaceSource = matcher.replaceFirst("");
-
- //replace hour string once
- matcher = createMatcher(HOUR_REGEX_PATTERN, replaceSource);
- if (matcher.find() && matcher.find()) {
- throw new IllegalArgumentException("Hours should not be specified more then once: " + source);
- }
- replaceSource = matcher.replaceFirst("");
-
- //replace minutes once
- matcher = createMatcher(MINUTES_REGEX_PATTERN, replaceSource);
- if (matcher.find() && matcher.find()) {
- throw new IllegalArgumentException("Minutes should not be specified more then once: " + source);
- }
- replaceSource = matcher.replaceFirst("");
-
- //replace seconds once
- matcher = createMatcher(SECONDS_REGEX_PATTERN, replaceSource);
- if (matcher.find() && matcher.find()) {
- throw new IllegalArgumentException("Seconds should not be specified more then once: " + source);
- }
- replaceSource = matcher.replaceFirst("");
-
- if (replaceSource.length() > 0) {
- throw new IllegalArgumentException("Illegal characters: " + source);
- }
- }
-
- private static Matcher createMatcher(Pattern pattern, String source) {
- return pattern.matcher(source);
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java b/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
deleted file mode 100644
index ea1ecd5..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/URISupport.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Copied from org.apache.camel.util.URISupport
- */
-public final class URISupport {
-
- public static final String RAW_TOKEN_START = "RAW(";
- public static final String RAW_TOKEN_END = ")";
-
- private static final String CHARSET = "UTF-8";
-
- private URISupport() {
- // Helper class
- }
-
- /**
- * Normalizes the URI so unsafe characters is encoded
- *
- * @param uri the input uri
- * @return as URI instance
- * @throws URISyntaxException is thrown if syntax error in the input uri
- */
- public static URI normalizeUri(String uri) throws URISyntaxException {
- return new URI(UnsafeUriCharactersEncoder.encode(uri, true));
- }
-
- public static Map<String, Object> extractProperties(Map<String, Object> properties, String optionPrefix) {
- Map<String, Object> rc = new LinkedHashMap<String, Object>(properties.size());
-
- for (Iterator<Map.Entry<String, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
- Map.Entry<String, Object> entry = it.next();
- String name = entry.getKey();
- if (name.startsWith(optionPrefix)) {
- Object value = properties.get(name);
- name = name.substring(optionPrefix.length());
- rc.put(name, value);
- it.remove();
- }
- }
-
- return rc;
- }
-
- /**
- * Strips the query parameters from the uri
- *
- * @param uri the uri
- * @return the uri without the query parameter
- */
- public static String stripQuery(String uri) {
- int idx = uri.indexOf('?');
- if (idx > -1) {
- uri = uri.substring(0, idx);
- }
- return uri;
- }
-
- /**
- * Parses the query parameters of the uri (eg the query part).
- *
- * @param uri the uri
- * @return the parameters, or an empty map if no parameters (eg never null)
- * @throws URISyntaxException is thrown if uri has invalid syntax.
- */
- public static Map<String, Object> parseParameters(URI uri) throws URISyntaxException {
- String query = uri.getQuery();
- if (query == null) {
- String schemeSpecificPart = uri.getSchemeSpecificPart();
- int idx = schemeSpecificPart.indexOf('?');
- if (idx < 0) {
- // return an empty map
- return new LinkedHashMap<String, Object>(0);
- } else {
- query = schemeSpecificPart.substring(idx + 1);
- }
- } else {
- query = stripPrefix(query, "?");
- }
- return parseQuery(query);
- }
-
- /**
- * Strips the prefix from the value.
- * <p/>
- * Returns the value as-is if not starting with the prefix.
- *
- * @param value the value
- * @param prefix the prefix to remove from value
- * @return the value without the prefix
- */
- public static String stripPrefix(String value, String prefix) {
- if (value != null && value.startsWith(prefix)) {
- return value.substring(prefix.length());
- }
- return value;
- }
-
- /**
- * Parses the query part of the uri (eg the parameters).
- * <p/>
- * The URI parameters will by default be URI encoded. However you can define a parameter
- * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
- * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
- *
- * @param uri the uri
- * @return the parameters, or an empty map if no parameters (eg never null)
- * @throws URISyntaxException is thrown if uri has invalid syntax.
- * @see #RAW_TOKEN_START
- * @see #RAW_TOKEN_END
- */
- public static Map<String, Object> parseQuery(String uri) throws URISyntaxException {
- return parseQuery(uri, false);
- }
-
- /**
- * Parses the query part of the uri (eg the parameters).
- * <p/>
- * The URI parameters will by default be URI encoded. However you can define a parameter
- * values with the syntax: <tt>key=RAW(value)</tt> which tells Camel to not encode the value,
- * and use the value as is (eg key=value) and the value has <b>not</b> been encoded.
- *
- * @param uri the uri
- * @param useRaw whether to force using raw values
- * @return the parameters, or an empty map if no parameters (eg never null)
- * @throws URISyntaxException is thrown if uri has invalid syntax.
- * @see #RAW_TOKEN_START
- * @see #RAW_TOKEN_END
- */
- public static Map<String, Object> parseQuery(String uri, boolean useRaw) throws URISyntaxException {
- // must check for trailing & as the uri.split("&") will ignore those
- if (uri != null && uri.endsWith("&")) {
- throw new URISyntaxException(uri, "Invalid uri syntax: Trailing & marker found. "
- + "Check the uri and remove the trailing & marker.");
- }
-
- if (isEmpty(uri)) {
- // return an empty map
- return new LinkedHashMap<String, Object>(0);
- }
-
- // need to parse the uri query parameters manually as we cannot rely on splitting by &,
- // as & can be used in a parameter value as well.
-
- try {
- // use a linked map so the parameters is in the same order
- Map<String, Object> rc = new LinkedHashMap<String, Object>();
-
- boolean isKey = true;
- boolean isValue = false;
- boolean isRaw = false;
- StringBuilder key = new StringBuilder();
- StringBuilder value = new StringBuilder();
-
- // parse the uri parameters char by char
- for (int i = 0; i < uri.length(); i++) {
- // current char
- char ch = uri.charAt(i);
- // look ahead of the next char
- char next;
- if (i <= uri.length() - 2) {
- next = uri.charAt(i + 1);
- } else {
- next = '\u0000';
- }
-
- // are we a raw value
- isRaw = value.toString().startsWith(RAW_TOKEN_START);
-
- // if we are in raw mode, then we keep adding until we hit the end marker
- if (isRaw) {
- if (isKey) {
- key.append(ch);
- } else if (isValue) {
- value.append(ch);
- }
-
- // we only end the raw marker if its )& or at the end of the value
-
- boolean end = ch == RAW_TOKEN_END.charAt(0) && (next == '&' || next == '\u0000');
- if (end) {
- // raw value end, so add that as a parameter, and reset flags
- addParameter(key.toString(), value.toString(), rc, useRaw || isRaw);
- key.setLength(0);
- value.setLength(0);
- isKey = true;
- isValue = false;
- isRaw = false;
- // skip to next as we are in raw mode and have already added the value
- i++;
- }
- continue;
- }
-
- // if its a key and there is a = sign then the key ends and we are in value mode
- if (isKey && ch == '=') {
- isKey = false;
- isValue = true;
- isRaw = false;
- continue;
- }
-
- // the & denote parameter is ended
- if (ch == '&') {
- // parameter is ended, as we hit & separator
- String aKey = key.toString();
- // the key may be a placeholder of options which we then do not know what is
- boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
- if (validKey) {
- addParameter(aKey, value.toString(), rc, useRaw || isRaw);
- }
- key.setLength(0);
- value.setLength(0);
- isKey = true;
- isValue = false;
- isRaw = false;
- continue;
- }
-
- // regular char so add it to the key or value
- if (isKey) {
- key.append(ch);
- } else if (isValue) {
- value.append(ch);
- }
- }
-
- // any left over parameters, then add that
- if (key.length() > 0) {
- String aKey = key.toString();
- // the key may be a placeholder of options which we then do not know what is
- boolean validKey = !aKey.startsWith("{{") && !aKey.endsWith("}}");
- if (validKey) {
- addParameter(aKey, value.toString(), rc, useRaw || isRaw);
- }
- }
-
- return rc;
-
- } catch (UnsupportedEncodingException e) {
- URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
- se.initCause(e);
- throw se;
- }
- }
-
- @SuppressWarnings("unchecked")
- private static void addParameter(String name, String value, Map<String, Object> map, boolean isRaw) throws UnsupportedEncodingException {
- name = URLDecoder.decode(name, CHARSET);
- if (!isRaw) {
- // need to replace % with %25
- value = URLDecoder.decode(value.replaceAll("%", "%25"), CHARSET);
- }
-
- // does the key already exist?
- if (map.containsKey(name)) {
- // yes it does, so make sure we can support multiple values, but using a list
- // to hold the multiple values
- Object existing = map.get(name);
- List<String> list;
- if (existing instanceof List) {
- list = (List<String>) existing;
- } else {
- // create a new list to hold the multiple values
- list = new ArrayList<String>();
- String s = existing != null ? existing.toString() : null;
- if (s != null) {
- list.add(s);
- }
- }
- list.add(value);
- map.put(name, list);
- } else {
- map.put(name, value);
- }
- }
-
- /**
- * Assembles a query from the given map.
- *
- * @param options the map with the options (eg key/value pairs)
- * @param ampersand to use & for Java code, and & for XML
- * @return a query string with <tt>key1=value&key2=value2&...</tt>, or an empty string if there is no options.
- * @throws URISyntaxException is thrown if uri has invalid syntax.
- */
- public static String createQueryString(Map<String, String> options, String ampersand, boolean encode) throws URISyntaxException {
- try {
- if (options.size() > 0) {
- StringBuilder rc = new StringBuilder();
- boolean first = true;
- for (Object o : options.keySet()) {
- if (first) {
- first = false;
- } else {
- rc.append(ampersand);
- }
-
- String key = (String) o;
- Object value = options.get(key);
-
- // use the value as a String
- String s = value != null ? value.toString() : null;
- appendQueryStringParameter(key, s, rc, encode);
- }
- return rc.toString();
- } else {
- return "";
- }
- } catch (UnsupportedEncodingException e) {
- URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
- se.initCause(e);
- throw se;
- }
- }
-
- private static void appendQueryStringParameter(String key, String value, StringBuilder rc, boolean encode) throws UnsupportedEncodingException {
- if (encode) {
- rc.append(URLEncoder.encode(key, CHARSET));
- } else {
- rc.append(key);
- }
- // only append if value is not null
- if (value != null) {
- rc.append("=");
- if (value.startsWith(RAW_TOKEN_START) && value.endsWith(RAW_TOKEN_END)) {
- // do not encode RAW parameters
- rc.append(value);
- } else {
- if (encode) {
- rc.append(URLEncoder.encode(value, CHARSET));
- } else {
- rc.append(value);
- }
- }
- }
- }
-
- /**
- * Tests whether the value is <tt>null</tt> or an empty string.
- *
- * @param value the value, if its a String it will be tested for text length as well
- * @return true if empty
- */
- public static boolean isEmpty(Object value) {
- return !isNotEmpty(value);
- }
-
- /**
- * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
- *
- * @param value the value, if its a String it will be tested for text length as well
- * @return true if <b>not</b> empty
- */
- public static boolean isNotEmpty(Object value) {
- if (value == null) {
- return false;
- } else if (value instanceof String) {
- String text = (String) value;
- return text.trim().length() > 0;
- } else {
- return true;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java b/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
deleted file mode 100644
index 563bac2..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/UnsafeUriCharactersEncoder.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Encoder for unsafe URI characters.
- * <p/>
- * A good source for details is <a href="http://en.wikipedia.org/wiki/Url_encode">wikipedia url encode</a> article.
- */
-public final class UnsafeUriCharactersEncoder {
- private static BitSet unsafeCharactersRfc1738;
- private static BitSet unsafeCharactersHttp;
- private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
- 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f'};
- private static final Pattern RAW_PATTERN = Pattern.compile("RAW\\([^\\)]+\\)");
-
- static {
- unsafeCharactersRfc1738 = new BitSet(256);
- unsafeCharactersRfc1738.set(' ');
- unsafeCharactersRfc1738.set('"');
- unsafeCharactersRfc1738.set('<');
- unsafeCharactersRfc1738.set('>');
- unsafeCharactersRfc1738.set('#');
- unsafeCharactersRfc1738.set('%');
- unsafeCharactersRfc1738.set('{');
- unsafeCharactersRfc1738.set('}');
- unsafeCharactersRfc1738.set('|');
- unsafeCharactersRfc1738.set('\\');
- unsafeCharactersRfc1738.set('^');
- unsafeCharactersRfc1738.set('~');
- unsafeCharactersRfc1738.set('[');
- unsafeCharactersRfc1738.set(']');
- unsafeCharactersRfc1738.set('`');
- }
-
- static {
- unsafeCharactersHttp = new BitSet(256);
- unsafeCharactersHttp.set(' ');
- unsafeCharactersHttp.set('"');
- unsafeCharactersHttp.set('<');
- unsafeCharactersHttp.set('>');
- unsafeCharactersHttp.set('#');
- unsafeCharactersHttp.set('%');
- unsafeCharactersHttp.set('{');
- unsafeCharactersHttp.set('}');
- unsafeCharactersHttp.set('|');
- unsafeCharactersHttp.set('\\');
- unsafeCharactersHttp.set('^');
- unsafeCharactersHttp.set('~');
- unsafeCharactersHttp.set('`');
- }
-
- private UnsafeUriCharactersEncoder() {
- // util class
- }
-
- public static String encode(String s) {
- return encode(s, unsafeCharactersRfc1738);
- }
-
- public static String encodeHttpURI(String s) {
- return encode(s, unsafeCharactersHttp);
- }
-
- public static String encode(String s, BitSet unsafeCharacters) {
- return encode(s, unsafeCharacters, false);
- }
-
- public static String encode(String s, boolean checkRaw) {
- return encode(s, unsafeCharactersRfc1738, checkRaw);
- }
-
- public static String encodeHttpURI(String s, boolean checkRaw) {
- return encode(s, unsafeCharactersHttp, checkRaw);
- }
-
- private static List<Pair> checkRAW(String s) {
- Matcher matcher = RAW_PATTERN.matcher(s);
- List<Pair> answer = new ArrayList<Pair>();
- // Check all occurrences
- while (matcher.find()) {
- answer.add(new Pair(matcher.start(), matcher.end()));
- }
- return answer;
- }
-
- private static boolean isRaw(int index, List<Pair> pairs) {
- for (Pair pair : pairs) {
- if (index < pair.left) {
- return false;
- } else {
- if (index >= pair.left) {
- if (index <= pair.right) {
- return true;
- } else {
- continue;
- }
- }
- }
- }
- return false;
- }
-
- private static class Pair {
- int left;
- int right;
-
- Pair(int left, int right) {
- this.left = left;
- this.right = right;
- }
- }
-
- // Just skip the encode for isRAW part
- public static String encode(String s, BitSet unsafeCharacters, boolean checkRaw) {
- List<Pair> rawPairs;
- if (checkRaw) {
- rawPairs = checkRAW(s);
- } else {
- rawPairs = new ArrayList<Pair>();
- }
-
- int n = s == null ? 0 : s.length();
- if (n == 0) {
- return s;
- }
-
- // First check whether we actually need to encode
- char chars[] = s.toCharArray();
- for (int i = 0;;) {
- // just deal with the ascii character
- if (chars[i] > 0 && chars[i] < 128) {
- if (unsafeCharacters.get(chars[i])) {
- break;
- }
- }
- if (++i >= chars.length) {
- return s;
- }
- }
-
- // okay there are some unsafe characters so we do need to encode
- // see details at: http://en.wikipedia.org/wiki/Url_encode
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < chars.length; i++) {
- char ch = chars[i];
- if (ch > 0 && ch < 128 && unsafeCharacters.get(ch)) {
- // special for % sign as it may be a decimal encoded value
- if (ch == '%') {
- char next = i + 1 < chars.length ? chars[i + 1] : ' ';
- char next2 = i + 2 < chars.length ? chars[i + 2] : ' ';
-
- if (isHexDigit(next) && isHexDigit(next2) && !isRaw(i, rawPairs)) {
- // its already encoded (decimal encoded) so just append as is
- sb.append(ch);
- } else {
- // must escape then, as its an unsafe character
- appendEscape(sb, (byte) ch);
- }
- } else {
- // must escape then, as its an unsafe character
- appendEscape(sb, (byte) ch);
- }
- } else {
- sb.append(ch);
- }
- }
- return sb.toString();
- }
-
- private static void appendEscape(StringBuilder sb, byte b) {
- sb.append('%');
- sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
- sb.append(HEX_DIGITS[(b >> 0) & 0x0f]);
- }
-
- private static boolean isHexDigit(char ch) {
- for (char hex : HEX_DIGITS) {
- if (hex == ch) {
- return true;
- }
- }
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/package.html
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/package.html b/camel-core/src/main/java/org/apache/camel/catalog/package.html
deleted file mode 100644
index 98786d1..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- 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.
--->
-<html>
-<head>
-</head>
-<body>
-
-Camel Catalog
-
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
index 5d19e0d..4013e5f 100644
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java
@@ -22,12 +22,12 @@ import java.util.Map;
import org.apache.camel.Component;
import org.apache.camel.ComponentVerifier;
import org.apache.camel.VerifiableComponent;
-import org.apache.camel.catalog.JSonSchemaHelper;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.impl.verifier.CatalogVerifierCustomizer;
import org.apache.camel.impl.verifier.DefaultComponentVerifier;
import org.apache.camel.impl.verifier.ResultBuilder;
import org.apache.camel.impl.verifier.ResultErrorBuilder;
+import org.apache.camel.runtimecatalog.JSonSchemaHelper;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.RestConsumerFactory;
import org.apache.camel.spi.RestProducerFactory;
import org.apache.camel.util.ObjectHelper;
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index c85ce8c..b53efc8 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -26,7 +26,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -87,8 +86,6 @@ import org.apache.camel.api.management.mbean.ManagedRouteMBean;
import org.apache.camel.builder.DefaultFluentProducerTemplate;
import org.apache.camel.builder.ErrorHandlerBuilder;
import org.apache.camel.builder.ErrorHandlerBuilderSupport;
-import org.apache.camel.catalog.DefaultRuntimeCamelCatalog;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
import org.apache.camel.impl.converter.DefaultTypeConverter;
@@ -121,6 +118,8 @@ import org.apache.camel.processor.interceptor.Delayer;
import org.apache.camel.processor.interceptor.HandleFault;
import org.apache.camel.processor.interceptor.StreamCaching;
import org.apache.camel.processor.interceptor.Tracer;
+import org.apache.camel.runtimecatalog.DefaultRuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.AsyncProcessorAwaitManager;
import org.apache.camel.spi.CamelContextNameStrategy;
import org.apache.camel.spi.ClassResolver;
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
index b9d9998..f05cdb1 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
@@ -25,8 +25,8 @@ import org.apache.camel.CamelContext;
import org.apache.camel.ComponentVerifier;
import org.apache.camel.NoSuchOptionException;
import org.apache.camel.TypeConverter;
-import org.apache.camel.catalog.EndpointValidationResult;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.EndpointValidationResult;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.util.CamelContextHelper;
import org.apache.camel.util.EndpointHelper;
import org.apache.camel.util.IntrospectionSupport;
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
index a09ff7d..9a70390 100644
--- a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
@@ -46,12 +46,9 @@ import org.apache.camel.StartupListener;
import org.apache.camel.TimerListener;
import org.apache.camel.VetoCamelContextStartException;
import org.apache.camel.api.management.PerformanceCounter;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.impl.ConsumerCache;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.DefaultEndpointRegistry;
-import org.apache.camel.impl.DefaultTransformerRegistry;
-import org.apache.camel.impl.DefaultValidatorRegistry;
import org.apache.camel.impl.EventDrivenConsumerRoute;
import org.apache.camel.impl.ProducerCache;
import org.apache.camel.impl.ThrottlingExceptionRoutePolicy;
@@ -89,6 +86,7 @@ import org.apache.camel.processor.CamelInternalProcessor;
import org.apache.camel.processor.interceptor.BacklogDebugger;
import org.apache.camel.processor.interceptor.BacklogTracer;
import org.apache.camel.processor.interceptor.Tracer;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.AsyncProcessorAwaitManager;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.EventNotifier;
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
index 20d3f28..6a99656 100644
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
+++ b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRuntimeCamelCatalog.java
@@ -19,7 +19,7 @@ package org.apache.camel.management.mbean;
import org.apache.camel.CamelContext;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.api.management.mbean.ManagedRuntimeCamelCatalogMBean;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.ManagementStrategy;
/**
[6/6] camel git commit: Rename catalog to runtimecatalog to avoid
clash with same package name in camel-catalog.
Posted by da...@apache.org.
Rename catalog to runtimecatalog to avoid clash with same package name in camel-catalog.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/c66be7a8
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/c66be7a8
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/c66be7a8
Branch: refs/heads/master
Commit: c66be7a8c21de8944fd86888a2cf039eb97a2ff1
Parents: d726964
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Apr 14 12:08:59 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Apr 14 12:52:40 2017 +0200
----------------------------------------------------------------------
.../java/org/apache/camel/CamelContext.java | 2 +-
.../camel/catalog/AbstractCamelCatalog.java | 1294 ------------------
.../catalog/CamelContextJSonSchemaResolver.java | 80 --
.../org/apache/camel/catalog/CatalogHelper.java | 179 ---
.../camel/catalog/CollectionStringBuffer.java | 57 -
.../catalog/DefaultRuntimeCamelCatalog.java | 136 --
.../camel/catalog/EndpointValidationResult.java | 451 ------
.../apache/camel/catalog/JSonSchemaHelper.java | 424 ------
.../camel/catalog/JSonSchemaResolver.java | 64 -
.../camel/catalog/LanguageValidationResult.java | 65 -
.../camel/catalog/RuntimeCamelCatalog.java | 234 ----
.../camel/catalog/SimpleValidationResult.java | 32 -
.../camel/catalog/SuggestionStrategy.java | 34 -
.../camel/catalog/TimePatternConverter.java | 120 --
.../org/apache/camel/catalog/URISupport.java | 392 ------
.../catalog/UnsafeUriCharactersEncoder.java | 206 ---
.../java/org/apache/camel/catalog/package.html | 25 -
.../component/rest/RestComponentVerifier.java | 4 +-
.../apache/camel/impl/DefaultCamelContext.java | 5 +-
.../impl/verifier/DefaultComponentVerifier.java | 4 +-
.../DefaultManagementLifecycleStrategy.java | 4 +-
.../mbean/ManagedRuntimeCamelCatalog.java | 2 +-
.../runtimecatalog/AbstractCamelCatalog.java | 1294 ++++++++++++++++++
.../CamelContextJSonSchemaResolver.java | 80 ++
.../camel/runtimecatalog/CatalogHelper.java | 179 +++
.../runtimecatalog/CollectionStringBuffer.java | 57 +
.../DefaultRuntimeCamelCatalog.java | 136 ++
.../EndpointValidationResult.java | 451 ++++++
.../camel/runtimecatalog/JSonSchemaHelper.java | 424 ++++++
.../runtimecatalog/JSonSchemaResolver.java | 64 +
.../LanguageValidationResult.java | 65 +
.../runtimecatalog/RuntimeCamelCatalog.java | 234 ++++
.../runtimecatalog/SimpleValidationResult.java | 32 +
.../runtimecatalog/SuggestionStrategy.java | 34 +
.../runtimecatalog/TimePatternConverter.java | 120 ++
.../apache/camel/runtimecatalog/URISupport.java | 392 ++++++
.../UnsafeUriCharactersEncoder.java | 206 +++
.../apache/camel/runtimecatalog/package.html | 25 +
.../org/apache/camel/util/EndpointHelper.java | 6 +-
.../camel/catalog/AbstractCamelCatalogTest.java | 104 --
.../camel/catalog/RuntimeCamelCatalogTest.java | 393 ------
.../AbstractCamelCatalogTest.java | 104 ++
.../runtimecatalog/RuntimeCamelCatalogTest.java | 393 ++++++
43 files changed, 4302 insertions(+), 4305 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/CamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index d4fd6ae..00702d1 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -30,7 +30,6 @@ import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
import org.apache.camel.api.management.mbean.ManagedRouteMBean;
import org.apache.camel.builder.ErrorHandlerBuilder;
-import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.HystrixConfigurationDefinition;
import org.apache.camel.model.ProcessorDefinition;
@@ -41,6 +40,7 @@ import org.apache.camel.model.rest.RestDefinition;
import org.apache.camel.model.rest.RestsDefinition;
import org.apache.camel.model.transformer.TransformerDefinition;
import org.apache.camel.model.validator.ValidatorDefinition;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import org.apache.camel.spi.AsyncProcessorAwaitManager;
import org.apache.camel.spi.CamelContextNameStrategy;
import org.apache.camel.spi.ClassResolver;
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
deleted file mode 100644
index 6511eff..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/AbstractCamelCatalog.java
+++ /dev/null
@@ -1,1294 +0,0 @@
-/**
- * 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.catalog;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-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.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.apache.camel.catalog.CatalogHelper.after;
-import static org.apache.camel.catalog.JSonSchemaHelper.getNames;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyDefaultValue;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyEnum;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyKind;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyNameFromNameWithPrefix;
-import static org.apache.camel.catalog.JSonSchemaHelper.getPropertyPrefix;
-import static org.apache.camel.catalog.JSonSchemaHelper.getRow;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentConsumerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentLenientProperties;
-import static org.apache.camel.catalog.JSonSchemaHelper.isComponentProducerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyBoolean;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyConsumerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyInteger;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyMultiValue;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyNumber;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyObject;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyProducerOnly;
-import static org.apache.camel.catalog.JSonSchemaHelper.isPropertyRequired;
-import static org.apache.camel.catalog.JSonSchemaHelper.stripOptionalPrefixFromName;
-import static org.apache.camel.catalog.URISupport.createQueryString;
-import static org.apache.camel.catalog.URISupport.isEmpty;
-import static org.apache.camel.catalog.URISupport.normalizeUri;
-import static org.apache.camel.catalog.URISupport.stripQuery;
-
-/**
- * Base class for both the runtime RuntimeCamelCatalog from camel-core and the complete CamelCatalog from camel-catalog.
- */
-public abstract class AbstractCamelCatalog {
-
- // CHECKSTYLE:OFF
-
- private static final Pattern SYNTAX_PATTERN = Pattern.compile("(\\w+)");
-
- private SuggestionStrategy suggestionStrategy;
- private JSonSchemaResolver jsonSchemaResolver;
-
- public SuggestionStrategy getSuggestionStrategy() {
- return suggestionStrategy;
- }
-
- public void setSuggestionStrategy(SuggestionStrategy suggestionStrategy) {
- this.suggestionStrategy = suggestionStrategy;
- }
-
- public JSonSchemaResolver getJSonSchemaResolver() {
- return jsonSchemaResolver;
- }
-
- public void setJSonSchemaResolver(JSonSchemaResolver resolver) {
- this.jsonSchemaResolver = resolver;
- }
-
- public boolean validateTimePattern(String pattern) {
- return validateInteger(pattern);
- }
-
- public EndpointValidationResult validateEndpointProperties(String uri) {
- return validateEndpointProperties(uri, false, false, false);
- }
-
- public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties) {
- return validateEndpointProperties(uri, ignoreLenientProperties, false, false);
- }
-
- public EndpointValidationResult validateProperties(String scheme, Map<String, String> properties) {
- EndpointValidationResult result = new EndpointValidationResult(scheme);
-
- String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
- List<Map<String, String>> componentProps = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
-
- // endpoint options have higher priority so remove those from component
- // that may clash
- componentProps.stream()
- .filter(c -> rows.stream().noneMatch(e -> Objects.equals(e.get("name"), c.get("name"))))
- .forEach(rows::add);
-
- boolean lenient = Boolean.getBoolean(properties.getOrDefault("lenient", "false"));
-
- // the dataformat component refers to a data format so lets add the properties for the selected
- // data format to the list of rows
- if ("dataformat".equals(scheme)) {
- String dfName = properties.get("name");
- if (dfName != null) {
- String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
- List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
- if (dfRows != null && !dfRows.isEmpty()) {
- rows.addAll(dfRows);
- }
- }
- }
-
- for (Map.Entry<String, String> property : properties.entrySet()) {
- String value = property.getValue();
- String originalName = property.getKey();
- String name = property.getKey();
- // the name may be using an optional prefix, so lets strip that because the options
- // in the schema are listed without the prefix
- name = stripOptionalPrefixFromName(rows, name);
- // the name may be using a prefix, so lets see if we can find the real property name
- String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
- if (propertyName != null) {
- name = propertyName;
- }
-
- String prefix = getPropertyPrefix(rows, name);
- String kind = getPropertyKind(rows, name);
- boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
- boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
- boolean lookup = value.startsWith("#") && value.length() > 1;
- // we cannot evaluate multi values as strict as the others, as we don't know their expected types
- boolean multiValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
-
- Map<String, String> row = getRow(rows, name);
- if (row == null) {
- // unknown option
-
- // only add as error if the component is not lenient properties, or not stub component
- // and the name is not a property placeholder for one or more values
- if (!namePlaceholder && !"stub".equals(scheme)) {
- if (lenient) {
- // as if we are lenient then the option is a dynamic extra option which we cannot validate
- result.addLenient(name);
- } else {
- // its unknown
- result.addUnknown(name);
- if (suggestionStrategy != null) {
- String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
- if (suggestions != null) {
- result.addUnknownSuggestions(name, suggestions);
- }
- }
- }
- }
- } else {
- /* TODO: we may need to add something in the properties to know if they are related to a producer or consumer
- if ("parameter".equals(kind)) {
- // consumer only or producer only mode for parameters
- if (consumerOnly) {
- boolean producer = isPropertyProducerOnly(rows, name);
- if (producer) {
- // the option is only for producer so you cannot use it in consumer mode
- result.addNotConsumerOnly(name);
- }
- } else if (producerOnly) {
- boolean consumer = isPropertyConsumerOnly(rows, name);
- if (consumer) {
- // the option is only for consumer so you cannot use it in producer mode
- result.addNotProducerOnly(name);
- }
- }
- }
- */
-
- // default value
- String defaultValue = getPropertyDefaultValue(rows, name);
- if (defaultValue != null) {
- result.addDefaultValue(name, defaultValue);
- }
-
- // is required but the value is empty
- boolean required = isPropertyRequired(rows, name);
- if (required && isEmpty(value)) {
- result.addRequired(name);
- }
-
- // is enum but the value is not within the enum range
- // but we can only check if the value is not a placeholder
- String enums = getPropertyEnum(rows, name);
- if (!multiValue && !valuePlaceholder && !lookup && enums != null) {
- String[] choices = enums.split(",");
- boolean found = false;
- for (String s : choices) {
- if (value.equalsIgnoreCase(s)) {
- found = true;
- break;
- }
- }
- if (!found) {
- result.addInvalidEnum(name, value);
- result.addInvalidEnumChoices(name, choices);
- if (suggestionStrategy != null) {
- Set<String> names = new LinkedHashSet<>();
- names.addAll(Arrays.asList(choices));
- String[] suggestions = suggestionStrategy.suggestEndpointOptions(names, value);
- if (suggestions != null) {
- result.addInvalidEnumSuggestions(name, suggestions);
- }
- }
-
- }
- }
-
- // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
- if (!multiValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
- // must start with # and be at least 2 characters
- if (!value.startsWith("#") || value.length() <= 1) {
- result.addInvalidReference(name, value);
- }
- }
-
- // is boolean
- if (!multiValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
- // value must be a boolean
- boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
- if (!bool) {
- result.addInvalidBoolean(name, value);
- }
- }
-
- // is integer
- if (!multiValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
- // value must be an integer
- boolean valid = validateInteger(value);
- if (!valid) {
- result.addInvalidInteger(name, value);
- }
- }
-
- // is number
- if (!multiValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
- // value must be an number
- boolean valid = false;
- try {
- valid = !Double.valueOf(value).isNaN() || !Float.valueOf(value).isNaN();
- } catch (Exception e) {
- // ignore
- }
- if (!valid) {
- result.addInvalidNumber(name, value);
- }
- }
- }
- }
-
- // now check if all required values are there, and that a default value does not exists
- for (Map<String, String> row : rows) {
- String name = row.get("name");
- boolean required = isPropertyRequired(rows, name);
- if (required) {
- String value = properties.get(name);
- if (isEmpty(value)) {
- value = getPropertyDefaultValue(rows, name);
- }
- if (isEmpty(value)) {
- result.addRequired(name);
- }
- }
- }
-
- return result;
- }
-
- public EndpointValidationResult validateEndpointProperties(String uri, boolean ignoreLenientProperties, boolean consumerOnly, boolean producerOnly) {
- EndpointValidationResult result = new EndpointValidationResult(uri);
-
- Map<String, String> properties;
- List<Map<String, String>> rows;
- boolean lenientProperties;
- String scheme;
-
- try {
- String json = null;
-
- // parse the uri
- URI u = normalizeUri(uri);
- scheme = u.getScheme();
-
- if (scheme != null) {
- json = jsonSchemaResolver.getComponentJSonSchema(scheme);
- }
- if (json == null) {
- // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
- if (uri.startsWith("{{")) {
- result.addIncapable(uri);
- } else if (scheme != null) {
- result.addUnknownComponent(scheme);
- } else {
- result.addUnknownComponent(uri);
- }
- return result;
- }
-
- rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-
- // is the component capable of both consumer and producer?
- boolean canConsumeAndProduce = false;
- if (!isComponentConsumerOnly(rows) && !isComponentProducerOnly(rows)) {
- canConsumeAndProduce = true;
- }
-
- if (canConsumeAndProduce && consumerOnly) {
- // lenient properties is not support in consumer only mode if the component can do both of them
- lenientProperties = false;
- } else {
- // only enable lenient properties if we should not ignore
- lenientProperties = !ignoreLenientProperties && isComponentLenientProperties(rows);
- }
- rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
- properties = endpointProperties(uri);
- } catch (URISyntaxException e) {
- if (uri.startsWith("{{")) {
- // if the uri starts with a placeholder then we are also incapable of parsing it as we wasn't able to resolve the component name
- result.addIncapable(uri);
- } else {
- result.addSyntaxError(e.getMessage());
- }
-
- return result;
- }
-
- // the dataformat component refers to a data format so lets add the properties for the selected
- // data format to the list of rows
- if ("dataformat".equals(scheme)) {
- String dfName = properties.get("name");
- if (dfName != null) {
- String dfJson = jsonSchemaResolver.getDataFormatJSonSchema(dfName);
- List<Map<String, String>> dfRows = JSonSchemaHelper.parseJsonSchema("properties", dfJson, true);
- if (dfRows != null && !dfRows.isEmpty()) {
- rows.addAll(dfRows);
- }
- }
- }
-
- for (Map.Entry<String, String> property : properties.entrySet()) {
- String value = property.getValue();
- String originalName = property.getKey();
- String name = property.getKey();
- // the name may be using an optional prefix, so lets strip that because the options
- // in the schema are listed without the prefix
- name = stripOptionalPrefixFromName(rows, name);
- // the name may be using a prefix, so lets see if we can find the real property name
- String propertyName = getPropertyNameFromNameWithPrefix(rows, name);
- if (propertyName != null) {
- name = propertyName;
- }
-
- String prefix = getPropertyPrefix(rows, name);
- String kind = getPropertyKind(rows, name);
- boolean namePlaceholder = name.startsWith("{{") && name.endsWith("}}");
- boolean valuePlaceholder = value.startsWith("{{") || value.startsWith("${") || value.startsWith("$simple{");
- boolean lookup = value.startsWith("#") && value.length() > 1;
- // we cannot evaluate multi values as strict as the others, as we don't know their expected types
- boolean mulitValue = prefix != null && originalName.startsWith(prefix) && isPropertyMultiValue(rows, name);
-
- Map<String, String> row = getRow(rows, name);
- if (row == null) {
- // unknown option
-
- // only add as error if the component is not lenient properties, or not stub component
- // and the name is not a property placeholder for one or more values
- if (!namePlaceholder && !"stub".equals(scheme)) {
- if (lenientProperties) {
- // as if we are lenient then the option is a dynamic extra option which we cannot validate
- result.addLenient(name);
- } else {
- // its unknown
- result.addUnknown(name);
- if (suggestionStrategy != null) {
- String[] suggestions = suggestionStrategy.suggestEndpointOptions(getNames(rows), name);
- if (suggestions != null) {
- result.addUnknownSuggestions(name, suggestions);
- }
- }
- }
- }
- } else {
- if ("parameter".equals(kind)) {
- // consumer only or producer only mode for parameters
- if (consumerOnly) {
- boolean producer = isPropertyProducerOnly(rows, name);
- if (producer) {
- // the option is only for producer so you cannot use it in consumer mode
- result.addNotConsumerOnly(name);
- }
- } else if (producerOnly) {
- boolean consumer = isPropertyConsumerOnly(rows, name);
- if (consumer) {
- // the option is only for consumer so you cannot use it in producer mode
- result.addNotProducerOnly(name);
- }
- }
- }
-
- // default value
- String defaultValue = getPropertyDefaultValue(rows, name);
- if (defaultValue != null) {
- result.addDefaultValue(name, defaultValue);
- }
-
- // is required but the value is empty
- boolean required = isPropertyRequired(rows, name);
- if (required && isEmpty(value)) {
- result.addRequired(name);
- }
-
- // is enum but the value is not within the enum range
- // but we can only check if the value is not a placeholder
- String enums = getPropertyEnum(rows, name);
- if (!mulitValue && !valuePlaceholder && !lookup && enums != null) {
- String[] choices = enums.split(",");
- boolean found = false;
- for (String s : choices) {
- if (value.equalsIgnoreCase(s)) {
- found = true;
- break;
- }
- }
- if (!found) {
- result.addInvalidEnum(name, value);
- result.addInvalidEnumChoices(name, choices);
- if (suggestionStrategy != null) {
- Set<String> names = new LinkedHashSet<>();
- names.addAll(Arrays.asList(choices));
- String[] suggestions = suggestionStrategy.suggestEndpointOptions(names, value);
- if (suggestions != null) {
- result.addInvalidEnumSuggestions(name, suggestions);
- }
- }
-
- }
- }
-
- // is reference lookup of bean (not applicable for @UriPath, enums, or multi-valued)
- if (!mulitValue && enums == null && !"path".equals(kind) && isPropertyObject(rows, name)) {
- // must start with # and be at least 2 characters
- if (!value.startsWith("#") || value.length() <= 1) {
- result.addInvalidReference(name, value);
- }
- }
-
- // is boolean
- if (!mulitValue && !valuePlaceholder && !lookup && isPropertyBoolean(rows, name)) {
- // value must be a boolean
- boolean bool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
- if (!bool) {
- result.addInvalidBoolean(name, value);
- }
- }
-
- // is integer
- if (!mulitValue && !valuePlaceholder && !lookup && isPropertyInteger(rows, name)) {
- // value must be an integer
- boolean valid = validateInteger(value);
- if (!valid) {
- result.addInvalidInteger(name, value);
- }
- }
-
- // is number
- if (!mulitValue && !valuePlaceholder && !lookup && isPropertyNumber(rows, name)) {
- // value must be an number
- boolean valid = false;
- try {
- valid = !Double.valueOf(value).isNaN() || !Float.valueOf(value).isNaN();
- } catch (Exception e) {
- // ignore
- }
- if (!valid) {
- result.addInvalidNumber(name, value);
- }
- }
- }
- }
-
- // now check if all required values are there, and that a default value does not exists
- for (Map<String, String> row : rows) {
- String name = row.get("name");
- boolean required = isPropertyRequired(rows, name);
- if (required) {
- String value = properties.get(name);
- if (isEmpty(value)) {
- value = getPropertyDefaultValue(rows, name);
- }
- if (isEmpty(value)) {
- result.addRequired(name);
- }
- }
- }
-
- return result;
- }
-
- public Map<String, String> endpointProperties(String uri) throws URISyntaxException {
- // need to normalize uri first
- URI u = normalizeUri(uri);
- String scheme = u.getScheme();
-
- String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
- if (json == null) {
- throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
- }
-
- // grab the syntax
- String syntax = null;
- String alternativeSyntax = null;
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
- for (Map<String, String> row : rows) {
- if (row.containsKey("syntax")) {
- syntax = row.get("syntax");
- }
- if (row.containsKey("alternativeSyntax")) {
- alternativeSyntax = row.get("alternativeSyntax");
- }
- }
- if (syntax == null) {
- throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
- }
-
- // only if we support alternative syntax, and the uri contains the username and password in the authority
- // part of the uri, then we would need some special logic to capture that information and strip those
- // details from the uri, so we can continue parsing the uri using the normal syntax
- Map<String, String> userInfoOptions = new LinkedHashMap<String, String>();
- if (alternativeSyntax != null && alternativeSyntax.contains("@")) {
- // clip the scheme from the syntax
- alternativeSyntax = after(alternativeSyntax, ":");
- // trim so only userinfo
- int idx = alternativeSyntax.indexOf("@");
- String fields = alternativeSyntax.substring(0, idx);
- String[] names = fields.split(":");
-
- // grab authority part and grab username and/or password
- String authority = u.getAuthority();
- if (authority != null && authority.contains("@")) {
- String username = null;
- String password = null;
-
- // grab unserinfo part before @
- String userInfo = authority.substring(0, authority.indexOf("@"));
- String[] parts = userInfo.split(":");
- if (parts.length == 2) {
- username = parts[0];
- password = parts[1];
- } else {
- // only username
- username = userInfo;
- }
-
- // remember the username and/or password which we add later to the options
- if (names.length == 2) {
- userInfoOptions.put(names[0], username);
- if (password != null) {
- // password is optional
- userInfoOptions.put(names[1], password);
- }
- }
- }
- }
-
- // clip the scheme from the syntax
- syntax = after(syntax, ":");
- // clip the scheme from the uri
- uri = after(uri, ":");
- String uriPath = stripQuery(uri);
-
- // strip user info from uri path
- if (!userInfoOptions.isEmpty()) {
- int idx = uriPath.indexOf('@');
- if (idx > -1) {
- uriPath = uriPath.substring(idx + 1);
- }
- }
-
- // strip double slash in the start
- if (uriPath != null && uriPath.startsWith("//")) {
- uriPath = uriPath.substring(2);
- }
-
- // parse the syntax and find the names of each option
- Matcher matcher = SYNTAX_PATTERN.matcher(syntax);
- List<String> word = new ArrayList<String>();
- while (matcher.find()) {
- String s = matcher.group(1);
- if (!scheme.equals(s)) {
- word.add(s);
- }
- }
- // parse the syntax and find each token between each option
- String[] tokens = SYNTAX_PATTERN.split(syntax);
-
- // find the position where each option start/end
- List<String> word2 = new ArrayList<String>();
- int prev = 0;
- int prevPath = 0;
-
- // special for activemq/jms where the enum for destinationType causes a token issue as it includes a colon
- // for 'temp:queue' and 'temp:topic' values
- if ("activemq".equals(scheme) || "jms".equals(scheme)) {
- if (uriPath.startsWith("temp:")) {
- prevPath = 5;
- }
- }
-
- for (String token : tokens) {
- if (token.isEmpty()) {
- continue;
- }
-
- // special for some tokens where :// can be used also, eg http://foo
- int idx = -1;
- int len = 0;
- if (":".equals(token)) {
- idx = uriPath.indexOf("://", prevPath);
- len = 3;
- }
- if (idx == -1) {
- idx = uriPath.indexOf(token, prevPath);
- len = token.length();
- }
-
- if (idx > 0) {
- String option = uriPath.substring(prev, idx);
- word2.add(option);
- prev = idx + len;
- prevPath = prev;
- }
- }
- // special for last or if we did not add anyone
- if (prev > 0 || word2.isEmpty()) {
- String option = uriPath.substring(prev);
- word2.add(option);
- }
-
- rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
- boolean defaultValueAdded = false;
-
- // now parse the uri to know which part isw what
- Map<String, String> options = new LinkedHashMap<String, String>();
-
- // include the username and password from the userinfo section
- if (!userInfoOptions.isEmpty()) {
- options.putAll(userInfoOptions);
- }
-
- // word contains the syntax path elements
- Iterator<String> it = word2.iterator();
- for (int i = 0; i < word.size(); i++) {
- String key = word.get(i);
-
- boolean allOptions = word.size() == word2.size();
- boolean required = isPropertyRequired(rows, key);
- String defaultValue = getPropertyDefaultValue(rows, key);
-
- // we have all options so no problem
- if (allOptions) {
- String value = it.next();
- options.put(key, value);
- } else {
- // we have a little problem as we do not not have all options
- if (!required) {
- String value = null;
-
- boolean last = i == word.size() - 1;
- if (last) {
- // if its the last value then use it instead of the default value
- value = it.hasNext() ? it.next() : null;
- if (value != null) {
- options.put(key, value);
- } else {
- value = defaultValue;
- }
- }
- if (value != null) {
- options.put(key, value);
- defaultValueAdded = true;
- }
- } else {
- String value = it.hasNext() ? it.next() : null;
- if (value != null) {
- options.put(key, value);
- }
- }
- }
- }
-
- Map<String, String> answer = new LinkedHashMap<String, String>();
-
- // remove all options which are using default values and are not required
- for (Map.Entry<String, String> entry : options.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue();
-
- if (defaultValueAdded) {
- boolean required = isPropertyRequired(rows, key);
- String defaultValue = getPropertyDefaultValue(rows, key);
-
- if (!required && defaultValue != null) {
- if (defaultValue.equals(value)) {
- continue;
- }
- }
- }
-
- // we should keep this in the answer
- answer.put(key, value);
- }
-
- // now parse the uri parameters
- Map<String, Object> parameters = URISupport.parseParameters(u);
-
- // and covert the values to String so its JMX friendly
- while (!parameters.isEmpty()) {
- Map.Entry<String, Object> entry = parameters.entrySet().iterator().next();
- String key = entry.getKey();
- String value = entry.getValue() != null ? entry.getValue().toString() : "";
-
- boolean multiValued = isPropertyMultiValue(rows, key);
- if (multiValued) {
- String prefix = getPropertyPrefix(rows, key);
- // extra all the multi valued options
- Map<String, Object> values = URISupport.extractProperties(parameters, prefix);
- // build a string with the extra multi valued options with the prefix and & as separator
- CollectionStringBuffer csb = new CollectionStringBuffer("&");
- for (Map.Entry<String, Object> multi : values.entrySet()) {
- String line = prefix + multi.getKey() + "=" + (multi.getValue() != null ? multi.getValue().toString() : "");
- csb.append(line);
- }
- // append the extra multi-values to the existing (which contains the first multi value)
- if (!csb.isEmpty()) {
- value = value + "&" + csb.toString();
- }
- }
-
- answer.put(key, value);
- // remove the parameter as we run in a while loop until no more parameters
- parameters.remove(key);
- }
-
- return answer;
- }
-
- public Map<String, String> endpointLenientProperties(String uri) throws URISyntaxException {
- // need to normalize uri first
-
- // parse the uri
- URI u = normalizeUri(uri);
- String scheme = u.getScheme();
-
- String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
- if (json == null) {
- throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
- }
-
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
- // now parse the uri parameters
- Map<String, Object> parameters = URISupport.parseParameters(u);
-
- // all the known options
- Set<String> names = getNames(rows);
-
- Map<String, String> answer = new LinkedHashMap<>();
-
- // and covert the values to String so its JMX friendly
- parameters.forEach((k, v) -> {
- String key = k;
- String value = v != null ? v.toString() : "";
-
- // is the key a prefix property
- int dot = key.indexOf('.');
- if (dot != -1) {
- String prefix = key.substring(0, dot + 1); // include dot in prefix
- String option = getPropertyNameFromNameWithPrefix(rows, prefix);
- if (option == null || !isPropertyMultiValue(rows, option)) {
- answer.put(key, value);
- }
- } else if (!names.contains(key)) {
- answer.put(key, value);
- }
- });
-
- return answer;
- }
-
- public String endpointComponentName(String uri) {
- if (uri != null) {
- int idx = uri.indexOf(":");
- if (idx > 0) {
- return uri.substring(0, idx);
- }
- }
- return null;
- }
-
- public String asEndpointUri(String scheme, String json, boolean encode) throws URISyntaxException {
- return doAsEndpointUri(scheme, json, "&", encode);
- }
-
- public String asEndpointUriXml(String scheme, String json, boolean encode) throws URISyntaxException {
- return doAsEndpointUri(scheme, json, "&", encode);
- }
-
- private String doAsEndpointUri(String scheme, String json, String ampersand, boolean encode) throws URISyntaxException {
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
- Map<String, String> copy = new HashMap<String, String>();
- for (Map<String, String> row : rows) {
- String name = row.get("name");
- String required = row.get("required");
- String value = row.get("value");
- String defaultValue = row.get("defaultValue");
-
- // only add if either required, or the value is != default value
- String valueToAdd = null;
- if ("true".equals(required)) {
- valueToAdd = value != null ? value : defaultValue;
- if (valueToAdd == null) {
- valueToAdd = "";
- }
- } else {
- // if we have a value and no default then add it
- if (value != null && defaultValue == null) {
- valueToAdd = value;
- }
- // otherwise only add if the value is != default value
- if (value != null && defaultValue != null && !value.equals(defaultValue)) {
- valueToAdd = value;
- }
- }
-
- if (valueToAdd != null) {
- copy.put(name, valueToAdd);
- }
- }
-
- return doAsEndpointUri(scheme, copy, ampersand, encode);
- }
-
- public String asEndpointUri(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
- return doAsEndpointUri(scheme, properties, "&", encode);
- }
-
- public String asEndpointUriXml(String scheme, Map<String, String> properties, boolean encode) throws URISyntaxException {
- return doAsEndpointUri(scheme, properties, "&", encode);
- }
-
- String doAsEndpointUri(String scheme, Map<String, String> properties, String ampersand, boolean encode) throws URISyntaxException {
- String json = jsonSchemaResolver.getComponentJSonSchema(scheme);
- if (json == null) {
- throw new IllegalArgumentException("Cannot find endpoint with scheme " + scheme);
- }
-
- // grab the syntax
- String syntax = null;
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
- for (Map<String, String> row : rows) {
- if (row.containsKey("syntax")) {
- syntax = row.get("syntax");
- break;
- }
- }
- if (syntax == null) {
- throw new IllegalArgumentException("Endpoint with scheme " + scheme + " has no syntax defined in the json schema");
- }
-
- // do any properties filtering which can be needed for some special components
- properties = filterProperties(scheme, properties);
-
- rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-
- // clip the scheme from the syntax
- syntax = after(syntax, ":");
-
- String originalSyntax = syntax;
-
- // build at first according to syntax (use a tree map as we want the uri options sorted)
- Map<String, String> copy = new TreeMap<String, String>();
- for (Map.Entry<String, String> entry : properties.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue() != null ? entry.getValue() : "";
- if (syntax != null && syntax.contains(key)) {
- syntax = syntax.replace(key, value);
- } else {
- copy.put(key, value);
- }
- }
-
- // do we have all the options the original syntax needs (easy way)
- String[] keys = syntaxKeys(originalSyntax);
- boolean hasAllKeys = properties.keySet().containsAll(Arrays.asList(keys));
-
- // build endpoint uri
- StringBuilder sb = new StringBuilder();
- sb.append(scheme);
- sb.append(":");
-
- if (hasAllKeys) {
- // we have all the keys for the syntax so we can build the uri the easy way
- sb.append(syntax);
-
- if (!copy.isEmpty()) {
- boolean hasQuestionmark = sb.toString().contains("?");
- // the last option may already contain a ? char, if so we should use & instead of ?
- sb.append(hasQuestionmark ? ampersand : '?');
- String query = createQueryString(copy, ampersand, encode);
- sb.append(query);
- }
- } else {
- // TODO: revisit this and see if we can do this in another way
- // oh darn some options is missing, so we need a complex way of building the uri
-
- // the tokens between the options in the path
- String[] tokens = syntax.split("\\w+");
-
- // parse the syntax into each options
- Matcher matcher = SYNTAX_PATTERN.matcher(originalSyntax);
- List<String> options = new ArrayList<String>();
- while (matcher.find()) {
- String s = matcher.group(1);
- options.add(s);
- }
-
- // need to preserve {{ and }} from the syntax
- // (we need to use words only as its provisional placeholders)
- syntax = syntax.replaceAll("\\{\\{", "BEGINCAMELPLACEHOLDER");
- syntax = syntax.replaceAll("\\}\\}", "ENDCAMELPLACEHOLDER");
-
- // parse the syntax into each options
- Matcher matcher2 = SYNTAX_PATTERN.matcher(syntax);
- List<String> options2 = new ArrayList<String>();
- while (matcher2.find()) {
- String s = matcher2.group(1);
- s = s.replaceAll("BEGINCAMELPLACEHOLDER", "\\{\\{");
- s = s.replaceAll("ENDCAMELPLACEHOLDER", "\\}\\}");
- options2.add(s);
- }
-
- // build the endpoint
- int range = 0;
- boolean first = true;
- boolean hasQuestionmark = false;
- for (int i = 0; i < options.size(); i++) {
- String key = options.get(i);
- String key2 = options2.get(i);
- String token = null;
- if (tokens.length > i) {
- token = tokens[i];
- }
-
- boolean contains = properties.containsKey(key);
- if (!contains) {
- // if the key are similar we have no explicit value and can try to find a default value if the option is required
- if (isPropertyRequired(rows, key)) {
- String value = getPropertyDefaultValue(rows, key);
- if (value != null) {
- properties.put(key, value);
- key2 = value;
- }
- }
- }
-
- // was the option provided?
- if (properties.containsKey(key)) {
- if (!first && token != null) {
- sb.append(token);
- }
- hasQuestionmark |= key.contains("?") || (token != null && token.contains("?"));
- sb.append(key2);
- first = false;
- }
- range++;
- }
- // append any extra options that was in surplus for the last
- while (range < options2.size()) {
- String token = null;
- if (tokens.length > range) {
- token = tokens[range];
- }
- String key2 = options2.get(range);
- sb.append(token);
- sb.append(key2);
- hasQuestionmark |= key2.contains("?") || (token != null && token.contains("?"));
- range++;
- }
-
-
- if (!copy.isEmpty()) {
- // the last option may already contain a ? char, if so we should use & instead of ?
- sb.append(hasQuestionmark ? ampersand : '?');
- String query = createQueryString(copy, ampersand, encode);
- sb.append(query);
- }
- }
-
- return sb.toString();
- }
-
- @Deprecated
- private static String[] syntaxTokens(String syntax) {
- // build tokens between the words
- List<String> tokens = new ArrayList<>();
- // preserve backwards behavior which had an empty token first
- tokens.add("");
-
- String current = "";
- for (int i = 0; i < syntax.length(); i++) {
- char ch = syntax.charAt(i);
- if (Character.isLetterOrDigit(ch)) {
- // reset for new current tokens
- if (current.length() > 0) {
- tokens.add(current);
- current = "";
- }
- } else {
- current += ch;
- }
- }
- // anything left over?
- if (current.length() > 0) {
- tokens.add(current);
- }
-
- return tokens.toArray(new String[tokens.size()]);
- }
-
- private static String[] syntaxKeys(String syntax) {
- // build tokens between the separators
- List<String> tokens = new ArrayList<>();
-
- String current = "";
- for (int i = 0; i < syntax.length(); i++) {
- char ch = syntax.charAt(i);
- if (Character.isLetterOrDigit(ch)) {
- current += ch;
- } else {
- // reset for new current tokens
- if (current.length() > 0) {
- tokens.add(current);
- current = "";
- }
- }
- }
- // anything left over?
- if (current.length() > 0) {
- tokens.add(current);
- }
-
- return tokens.toArray(new String[tokens.size()]);
- }
-
- public SimpleValidationResult validateSimpleExpression(String simple) {
- return doValidateSimple(null, simple, false);
- }
-
- public SimpleValidationResult validateSimpleExpression(ClassLoader classLoader, String simple) {
- return doValidateSimple(classLoader, simple, false);
- }
-
- public SimpleValidationResult validateSimplePredicate(String simple) {
- return doValidateSimple(null, simple, true);
- }
-
- public SimpleValidationResult validateSimplePredicate(ClassLoader classLoader, String simple) {
- return doValidateSimple(classLoader, simple, true);
- }
-
- private SimpleValidationResult doValidateSimple(ClassLoader classLoader, String simple, boolean predicate) {
- if (classLoader == null) {
- classLoader = getClass().getClassLoader();
- }
-
- // if there are {{ }}} property placeholders then we need to resolve them to something else
- // as the simple parse cannot resolve them before parsing as we dont run the actual Camel application
- // with property placeholders setup so we need to dummy this by replace the {{ }} to something else
- // therefore we use an more unlikely character: {{XXX}} to ~^XXX^~
- String resolved = simple.replaceAll("\\{\\{(.+)\\}\\}", "~^$1^~");
-
- SimpleValidationResult answer = new SimpleValidationResult(simple);
-
- Object instance = null;
- Class clazz = null;
- try {
- clazz = classLoader.loadClass("org.apache.camel.language.simple.SimpleLanguage");
- instance = clazz.newInstance();
- } catch (Exception e) {
- // ignore
- }
-
- if (clazz != null && instance != null) {
- Throwable cause = null;
- try {
- if (predicate) {
- instance.getClass().getMethod("createPredicate", String.class).invoke(instance, resolved);
- } else {
- instance.getClass().getMethod("createExpression", String.class).invoke(instance, resolved);
- }
- } catch (InvocationTargetException e) {
- cause = e.getTargetException();
- } catch (Exception e) {
- cause = e;
- }
-
- if (cause != null) {
-
- // reverse ~^XXX^~ back to {{XXX}}
- String errMsg = cause.getMessage();
- errMsg = errMsg.replaceAll("\\~\\^(.+)\\^\\~", "{{$1}}");
-
- answer.setError(errMsg);
-
- // is it simple parser exception then we can grab the index where the problem is
- if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")
- || cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleParserException")) {
- try {
- // we need to grab the index field from those simple parser exceptions
- Method method = cause.getClass().getMethod("getIndex");
- Object result = method.invoke(cause);
- if (result != null) {
- int index = (int) result;
- answer.setIndex(index);
- }
- } catch (Throwable i) {
- // ignore
- }
- }
-
- // we need to grab the short message field from this simple syntax exception
- if (cause.getClass().getName().equals("org.apache.camel.language.simple.types.SimpleIllegalSyntaxException")) {
- try {
- Method method = cause.getClass().getMethod("getShortMessage");
- Object result = method.invoke(cause);
- if (result != null) {
- String msg = (String) result;
- answer.setShortError(msg);
- }
- } catch (Throwable i) {
- // ignore
- }
-
- if (answer.getShortError() == null) {
- // fallback and try to make existing message short instead
- String msg = answer.getError();
- // grab everything before " at location " which would be regarded as the short message
- int idx = msg.indexOf(" at location ");
- if (idx > 0) {
- msg = msg.substring(0, idx);
- answer.setShortError(msg);
- }
- }
- }
- }
- }
-
- return answer;
- }
-
- public LanguageValidationResult validateLanguagePredicate(ClassLoader classLoader, String language, String text) {
- return doValidateLanguage(classLoader, language, text, true);
- }
-
- public LanguageValidationResult validateLanguageExpression(ClassLoader classLoader, String language, String text) {
- return doValidateLanguage(classLoader, language, text, false);
- }
-
- private LanguageValidationResult doValidateLanguage(ClassLoader classLoader, String language, String text, boolean predicate) {
- if (classLoader == null) {
- classLoader = getClass().getClassLoader();
- }
-
- SimpleValidationResult answer = new SimpleValidationResult(text);
-
- String json = jsonSchemaResolver.getLanguageJSonSchema(language);
- if (json == null) {
- answer.setError("Unknown language " + language);
- return answer;
- }
-
- List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
- String className = null;
- for (Map<String, String> row : rows) {
- if (row.containsKey("javaType")) {
- className = row.get("javaType");
- }
- }
-
- if (className == null) {
- answer.setError("Cannot find javaType for language " + language);
- return answer;
- }
-
- Object instance = null;
- Class clazz = null;
- try {
- clazz = classLoader.loadClass(className);
- instance = clazz.newInstance();
- } catch (Exception e) {
- // ignore
- }
-
- if (clazz != null && instance != null) {
- Throwable cause = null;
- try {
- if (predicate) {
- instance.getClass().getMethod("createPredicate", String.class).invoke(instance, text);
- } else {
- instance.getClass().getMethod("createExpression", String.class).invoke(instance, text);
- }
- } catch (InvocationTargetException e) {
- cause = e.getTargetException();
- } catch (Exception e) {
- cause = e;
- }
-
- if (cause != null) {
- answer.setError(cause.getMessage());
- }
- }
-
- return answer;
- }
-
- /**
- * Special logic for log endpoints to deal when showAll=true
- */
- private Map<String, String> filterProperties(String scheme, Map<String, String> options) {
- if ("log".equals(scheme)) {
- String showAll = options.get("showAll");
- if ("true".equals(showAll)) {
- Map<String, String> filtered = new LinkedHashMap<String, String>();
- // remove all the other showXXX options when showAll=true
- for (Map.Entry<String, String> entry : options.entrySet()) {
- String key = entry.getKey();
- boolean skip = key.startsWith("show") && !key.equals("showAll");
- if (!skip) {
- filtered.put(key, entry.getValue());
- }
- }
- return filtered;
- }
- }
- // use as-is
- return options;
- }
-
- private static boolean validateInteger(String value) {
- boolean valid = false;
- try {
- valid = Integer.valueOf(value) != null;
- } catch (Exception e) {
- // ignore
- }
- if (!valid) {
- // it may be a time pattern, such as 5s for 5 seconds = 5000
- try {
- TimePatternConverter.toMilliSeconds(value);
- valid = true;
- } catch (Exception e) {
- // ignore
- }
- }
- return valid;
- }
-
- // CHECKSTYLE:ON
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java b/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
deleted file mode 100644
index 8d95488..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CamelContextJSonSchemaResolver.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.IOException;
-
-import org.apache.camel.CamelContext;
-
-/**
- * Uses runtime {@link CamelContext} to resolve the JSon schema files.
- */
-public class CamelContextJSonSchemaResolver implements JSonSchemaResolver {
-
- private final CamelContext camelContext;
-
- public CamelContextJSonSchemaResolver(CamelContext camelContext) {
- this.camelContext = camelContext;
- }
-
- @Override
- public String getComponentJSonSchema(String name) {
- try {
- return camelContext.getComponentParameterJsonSchema(name);
- } catch (IOException e) {
- // ignore
- }
- return null;
- }
-
- @Override
- public String getDataFormatJSonSchema(String name) {
- try {
- return camelContext.getDataFormatParameterJsonSchema(name);
- } catch (IOException e) {
- // ignore
- }
- return null;
- }
-
- @Override
- public String getLanguageJSonSchema(String name) {
- try {
- return camelContext.getLanguageParameterJsonSchema(name);
- } catch (IOException e) {
- // ignore
- }
- return null;
- }
-
- @Override
- public String getOtherJSonSchema(String name) {
- // not supported
- return null;
- }
-
- @Override
- public String getModelJSonSchema(String name) {
- try {
- return camelContext.getEipParameterJsonSchema(name);
- } catch (IOException e) {
- // ignore
- }
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java b/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
deleted file mode 100644
index caba4a3..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CatalogHelper.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * 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.catalog;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.util.List;
-
-public final class CatalogHelper {
-
- private CatalogHelper() {
- }
-
- /**
- * Loads the entire stream into memory as a String and returns it.
- * <p/>
- * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
- * terminator at the of the text.
- * <p/>
- * Warning, don't use for crazy big streams :)
- */
- public static void loadLines(InputStream in, List<String> lines) throws IOException {
- try (final InputStreamReader isr = new InputStreamReader(in);
- final BufferedReader reader = new LineNumberReader(isr)) {
- String line;
- while ((line = reader.readLine()) != null) {
- lines.add(line);
- }
- }
- }
-
- /**
- * Loads the entire stream into memory as a String and returns it.
- * <p/>
- * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
- * terminator at the of the text.
- * <p/>
- * Warning, don't use for crazy big streams :)
- */
- public static String loadText(InputStream in) throws IOException {
- StringBuilder builder = new StringBuilder();
- try (final InputStreamReader isr = new InputStreamReader(in);
- final BufferedReader reader = new LineNumberReader(isr)) {
- String line;
- while ((line = reader.readLine()) != null) {
- builder.append(line);
- builder.append("\n");
- }
- return builder.toString();
- }
- }
-
- /**
- * Matches the name with the pattern.
- *
- * @param name the name
- * @param pattern the pattern
- * @return <tt>true</tt> if matched, or <tt>false</tt> if not
- */
- public static boolean matchWildcard(String name, String pattern) {
- // we have wildcard support in that hence you can match with: file* to match any file endpoints
- if (pattern.endsWith("*") && name.startsWith(pattern.substring(0, pattern.length() - 1))) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns the string after the given token
- *
- * @param text the text
- * @param after the token
- * @return the text after the token, or <tt>null</tt> if text does not contain the token
- */
- public static String after(String text, String after) {
- if (!text.contains(after)) {
- return null;
- }
- return text.substring(text.indexOf(after) + after.length());
- }
-
- /**
- * Returns the string before the given token
- *
- * @param text the text
- * @param before the token
- * @return the text before the token, or <tt>null</tt> if text does not contain the token
- */
- public static String before(String text, String before) {
- if (!text.contains(before)) {
- return null;
- }
- return text.substring(0, text.indexOf(before));
- }
-
- /**
- * Returns the string between the given tokens
- *
- * @param text the text
- * @param after the before token
- * @param before the after token
- * @return the text between the tokens, or <tt>null</tt> if text does not contain the tokens
- */
- public static String between(String text, String after, String before) {
- text = after(text, after);
- if (text == null) {
- return null;
- }
- return before(text, before);
- }
-
- /**
- * Tests whether the value is <tt>null</tt> or an empty string.
- *
- * @param value the value, if its a String it will be tested for text length as well
- * @return true if empty
- */
- public static boolean isEmpty(Object value) {
- return !isNotEmpty(value);
- }
-
- /**
- * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
- *
- * @param value the value, if its a String it will be tested for text length as well
- * @return true if <b>not</b> empty
- */
- public static boolean isNotEmpty(Object value) {
- if (value == null) {
- return false;
- } else if (value instanceof String) {
- String text = (String) value;
- return text.trim().length() > 0;
- } else {
- return true;
- }
- }
-
- /**
- * Removes all leading and ending quotes (single and double) from the string
- *
- * @param s the string
- * @return the string without leading and ending quotes (single and double)
- */
- public static String removeLeadingAndEndingQuotes(String s) {
- if (isEmpty(s)) {
- return s;
- }
-
- String copy = s.trim();
- if (copy.startsWith("'") && copy.endsWith("'")) {
- return copy.substring(1, copy.length() - 1);
- }
- if (copy.startsWith("\"") && copy.endsWith("\"")) {
- return copy.substring(1, copy.length() - 1);
- }
-
- // no quotes, so return as-is
- return s;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java b/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
deleted file mode 100644
index 2844ca9..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/CollectionStringBuffer.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * 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.catalog;
-
-public class CollectionStringBuffer {
- private final StringBuilder buffer = new StringBuilder();
- private String separator;
- private boolean first = true;
-
- public CollectionStringBuffer() {
- this(", ");
- }
-
- public CollectionStringBuffer(String separator) {
- this.separator = separator;
- }
-
- @Override
- public String toString() {
- return buffer.toString();
- }
-
- public void append(Object value) {
- if (first) {
- first = false;
- } else {
- buffer.append(separator);
- }
- buffer.append(value);
- }
-
- public String getSeparator() {
- return separator;
- }
-
- public void setSeparator(String separator) {
- this.separator = separator;
- }
-
- public boolean isEmpty() {
- return first;
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/c66be7a8/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java b/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
deleted file mode 100644
index dd66c55..0000000
--- a/camel-core/src/main/java/org/apache/camel/catalog/DefaultRuntimeCamelCatalog.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * 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.catalog;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-
-/**
- * Default {@link RuntimeCamelCatalog}.
- */
-public class DefaultRuntimeCamelCatalog extends AbstractCamelCatalog implements RuntimeCamelCatalog {
-
- // cache of operation -> result
- private final Map<String, Object> cache = new HashMap<String, Object>();
- private boolean caching;
-
- /**
- * Creates the {@link RuntimeCamelCatalog} without caching enabled.
- *
- * @param camelContext the camel context
- */
- public DefaultRuntimeCamelCatalog(CamelContext camelContext) {
- this(camelContext, false);
- }
-
- /**
- * Creates the {@link RuntimeCamelCatalog}
- *
- * @param camelContext the camel context
- * @param caching whether to use cache
- */
- public DefaultRuntimeCamelCatalog(CamelContext camelContext, boolean caching) {
- this.caching = caching;
- setJSonSchemaResolver(new CamelContextJSonSchemaResolver(camelContext));
- }
-
- @Override
- public void start() throws Exception {
- // noop
- }
-
- @Override
- public void stop() throws Exception {
- cache.clear();
- }
-
- @Override
- public String modelJSonSchema(String name) {
- String answer = null;
- if (caching) {
- answer = (String) cache.get("model-" + name);
- }
-
- if (answer == null) {
- answer = getJSonSchemaResolver().getModelJSonSchema(name);
- if (caching) {
- cache.put("model-" + name, answer);
- }
- }
-
- return answer;
- }
-
- @Override
- public String componentJSonSchema(String name) {
- String answer = null;
- if (caching) {
- answer = (String) cache.get("component-" + name);
- }
-
- if (answer == null) {
- answer = getJSonSchemaResolver().getComponentJSonSchema(name);
- if (caching) {
- cache.put("component-" + name, answer);
- }
- }
-
- return answer;
- }
-
- @Override
- public String dataFormatJSonSchema(String name) {
- String answer = null;
- if (caching) {
- answer = (String) cache.get("dataformat-" + name);
- }
-
- if (answer == null) {
- answer = getJSonSchemaResolver().getDataFormatJSonSchema(name);
- if (caching) {
- cache.put("dataformat-" + name, answer);
- }
- }
-
- return answer;
- }
-
- @Override
- public String languageJSonSchema(String name) {
- // if we try to look method then its in the bean.json file
- if ("method".equals(name)) {
- name = "bean";
- }
-
- String answer = null;
- if (caching) {
- answer = (String) cache.get("language-" + name);
- }
-
- if (answer == null) {
- answer = getJSonSchemaResolver().getLanguageJSonSchema(name);
- if (caching) {
- cache.put("language-" + name, answer);
- }
- }
-
- return answer;
- }
-
-}