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);