You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2018/10/25 13:45:58 UTC
[camel] 03/03: Merge remote-tracking branch 'origin/master' into
camel-3.x
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 18e3d696e027271f40e5e66b35f4fe072128081f
Merge: 37a077a a287357
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Oct 25 15:18:06 2018 +0200
Merge remote-tracking branch 'origin/master' into camel-3.x
.../src/main/docs/eips/content-filter-eip.adoc | 2 +-
.../src/main/docs/eips/dead-letter-channel.adoc | 50 +--
.../src/main/docs/eips/message-translator.adoc | 2 +-
camel-core/src/main/docs/eips/pipeline-eip.adoc | 97 -----
.../src/main/docs/eips/pipes-and-filters.adoc | 4 +-
.../requestReply-eip.adoc} | 2 +-
.../camel/impl/validator/ProcessorValidator.java | 9 +-
.../impl/validator/ValidatorXmlSchemaTest.java | 70 +++
.../resources/org/apache/camel/impl/validate.xsd | 29 ++
.../java/org/apache/camel/util/URISupport.java | 2 +-
.../camel/converter/crypto/PGPDataFormatUtil.java | 8 +
...va => SpringPGPDataFormatNoPassPhraseTest.java} | 6 +-
.../converter/crypto/SpringPGPDataFormatTest.java | 5 -
.../crypto/SpringPGPDataFormatNoPassPhraseTest.xml | 43 ++
.../camel/component/crypto/camel-private.pgp | Bin 0 -> 2547 bytes
.../apache/camel/component/crypto/camel-public.pgp | Bin 0 -> 1245 bytes
.../config_maps/KubernetesConfigMapsProducer.java | 7 +-
.../producer/KubernetesConfigMapsProducerTest.java | 25 +-
.../src/main/docs/mybatis-component.adoc | 2 +-
.../camel/component/printer/PrinterProducer.java | 2 +-
.../camel/component/printer/PrinterPrintTest.java | 30 ++
docs/user-manual/en/SUMMARY.md | 22 +-
docs/user-manual/en/architecture.adoc | 2 +-
docs/user-manual/en/backlog-tracer.adoc | 115 +++++
docs/user-manual/en/bean-integration.adoc | 2 +-
docs/user-manual/en/binding.adoc | 90 ++++
docs/user-manual/en/data-format.adoc | 4 +-
docs/user-manual/en/defaulterrorhandler.adoc | 6 +-
docs/user-manual/en/download-archives.adoc | 127 ++++++
docs/user-manual/en/download.adoc | 127 ++++++
docs/user-manual/en/error-handling-in-camel.adoc | 12 +-
docs/user-manual/en/exception-clause.adoc | 20 +-
docs/user-manual/en/expression.adoc | 4 +-
docs/user-manual/en/faq.adoc | 201 +++------
...loader-issue-of-servicemix-camel-component.adoc | 43 ++
.../exception-beandefinitionstoreexception.adoc | 50 +++
...ption-javaxnamingnoinitialcontextexception.adoc | 36 ++
...tion-orgapachecamelnosuchendpointexception.adoc | 25 ++
.../faq/exception-orgxmlsaxsaxparseexception.adoc | 26 ++
...an-i-create-a-custom-component-or-endpoint.adoc | 13 +
...on-ip-address-from-the-camel-cxf-consumer-.adoc | 17 +
.../faq/how-can-i-stop-a-route-from-a-route.adoc | 70 +++
...ults-with-stacktraces-when-using-camel-cxf.adoc | 6 +
.../en/faq/how-do-i-configure-endpoints.adoc | 36 +-
...-endpoints-without-the-value-being-encoded.adoc | 16 +
...size-for-producercache-or-producertemplate.adoc | 36 ++
...ximum-endpoint-cache-size-for-camelcontext.adoc | 42 ++
.../en/faq/how-do-i-debug-my-route.adoc | 15 +
docs/user-manual/en/faq/how-do-i-disable-jmx.adoc | 30 ++
.../en/faq/how-do-i-enable-debug-logging.adoc | 33 ++
...reams-when-debug-logging-messages-in-camel.adoc | 55 +++
...en-consuming-for-example-from-a-ftp-server.adoc | 31 ++
...how-do-i-import-rests-from-other-xml-files.adoc | 87 ++++
...ow-do-i-import-routes-from-other-xml-files.adoc | 44 ++
.../faq/how-do-i-invoke-camel-routes-from-jbi.adoc | 34 ++
.../en/faq/how-do-i-let-jetty-match-wildcards.adoc | 31 ++
...ow-do-i-make-my-jms-endpoint-transactional.adoc | 31 ++
.../en/faq/how-do-i-name-my-routes.adoc | 20 +
.../en/faq/how-do-i-restart-camelcontext.adoc | 9 +
...wn-exception-during-processing-an-exchange.adoc | 54 +++
.../how-do-i-retry-failed-messages-forever.adoc | 19 +
...om-a-certain-point-back-or-an-entire-route.adoc | 92 ++++
...-contexttestsupport-class-in-my-unit-tests.adoc | 44 ++
.../how-do-i-run-activemq-and-camel-in-jboss.adoc | 21 +
...chars-when-debug-logging-messages-in-camel.adoc | 54 +++
...do-i-set-the-mep-when-interacting-with-jbi.adoc | 34 ++
...ify-time-period-in-a-human-friendly-syntax.adoc | 55 +++
...h-method-to-use-when-using-beans-in-routes.adoc | 9 +
.../en/faq/how-do-i-use-a-big-uber-jar.adoc | 11 +
.../faq/how-do-i-use-camel-inside-servicemix.adoc | 7 +
.../en/faq/how-do-i-use-java-14-logging.adoc | 20 +
docs/user-manual/en/faq/how-do-i-use-log4j.adoc | 47 ++
.../how-do-i-use-uris-with-parameters-in-xml.adoc | 52 +++
...om-processor-which-sends-multiple-messages.adoc | 51 +++
...direct-event-seda-and-vm-endpoints-compare.adoc | 14 +
...-do-the-timer-and-quartz-endpoints-compare.adoc | 8 +
...how-does-camel-look-up-beans-and-endpoints.adoc | 23 +
.../en/faq/how-does-camel-work-with-activemq.adoc | 2 +-
...hould-i-invoke-my-pojos-or-spring-services.adoc | 22 +
...kage-applications-using-camel-and-activemq.adoc | 22 +
...the-camel-cxf-endpoint-from-osgi-platform-.adoc | 67 +++
...-avoid-sending-some-or-all-message-headers.adoc | 75 ++++
...e-a-static-camel-converter-method-in-scala.adoc | 19 +
...http-protocol-headers-in-the-camel-message.adoc | 44 ++
...end-the-same-message-to-multiple-endpoints.adoc | 34 ++
...-without-touching-the-spring-configuration.adoc | 88 ++++
.../en/faq/how-to-use-a-dynamic-uri-in-to.adoc | 80 ++++
...-extra-camel-componets-in-servicemix-camel.adoc | 73 ++++
...-1x-context-xml-from-apache-camel-web-site.adoc | 42 ++
.../Message-flow-in-Route.png | Bin 0 -> 13415 bytes
.../flow.png | Bin 0 -> 6152 bytes
docs/user-manual/en/faq/is-there-an-ide.adoc | 14 +
...when-adding-and-removing-routes-at-runtime.adoc | 10 +
...-activemq-broker-or-in-another-application.adoc | 36 ++
.../en/faq/using-camel-core-testsjar.adoc | 10 +
.../using-getin-or-getout-methods-on-exchange.adoc | 131 ++++++
...se-when-or-otherwise-in-a-java-camel-route.adoc | 98 +++++
.../en/faq/why-cant-i-use-sign-in-my-password.adoc | 18 +
...o-many-noclassdeffoundexception-on-startup.adoc | 17 +
...my-message-lose-its-headers-during-routing.adoc | 4 +
...use-too-many-threads-with-producertemplate.adoc | 29 ++
...-does-ftp-component-not-download-any-files.adoc | 8 +
.../why-does-maven-not-download-dependencies.adoc | 10 +
...-file-consumer-use-the-camel-error-handler.adoc | 51 +++
...jms-route-only-consume-one-message-at-once.adoc | 21 +
...ge-with-error-handler-not-work-as-expected.adoc | 16 +
.../en/faq/why-is-my-message-body-empty.adoc | 19 +
...is-my-processor-not-showing-up-in-jconsole.adoc | 35 ++
...-the-exception-null-when-i-use-onexception.adoc | 37 ++
.../en/faq/why-use-multiple-camelcontext.adoc | 16 +
docs/user-manual/en/getting-started.adoc | 4 +-
docs/user-manual/en/graceful-shutdown.adoc | 471 +++++++++++++++++++++
.../download.data/camel-box-v1.0-150x200.png | Bin 0 -> 93934 bytes
docs/user-manual/en/jndi.adoc | 22 +
docs/user-manual/en/languages.adoc | 2 +-
docs/user-manual/en/predicate.adoc | 2 +-
docs/user-manual/en/processor.adoc | 4 +-
.../en/release-notes/camel-2170-release.adoc | 28 +-
.../en/release-notes/camel-2180-release.adoc | 44 +-
.../en/release-notes/camel-2190-release.adoc | 14 +-
.../en/release-notes/camel-2200-release.adoc | 14 +-
.../en/release-notes/camel-2210-release.adoc | 14 +-
docs/user-manual/en/route-policy.adoc | 227 ++++++++++
docs/user-manual/en/scripting-languages.adoc | 2 +-
docs/user-manual/en/spring-testing.adoc | 2 +-
docs/user-manual/en/spring.adoc | 4 +-
docs/user-manual/en/uuidgenerator.adoc | 80 ++++
docs/user-manual/en/vtd-xml.adoc | 51 ---
.../resources/fabric8/hazelcast-deployment.yaml | 2 +-
parent/pom.xml | 16 +-
.../camel/generator/swagger/PathVisitor.java | 10 +-
.../swagger/RestDslDefinitionGenerator.java | 2 +-
.../swagger/RestDslSourceCodeGenerator.java | 2 +-
.../generator/swagger/RestDslXmlGenerator.java | 3 +-
.../generator/swagger/RestDslGeneratorTest.java | 2 +
.../generator/swagger/RestDslXmlGeneratorTest.java | 2 +-
.../src/test/resources/MyRestRoute.txt | 2 +-
.../src/test/resources/MyRestRouteFilter.txt | 2 +-
.../src/test/resources/SwaggerPetstore.txt | 2 +-
.../resources/SwaggerPetstoreWithRestComponent.txt | 2 +-
.../SwaggerPetstoreWithRestComponentXml.txt | 2 +-
.../src/test/resources/SwaggerPetstoreXml.txt | 2 +-
142 files changed, 4282 insertions(+), 480 deletions(-)
diff --cc camel-util/src/main/java/org/apache/camel/util/URISupport.java
index 88fd074,0000000..539e416
mode 100644,000000..100644
--- a/camel-util/src/main/java/org/apache/camel/util/URISupport.java
+++ b/camel-util/src/main/java/org/apache/camel/util/URISupport.java
@@@ -1,691 -1,0 +1,691 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.util;
+
+import 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;
+import java.util.regex.Pattern;
+
+/**
+ * URI utilities.
+ */
+public final class URISupport {
+
+ public static final String RAW_TOKEN_START = "RAW(";
+ public static final String RAW_TOKEN_END = ")";
+
+ // Match any key-value pair in the URI query string whose key contains
+ // "passphrase" or "password" or secret key (case-insensitive).
+ // First capture group is the key, second is the value.
+ private static final Pattern SECRETS = Pattern.compile("([?&][^=]*(?:passphrase|password|secretKey)[^=]*)=(RAW\\(.*\\)|[^&]*)",
+ Pattern.CASE_INSENSITIVE);
+
+ // Match the user password in the URI as second capture group
+ // (applies to URI with authority component and userinfo token in the form "user:password").
+ private static final Pattern USERINFO_PASSWORD = Pattern.compile("(.*://.*:)(.*)(@)");
+
+ // Match the user password in the URI path as second capture group
+ // (applies to URI path with authority component and userinfo token in the form "user:password").
+ private static final Pattern PATH_USERINFO_PASSWORD = Pattern.compile("(.*:)(.*)(@)");
+
+ private static final String CHARSET = "UTF-8";
+
+ private URISupport() {
+ // Helper class
+ }
+
+ /**
+ * Removes detected sensitive information (such as passwords) from the URI and returns the result.
+ *
+ * @param uri The uri to sanitize.
+ * @see #SECRETS and #USERINFO_PASSWORD for the matched pattern
+ *
+ * @return Returns null if the uri is null, otherwise the URI with the passphrase, password or secretKey sanitized.
+ */
+ public static String sanitizeUri(String uri) {
+ // use xxxxx as replacement as that works well with JMX also
+ String sanitized = uri;
+ if (uri != null) {
+ sanitized = SECRETS.matcher(sanitized).replaceAll("$1=xxxxxx");
+ sanitized = USERINFO_PASSWORD.matcher(sanitized).replaceFirst("$1xxxxxx$3");
+ }
+ return sanitized;
+ }
+
+ /**
+ * Removes detected sensitive information (such as passwords) from the
+ * <em>path part</em> of an URI (that is, the part without the query
+ * parameters or component prefix) and returns the result.
+ *
+ * @param path the URI path to sanitize
+ * @return null if the path is null, otherwise the sanitized path
+ */
+ public static String sanitizePath(String path) {
+ String sanitized = path;
+ if (path != null) {
+ sanitized = PATH_USERINFO_PASSWORD.matcher(sanitized).replaceFirst("$1xxxxxx$3");
+ }
+ return sanitized;
+ }
+
+ /**
+ * Extracts the scheme specific path from the URI that is used as the remainder option when creating endpoints.
+ *
+ * @param u the URI
+ * @param useRaw whether to force using raw values
+ * @return the remainder path
+ */
+ public static String extractRemainderPath(URI u, boolean useRaw) {
+ String path = useRaw ? u.getRawSchemeSpecificPart() : u.getSchemeSpecificPart();
+
+ // lets trim off any query arguments
+ if (path.startsWith("//")) {
+ path = path.substring(2);
+ }
+ int idx = path.indexOf('?');
+ if (idx > -1) {
+ path = path.substring(0, idx);
+ }
+
+ return path;
+ }
+
+ /**
+ * 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 {
+ return parseQuery(uri, useRaw, 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
+ * @param lenient whether to parse lenient and ignore trailing & markers which has no key or value which can happen when using HTTP components
+ * @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, boolean lenient) throws URISyntaxException {
+ // must check for trailing & as the uri.split("&") will ignore those
+ if (!lenient) {
+ if (uri != null && uri.endsWith("&")) {
+ throw new URISyntaxException(uri, "Invalid uri syntax: Trailing & marker found. "
+ + "Check the uri and remove the trailing & marker.");
+ }
+ }
+
+ if (uri == null || ObjectHelper.isEmpty(uri)) {
+ // return an empty map
+ return new LinkedHashMap<>(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<>();
+
+ 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
+ addParameter(key.toString(), 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) {
+ addParameter(key.toString(), value.toString(), rc, useRaw || isRaw);
+ }
+
+ return rc;
+
+ } catch (UnsupportedEncodingException e) {
+ URISyntaxException se = new URISyntaxException(e.toString(), "Invalid encoding");
+ se.initCause(e);
+ throw se;
+ }
+ }
+
+ 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
+ String s = StringHelper.replaceAll(value, "%", "%25");
+ value = URLDecoder.decode(s, 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 = CastUtils.cast((List<?>) existing);
+ } else {
+ // create a new list to hold the multiple values
+ list = new ArrayList<>();
+ 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);
+ }
+ }
+
+ /**
+ * 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<>(0);
+ } else {
+ query = schemeSpecificPart.substring(idx + 1);
+ }
+ } else {
+ query = stripPrefix(query, "?");
+ }
+ return parseQuery(query);
+ }
+
+ /**
+ * Traverses the given parameters, and resolve any parameter values which uses the RAW token
+ * syntax: <tt>key=RAW(value)</tt>. This method will then remove the RAW tokens, and replace
+ * the content of the value, with just the value.
+ *
+ * @param parameters the uri parameters
+ * @see #parseQuery(String)
+ * @see #RAW_TOKEN_START
+ * @see #RAW_TOKEN_END
+ */
+ @SuppressWarnings("unchecked")
+ public static void resolveRawParameterValues(Map<String, Object> parameters) {
+ for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+ if (entry.getValue() != null) {
+ // if the value is a list then we need to iterate
+ Object value = entry.getValue();
+ if (value instanceof List) {
+ List list = (List) value;
+ for (int i = 0; i < list.size(); i++) {
+ Object obj = list.get(i);
+ if (obj != null) {
+ String str = obj.toString();
+ if (str.startsWith(RAW_TOKEN_START) && str.endsWith(RAW_TOKEN_END)) {
+ str = str.substring(4, str.length() - 1);
+ // update the string in the list
+ list.set(i, str);
+ }
+ }
+ }
+ } else {
+ String str = entry.getValue().toString();
+ if (str.startsWith(RAW_TOKEN_START) && str.endsWith(RAW_TOKEN_END)) {
+ str = str.substring(4, str.length() - 1);
+ entry.setValue(str);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates a URI with the given query
+ *
+ * @param uri the uri
+ * @param query the query to append to the uri
+ * @return uri with the query appended
+ * @throws URISyntaxException is thrown if uri has invalid syntax.
+ */
+ public static URI createURIWithQuery(URI uri, String query) throws URISyntaxException {
+ ObjectHelper.notNull(uri, "uri");
+
+ // assemble string as new uri and replace parameters with the query instead
+ String s = uri.toString();
+ String before = StringHelper.before(s, "?");
+ if (before == null) {
+ before = StringHelper.before(s, "#");
+ }
+ if (before != null) {
+ s = before;
+ }
+ if (query != null) {
+ s = s + "?" + query;
+ }
+ if ((!s.contains("#")) && (uri.getFragment() != null)) {
+ s = s + "#" + uri.getFragment();
+ }
+
+ return new URI(s);
+ }
+
+ /**
+ * 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 || prefix == null) {
+ return value;
+ }
+
+ if (value.startsWith(prefix)) {
+ return value.substring(prefix.length());
+ }
+
+ return value;
+ }
+
+ /**
+ * Strips the suffix from the value.
+ * <p/>
+ * Returns the value as-is if not ending with the prefix.
+ *
+ * @param value the value
+ * @param suffix the suffix to remove from value
+ * @return the value without the suffix
+ */
+ public static String stripSuffix(final String value, final String suffix) {
+ if (value == null || suffix == null) {
+ return value;
+ }
+
+ if (value.endsWith(suffix)) {
+ return value.substring(0, value.length() - suffix.length());
+ }
+
+ return value;
+ }
+
+ /**
+ * Assembles a query from the given map.
+ *
+ * @param options the map with the options (eg key/value pairs)
+ * @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.
+ */
+ @SuppressWarnings("unchecked")
+ public static String createQueryString(Map<String, Object> options) 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("&");
+ }
+
+ String key = (String) o;
+ Object value = options.get(key);
+
+ // the value may be a list since the same key has multiple values
+ if (value instanceof List) {
+ List<String> list = (List<String>) value;
+ for (Iterator<String> it = list.iterator(); it.hasNext();) {
+ String s = it.next();
+ appendQueryStringParameter(key, s, rc);
+ // append & separator if there is more in the list to append
+ if (it.hasNext()) {
+ rc.append("&");
+ }
+ }
+ } else {
+ // use the value as a String
+ String s = value != null ? value.toString() : null;
+ appendQueryStringParameter(key, s, rc);
+ }
+ }
+ 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) throws UnsupportedEncodingException {
+ rc.append(URLEncoder.encode(key, CHARSET));
+ // 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 unless it has %
+ // need to replace % with %25 to avoid losing "%" when decoding
+ String s = StringHelper.replaceAll(value, "%", "%25");
+ rc.append(s);
+ } else {
+ rc.append(URLEncoder.encode(value, CHARSET));
+ }
+ }
+ }
+
+ /**
+ * Creates a URI from the original URI and the remaining parameters
+ * <p/>
+ * Used by various Camel components
+ */
+ public static URI createRemainingURI(URI originalURI, Map<String, Object> params) throws URISyntaxException {
+ String s = createQueryString(params);
+ if (s.length() == 0) {
+ s = null;
+ }
+ return createURIWithQuery(originalURI, s);
+ }
+
+ /**
+ * Appends the given parameters to the given URI.
+ * <p/>
+ * It keeps the original parameters and if a new parameter is already defined in
+ * {@code originalURI}, it will be replaced by its value in {@code newParameters}.
+ *
+ * @param originalURI the original URI
+ * @param newParameters the parameters to add
+ * @return the URI with all the parameters
+ * @throws URISyntaxException is thrown if the uri syntax is invalid
+ * @throws UnsupportedEncodingException is thrown if encoding error
+ */
+ public static String appendParametersToURI(String originalURI, Map<String, Object> newParameters) throws URISyntaxException, UnsupportedEncodingException {
+ URI uri = new URI(normalizeUri(originalURI));
+ Map<String, Object> parameters = parseParameters(uri);
+ parameters.putAll(newParameters);
+ return createRemainingURI(uri, parameters).toString();
+ }
+
+ /**
+ * Normalizes the uri by reordering the parameters so they are sorted and thus
+ * we can use the uris for endpoint matching.
+ * <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 normalized uri
+ * @throws URISyntaxException in thrown if the uri syntax is invalid
+ * @throws UnsupportedEncodingException is thrown if encoding error
+ * @see #RAW_TOKEN_START
+ * @see #RAW_TOKEN_END
+ */
+ public static String normalizeUri(String uri) throws URISyntaxException, UnsupportedEncodingException {
+
+ URI u = new URI(UnsafeUriCharactersEncoder.encode(uri, true));
+ String path = u.getSchemeSpecificPart();
+ String scheme = u.getScheme();
+
+ // not possible to normalize
+ if (scheme == null || path == null) {
+ return uri;
+ }
+
+ // lets trim off any query arguments
+ if (path.startsWith("//")) {
+ path = path.substring(2);
+ }
+ int idx = path.indexOf('?');
+ // when the path has ?
+ if (idx != -1) {
+ path = path.substring(0, idx);
+ }
+
+ if (u.getScheme().startsWith("http")) {
+ path = UnsafeUriCharactersEncoder.encodeHttpURI(path);
+ } else {
+ path = UnsafeUriCharactersEncoder.encode(path);
+ }
+
+ // okay if we have user info in the path and they use @ in username or password,
+ // then we need to encode them (but leave the last @ sign before the hostname)
+ // this is needed as Camel end users may not encode their user info properly, but expect
+ // this to work out of the box with Camel, and hence we need to fix it for them
+ String userInfoPath = path;
+ if (userInfoPath.contains("/")) {
+ userInfoPath = userInfoPath.substring(0, userInfoPath.indexOf("/"));
+ }
+ if (StringHelper.countChar(userInfoPath, '@') > 1) {
+ int max = userInfoPath.lastIndexOf('@');
+ String before = userInfoPath.substring(0, max);
+ // after must be from original path
+ String after = path.substring(max);
+
+ // replace the @ with %40
+ before = StringHelper.replaceAll(before, "@", "%40");
+ path = before + after;
+ }
+
+ // in case there are parameters we should reorder them
+ Map<String, Object> parameters = URISupport.parseParameters(u);
+ if (parameters.isEmpty()) {
+ // no parameters then just return
+ return buildUri(scheme, path, null);
+ } else {
+ // reorder parameters a..z
+ List<String> keys = new ArrayList<>(parameters.keySet());
+ keys.sort(null);
+
+ Map<String, Object> sorted = new LinkedHashMap<>(parameters.size());
+ for (String key : keys) {
+ sorted.put(key, parameters.get(key));
+ }
+
+ // build uri object with sorted parameters
+ String query = URISupport.createQueryString(sorted);
+ return buildUri(scheme, path, query);
+ }
+ }
+
+ private static String buildUri(String scheme, String path, String query) {
+ // must include :// to do a correct URI all components can work with
+ return scheme + "://" + path + (query != null ? "?" + query : "");
+ }
+
+ public static Map<String, Object> extractProperties(Map<String, Object> properties, String optionPrefix) {
+ Map<String, Object> rc = new LinkedHashMap<>(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;
+ }
+
+ public static String pathAndQueryOf(final URI uri) {
+ final String path = uri.getPath();
+
+ String pathAndQuery = path;
+ if (ObjectHelper.isEmpty(path)) {
+ pathAndQuery = "/";
+ }
+
+ final String query = uri.getQuery();
+ if (ObjectHelper.isNotEmpty(query)) {
+ pathAndQuery += "?" + query;
+ }
+
+ return pathAndQuery;
+ }
+
+ public static String joinPaths(final String... paths) {
+ if (paths == null || paths.length == 0) {
+ return "";
+ }
+
+ final StringBuilder joined = new StringBuilder();
+
+ boolean addedLast = false;
- for (int i = paths.length -1 ; i >= 0 ; i--) {
++ for (int i = paths.length - 1; i >= 0; i--) {
+ String path = paths[i];
+ if (ObjectHelper.isNotEmpty(path)) {
+ if (addedLast) {
+ path = stripSuffix(path, "/");
+ }
+
+ addedLast = true;
+
+ if (path.charAt(0) == '/') {
+ joined.insert(0, path);
+ } else {
+ if (i > 0) {
+ joined.insert(0, '/').insert(1, path);
+ } else {
+ joined.insert(0, path);
+ }
+ }
+ }
+ }
+
+ return joined.toString();
+ }
+}
diff --cc components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/config_maps/KubernetesConfigMapsProducer.java
index c5ee87c,0bad3f3..0c29a56
--- a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/config_maps/KubernetesConfigMapsProducer.java
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/config_maps/KubernetesConfigMapsProducer.java
@@@ -105,11 -109,16 +105,16 @@@ public class KubernetesConfigMapsProduc
protected void doGetConfigMap(Exchange exchange, String operation) throws Exception {
ConfigMap configMap = null;
String cfMapName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_CONFIGMAP_NAME, String.class);
+ String namespaceName = exchange.getIn().getHeader(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, String.class);
if (ObjectHelper.isEmpty(cfMapName)) {
- LOG.error("Get a specific ConfigMap require specify a ConfigMap name");
+ log.error("Get a specific ConfigMap require specify a ConfigMap name");
throw new IllegalArgumentException("Get a specific ConfigMap require specify a ConfigMap name");
}
- configMap = getEndpoint().getKubernetesClient().configMaps().withName(cfMapName).get();
+ if (namespaceName != null) {
+ configMap = getEndpoint().getKubernetesClient().configMaps().inNamespace(namespaceName).withName(cfMapName).get();
+ } else {
+ configMap = getEndpoint().getKubernetesClient().configMaps().withName(cfMapName).get();
+ }
MessageHelper.copyHeaders(exchange.getIn(), exchange.getOut(), true);
exchange.getOut().setBody(configMap);