CAMEL-10795: PingCheck API - includes CAMEL-10923, CAMEL-10924

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/c6d54c03
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/c6d54c03
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/c6d54c03

Branch: refs/heads/master
Commit: c6d54c0349cc41c41c1aa3ff734da1ab9aa02a03
Parents: b27c98c
Author: lburgazzoli <lburgazz...@gmail.com>
Authored: Thu Feb 23 17:15:52 2017 +0100
Committer: lburgazzoli <lburgazz...@gmail.com>
Committed: Fri Mar 10 14:35:59 2017 +0100

----------------------------------------------------------------------
 .../org/apache/camel/ComponentVerifier.java     |  80 ++++++
 .../camel/ComponentVerifierException.java       |  34 +++
 .../apache/camel/IllegalOptionException.java    |  39 +++
 .../org/apache/camel/NoSuchOptionException.java |  29 ++
 .../org/apache/camel/VerifiableComponent.java   |  29 ++
 .../management/mbean/ManagedComponentMBean.java |   4 +
 .../org/apache/camel/impl/DefaultComponent.java |   2 +
 .../impl/verifier/DefaultComponentVerifier.java | 129 +++++++++
 .../camel/impl/verifier/DefaultResult.java      |  57 ++++
 .../camel/impl/verifier/DefaultResultError.java |  66 +++++
 .../camel/impl/verifier/ResultBuilder.java      | 134 +++++++++
 .../camel/impl/verifier/ResultErrorBuilder.java | 164 +++++++++++
 .../camel/impl/verifier/ResultErrorHelper.java  |  43 +++
 .../management/mbean/ManagedComponent.java      |  25 +-
 .../apache/camel/util/IntrospectionSupport.java |   9 +-
 .../camel/util/function/ThrowingBiConsumer.java |  22 ++
 .../camel/util/function/ThrowingConsumer.java   |  22 ++
 .../camel/util/function/ThrowingFunction.java   |  22 ++
 .../camel/util/function/ThrowingHelper.java     |  68 +++++
 .../camel/util/function/ThrowingSupplier.java   |  22 ++
 .../camel/impl/ConfigurationHelperTest.java     |   1 +
 .../camel/impl/EndpointConfigurationTest.java   |   1 +
 .../BlueprintComponentResolverTest.java         |   1 +
 .../core/osgi/OsgiComponentResolverTest.java    |   1 +
 .../component/http/CompositeHttpConfigurer.java |   1 +
 .../camel/component/http/HttpComponent.java     |  13 +-
 .../component/http/HttpComponentVerifier.java   | 250 ++++++++++++++++
 .../component/http/HttpProxyConfigurer.java     |  45 +++
 .../apache/camel/component/http/HttpUtil.java   |  37 +++
 .../http/CamelComponentVerifierTest.java        | 158 +++++++++++
 ...BasicAuthenticationHttpClientConfigurer.java |   4 +-
 .../camel/component/http4/HttpComponent.java    |  13 +-
 .../component/http4/HttpComponentVerifier.java  | 211 ++++++++++++++
 .../apache/camel/component/http4/HttpUtil.java  |  36 +++
 .../http4/ProxyHttpClientConfigurer.java        |   2 +
 .../http4/CamelComponentVerifierTest.java       | 230 +++++++++++++++
 .../camel/component/http4/HttpRedirectTest.java |   1 -
 .../salesforce/SalesforceComponent.java         |  18 +-
 .../salesforce/SalesforceComponentVerifier.java | 190 +++++++++++++
 .../SalesforceComponentVerifierTest.java        | 143 ++++++++++
 .../component/servicenow/ServiceNowClient.java  |  17 +-
 .../servicenow/ServiceNowComponent.java         |  14 +-
 .../servicenow/ServiceNowComponentVerifier.java | 113 ++++++++
 .../servicenow/ServiceNowConfiguration.java     |   2 +-
 .../servicenow/ServiceNowException.java         |  32 ++-
 .../servicenow/ServiceNowExceptionMapper.java   |  68 -----
 .../servicenow/ServiceNowExceptionModel.java    |  27 ++
 .../ServiceNowComponentVerifierTest.java        | 151 ++++++++++
 .../servicenow/ServiceNowTestSupport.java       |  34 ++-
 .../component/twitter/TwitterComponent.java     |  11 +-
 .../twitter/TwitterComponentVerifier.java       |  84 ++++++
 .../component/twitter/TwitterConfiguration.java |   3 +-
 .../twitter/CamelComponentVerifierTest.java     | 107 +++++++
 .../twitter/CamelTwitterTestSupport.java        |  12 +
 .../component/connector/ConnectorModel.java     | 266 +++++++++++++++++
 .../connector/DefaultConnectorComponent.java    | 282 ++++++-------------
 .../tools/apt/EndpointAnnotationProcessor.java  |   9 +
 .../camel/tools/apt/model/ComponentModel.java   |   9 +
 58 files changed, 3291 insertions(+), 306 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java 
b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
new file mode 100644
index 0000000..5628d40
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.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;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface ComponentVerifier {
+    // Todo: should be an enum ?
+    String CODE_EXCEPTION = "exception";
+    String CODE_MISSING_OPTION = "missing-option";
+    String CODE_ILLEGAL_OPTION = "illegal-option";
+    String CODE_ILLEGAL_OPTION_VALUE = "illegal-option-value";
+    String CODE_UNSUPPORTED = "unsupported";
+    String CODE_UNSUPPORTED_SCOPE = "unsupported-scope";
+    String ERROR_TYPE_ATTRIBUTE = "error.type";
+    String ERROR_TYPE_EXCEPTION = "exception";
+    String ERROR_TYPE_HTTP = "http";
+    String HTTP_CODE = "http.code";
+    String HTTP_TEXT = "http.text";
+    String HTTP_REDIRECT = "http.redirect";
+    String HTTP_REDIRECT_LOCATION = "http.redirect.location";
+    String EXCEPTION_CLASS = "exception.class";
+    String EXCEPTION_INSTANCE = "exception.instance";
+
+    enum Scope {
+        NONE,
+        PARAMETERS,
+        CONNECTIVITY
+    }
+
+    /**
+     * Represent an error
+     */
+    interface Error extends Serializable {
+        String getCode();
+        String getDescription();
+        Set<String> getParameters();
+        Map<String, Object> getAttributes();
+    }
+
+    /**
+     * Represent a Result
+     */
+    interface Result extends Serializable {
+        enum Status {
+            OK,
+            ERROR,
+            UNSUPPORTED
+        }
+
+        Scope getScope();
+        Status getStatus();
+        List<Error> getErrors();
+    }
+
+    /**
+     * TODO: document
+     * @param parameters
+     * @param scope
+     * @return
+     */
+    Result verify(Scope scope, Map<String, Object> parameters);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java 
b/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java
new file mode 100644
index 0000000..358498b
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.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;
+
+public class ComponentVerifierException extends CamelException {
+    public ComponentVerifierException() {
+    }
+
+    public ComponentVerifierException(String message) {
+        super(message);
+    }
+
+    public ComponentVerifierException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ComponentVerifierException(Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java 
b/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
new file mode 100644
index 0000000..527eb9d
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java
@@ -0,0 +1,39 @@
+/**
+ * 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;
+
+public class IllegalOptionException extends ComponentVerifierException {
+    private final String optionName;
+    private final String optionValue;
+
+    public IllegalOptionException(String optionName) {
+        this(optionName, null);
+    }
+
+    public IllegalOptionException(String optionName, String optionValue) {
+        this.optionName = optionName;
+        this.optionValue = optionValue;
+    }
+
+    public String getOptionName() {
+        return optionName;
+    }
+
+    public String getOptionValue() {
+        return optionValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java 
b/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
new file mode 100644
index 0000000..3f1d561
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+public class NoSuchOptionException extends ComponentVerifierException {
+    private final String optionName;
+
+    public NoSuchOptionException(String optionName) {
+        this.optionName = optionName;
+    }
+
+    public String getOptionName() {
+        return optionName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java 
b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
new file mode 100644
index 0000000..26df848
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+/**
+ * TODO: document
+ */
+public interface VerifiableComponent {
+    /**
+     * TODO: document
+     *
+     * @return a Component Verifier
+     */
+    ComponentVerifier getVerifier();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedComponentMBean.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedComponentMBean.java
 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedComponentMBean.java
index 2816f07..79ebd2e 100644
--- 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedComponentMBean.java
+++ 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedComponentMBean.java
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.api.management.mbean;
 
+import java.util.Map;
 import javax.management.openmbean.TabularData;
 
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.api.management.ManagedAttribute;
 import org.apache.camel.api.management.ManagedOperation;
 
@@ -41,4 +43,6 @@ public interface ManagedComponentMBean {
     @ManagedOperation(description = "Explain how this component is configured")
     TabularData explain(boolean allOptions);
 
+    @ManagedOperation(description = "Verify options against a given scope")
+    ComponentVerifier.Result verify(String scope, Map<String, String> options);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java 
b/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
index 7824a3c..9c97c2b 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultComponent.java
@@ -138,12 +138,14 @@ public abstract class DefaultComponent extends 
ServiceSupport implements Compone
         return new DefaultComponentConfiguration(this);
     }
 
+    @Override
     public EndpointConfiguration createConfiguration(String uri) throws 
Exception {
         MappedEndpointConfiguration config = new 
MappedEndpointConfiguration(getCamelContext());
         config.setURI(new URI(uri));
         return config;
     }
 
+    @Override
     public boolean useRawUri() {
         // should use encoded uri by default
         return false;

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/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
new file mode 100644
index 0000000..a799056
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
@@ -0,0 +1,129 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.NoSuchOptionException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.EndpointHelper;
+import org.apache.camel.util.IntrospectionSupport;
+
+public class DefaultComponentVerifier implements ComponentVerifier, 
CamelContextAware {
+    public static final ComponentVerifier INSTANCE = new 
DefaultComponentVerifier();
+
+    private CamelContext camelContext;
+
+    public DefaultComponentVerifier() {
+    }
+
+    public DefaultComponentVerifier(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public Result verify(Scope scope, Map<String, Object> parameters) {
+        switch (scope) {
+        case PARAMETERS:
+            return verifyParameters(parameters);
+        case CONNECTIVITY:
+            return verifyConnectivity(parameters);
+        default:
+            throw new IllegalArgumentException("Unsupported Verifier scope: " 
+ scope);
+        }
+    }
+
+    // *************************************
+    // Implementation
+    // *************************************
+
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        return new ResultBuilder().scope(Scope.PARAMETERS).build();
+    }
+
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        return new ResultBuilder().scope(Scope.CONNECTIVITY).build();
+    }
+
+    // *************************************
+    // Helpers
+    // *************************************
+
+    protected <T> T setProperties(T instance, Map<String, Object> properties) 
throws Exception {
+        if (camelContext == null) {
+            throw new IllegalStateException("Camel context is null");
+        }
+
+        if (!properties.isEmpty()) {
+            final CamelContext context = getCamelContext();
+            final TypeConverter converter = context.getTypeConverter();
+
+            IntrospectionSupport.setProperties(converter, instance, 
properties);
+
+            for (Map.Entry<String, Object> entry : properties.entrySet()) {
+                if (entry.getValue() instanceof String) {
+                    String value = (String)entry.getValue();
+                    if (EndpointHelper.isReferenceParameter(value)) {
+                        IntrospectionSupport.setProperty(context, converter, 
instance, entry.getKey(), null, value, true);
+                    }
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    protected <T> T setProperties(T instance, String prefix, Map<String, 
Object> properties) throws Exception {
+        return setProperties(
+            instance,
+            IntrospectionSupport.extractProperties(properties, prefix, false)
+        );
+    }
+
+    protected <T> Optional<T> getOption(Map<String, Object> parameters, String 
key, Class<T> type) {
+        Object value = parameters.get(key);
+        if (value != null) {
+            return 
Optional.ofNullable(CamelContextHelper.convertTo(getCamelContext(), type, 
value));
+        }
+
+        return Optional.empty();
+    }
+
+    protected <T> T getOption(Map<String, Object> parameters, String key, 
Class<T> type, Supplier<T> defaultSupplier) {
+        return getOption(parameters, key, type).orElseGet(defaultSupplier);
+    }
+
+    protected <T> T getMandatoryOption(Map<String, Object> parameters, String 
key, Class<T> type) throws NoSuchOptionException {
+        return getOption(parameters, key, type).orElseThrow(() ->  new 
NoSuchOptionException(key));
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
new file mode 100644
index 0000000..a2742a0
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.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.impl.verifier;
+
+import java.util.List;
+
+import org.apache.camel.ComponentVerifier;
+
+public class DefaultResult implements ComponentVerifier.Result {
+    private final ComponentVerifier.Scope scope;
+    private final Status status;
+    private final List<ComponentVerifier.Error> errors;
+
+    public DefaultResult(ComponentVerifier.Scope scope, Status status, 
List<ComponentVerifier.Error> errors) {
+        this.scope = scope;
+        this.status = status;
+        this.errors = errors;
+    }
+
+    @Override
+    public ComponentVerifier.Scope getScope() {
+        return scope;
+    }
+
+    @Override
+    public Status getStatus() {
+        return status;
+    }
+
+    @Override
+    public List<ComponentVerifier.Error> getErrors() {
+        return errors;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultResult{" +
+            "scope=" + scope +
+            ", status=" + status +
+            ", errors=" + errors +
+            '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
new file mode 100644
index 0000000..b4bfa8c
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
@@ -0,0 +1,66 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.ComponentVerifier;
+
+public class DefaultResultError implements ComponentVerifier.Error {
+    private final String code;
+    private final String description;
+    private final Set<String> parameters;
+    private final Map<String, Object> attributes;
+
+    public DefaultResultError(String code, String description, Set<String> 
parameters, Map<String, Object> attributes) {
+        this.code = code;
+        this.description = description;
+        this.parameters = parameters;
+        this.attributes = attributes;
+    }
+
+    @Override
+    public String getCode() {
+        return code;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public Set<String> getParameters() {
+        return parameters;
+    }
+
+    @Override
+    public Map<String, Object> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultResultError{" +
+            "code='" + code + '\'' +
+            ", description='" + description + '\'' +
+            ", parameters=" + parameters +
+            ", attributes=" + attributes +
+            '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
new file mode 100644
index 0000000..6a42a14
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
@@ -0,0 +1,134 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.IllegalOptionException;
+import org.apache.camel.NoSuchOptionException;
+import org.apache.camel.util.function.ThrowingBiConsumer;
+import org.apache.camel.util.function.ThrowingConsumer;
+
+public final class ResultBuilder {
+    private Optional<ComponentVerifier.Scope> scope;
+    private Optional<ComponentVerifier.Result.Status> status;
+    private List<ComponentVerifier.Error> errors;
+
+    public ResultBuilder() {
+        this.scope = Optional.empty();
+        this.status = scope.empty();
+    }
+
+    // **********************************
+    // Accessors
+    // **********************************
+
+    public ResultBuilder scope(ComponentVerifier.Scope scope) {
+        this.scope = Optional.of(scope);
+        return this;
+    }
+
+    public ResultBuilder status(ComponentVerifier.Result.Status status) {
+        this.status = Optional.of(status);
+        return this;
+    }
+
+    public ResultBuilder error(ComponentVerifier.Error error) {
+        if (this.errors == null) {
+            this.errors = new ArrayList<>();
+        }
+
+        this.errors.add(error);
+        this.status = Optional.of(ComponentVerifier.Result.Status.ERROR);
+
+        return this;
+    }
+
+    public ResultBuilder error(Optional<ComponentVerifier.Error> error) {
+        error.ifPresent(e -> error(e));
+        return this;
+    }
+
+    public ResultBuilder error(Supplier<Optional<ComponentVerifier.Error>> 
supplier) {
+        return error(supplier.get());
+    }
+
+    public ResultBuilder error(ThrowingConsumer<ResultBuilder, Exception> 
consumer) {
+        try {
+            consumer.accept(this);
+        } catch (NoSuchOptionException e) {
+            
error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
+        } catch (IllegalOptionException e) {
+            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), 
e.getOptionValue()).build());
+        } catch (Exception e) {
+            error(ResultErrorBuilder.withException(e).build());
+        }
+
+        return this;
+    }
+
+    public <T> ResultBuilder error(T data, ThrowingBiConsumer<ResultBuilder, 
T, Exception> consumer) {
+        try {
+            consumer.accept(this, data);
+        } catch (NoSuchOptionException e) {
+            
error(ResultErrorBuilder.withMissingOption(e.getOptionName()).build());
+        } catch (IllegalOptionException e) {
+            error(ResultErrorBuilder.withIllegalOption(e.getOptionName(), 
e.getOptionValue()).build());
+        } catch (Exception e) {
+            error(ResultErrorBuilder.withException(e).build());
+        }
+
+        return this;
+    }
+
+    // **********************************
+    // Build
+    // **********************************
+
+    public ComponentVerifier.Result build() {
+        return new DefaultResult(
+            scope.orElseGet(() -> ComponentVerifier.Scope.NONE),
+            status.orElseGet(() -> 
ComponentVerifier.Result.Status.UNSUPPORTED),
+            errors != null ? Collections.unmodifiableList(errors) : 
Collections.emptyList()
+        );
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    public static ResultBuilder withStatus(ComponentVerifier.Result.Status 
status) {
+        return new ResultBuilder().status(status);
+    }
+
+    public static ResultBuilder 
withStatusAndScope(ComponentVerifier.Result.Status status, 
ComponentVerifier.Scope scope) {
+        return new ResultBuilder().status(status).scope(scope);
+    }
+
+    public static ResultBuilder withScope(ComponentVerifier.Scope scope) {
+        return new ResultBuilder().scope(scope);
+    }
+
+    public static ResultBuilder unsupported() {
+        return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, 
ComponentVerifier.Scope.NONE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
new file mode 100644
index 0000000..58eb5ea
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
@@ -0,0 +1,164 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.util.ObjectHelper;
+
+public final class ResultErrorBuilder {
+    private String code;
+    private String description;
+    private Set<String> parameters;
+    private Map<String, Object> attributes;
+
+    public ResultErrorBuilder() {
+    }
+
+    // **********************************
+    // Accessors
+    // **********************************
+
+    public ResultErrorBuilder code(String code) {
+        this.code = code;
+        return this;
+    }
+
+    public ResultErrorBuilder description(String description) {
+        this.description = description;
+        return this;
+    }
+
+    public ResultErrorBuilder parameter(String parameter) {
+        if (parameter != null) {
+            if (this.parameters == null) {
+                this.parameters = new HashSet<>();
+            }
+
+            this.parameters.add(parameter);
+        }
+        return this;
+    }
+
+    public ResultErrorBuilder parameters(Collection<String> parameterList) {
+        if (parameterList != null) {
+            parameterList.forEach(this::parameter);
+        }
+
+        return this;
+    }
+
+    public ResultErrorBuilder attribute(String key, Object value) {
+        if (value != null) {
+            if (this.attributes == null) {
+                this.attributes = new HashMap<>();
+            }
+
+            this.attributes.put(key, value);
+        }
+        return this;
+    }
+
+    public <T> ResultErrorBuilder attribute(String key, Supplier<Optional<T>> 
supplier) {
+        supplier.get().ifPresent(value -> attribute(key, value));
+        return this;
+    }
+
+    // **********************************
+    // Build
+    // **********************************
+
+    public ComponentVerifier.Error build() {
+        return new DefaultResultError(
+            code,
+            description,
+            parameters != null ? Collections.unmodifiableSet(parameters) : 
Collections.emptySet(),
+            attributes != null ? Collections.unmodifiableMap(attributes) : 
Collections.emptyMap()
+        );
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    public static ResultErrorBuilder withCode(String code) {
+        return new ResultErrorBuilder().code(code);
+    }
+
+    public static ResultErrorBuilder withHttpCode(int code) {
+        return withCode(Integer.toString(code))
+            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, 
ComponentVerifier.ERROR_TYPE_HTTP)
+            .attribute(ComponentVerifier.HTTP_CODE, code);
+    }
+
+    public static ResultErrorBuilder withHttpCodeAndText(int code, String 
text) {
+        return withCodeAndDescription(Integer.toString(code), text)
+            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, 
ComponentVerifier.ERROR_TYPE_HTTP)
+            .attribute(ComponentVerifier.HTTP_CODE, code)
+            .attribute(ComponentVerifier.HTTP_TEXT, text);
+    }
+
+    public static ResultErrorBuilder withCodeAndDescription(String code, 
String description) {
+        return new ResultErrorBuilder().code(code).description(description);
+    }
+
+    public static ResultErrorBuilder withUnsupportedScope(String scope) {
+        return new ResultErrorBuilder()
+            .code(ComponentVerifier.CODE_UNSUPPORTED_SCOPE)
+            .description("Unsupported scope: " + scope);
+    }
+
+    public static ResultErrorBuilder withException(Exception exception) {
+        return new ResultErrorBuilder()
+            .code(ComponentVerifier.CODE_EXCEPTION)
+            .description(exception.getMessage())
+            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, 
ComponentVerifier.ERROR_TYPE_EXCEPTION)
+            .attribute(ComponentVerifier.EXCEPTION_INSTANCE, exception)
+            .attribute(ComponentVerifier.EXCEPTION_CLASS, 
exception.getClass().getName());
+    }
+
+    public static ResultErrorBuilder withMissingOption(String optionName) {
+        return new ResultErrorBuilder()
+            .code(ComponentVerifier.CODE_MISSING_OPTION)
+            .description(optionName + " should be set")
+            .parameter(optionName);
+    }
+
+    public static ResultErrorBuilder withIllegalOption(String optionName) {
+        return new ResultErrorBuilder()
+            .code(ComponentVerifier.CODE_ILLEGAL_OPTION)
+            .description("Illegal option " + optionName)
+            .parameter(optionName);
+    }
+
+    public static ResultErrorBuilder withIllegalOption(String optionName, 
String optionValue) {
+        return ObjectHelper.isNotEmpty(optionValue)
+            ? new ResultErrorBuilder()
+                .code(ComponentVerifier.CODE_ILLEGAL_OPTION_VALUE)
+                .description(optionName + " has wrong value (" + optionValue + 
")")
+                .parameter(optionName)
+            : withIllegalOption(optionName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
new file mode 100644
index 0000000..2481b40
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
@@ -0,0 +1,43 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.util.ObjectHelper;
+
+public final class ResultErrorHelper {
+
+    private ResultErrorHelper() {
+    }
+
+    // **********************************
+    // Helpers
+    // **********************************
+
+    public static Optional<ComponentVerifier.Error> requiresOption(String 
parameterName, Map<String, Object> parameters) {
+        if (ObjectHelper.isEmpty(parameters.get(parameterName))) {
+            return Optional.of(
+                ResultErrorBuilder.withMissingOption(parameterName).build()
+            );
+        }
+
+        return Optional.empty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
index 4ca9df9..37a3f65 100644
--- 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
+++ 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedComponent.java
@@ -19,7 +19,6 @@ package org.apache.camel.management.mbean;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
-
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
 import javax.management.openmbean.CompositeType;
@@ -27,12 +26,16 @@ import javax.management.openmbean.TabularData;
 import javax.management.openmbean.TabularDataSupport;
 
 import org.apache.camel.Component;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.ServiceStatus;
 import org.apache.camel.StatefulService;
+import org.apache.camel.VerifiableComponent;
 import org.apache.camel.api.management.ManagedInstance;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
 import org.apache.camel.api.management.mbean.ManagedComponentMBean;
+import org.apache.camel.impl.verifier.ResultBuilder;
+import org.apache.camel.impl.verifier.ResultErrorBuilder;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.JsonSchemaHelper;
 import org.apache.camel.util.ObjectHelper;
@@ -135,4 +138,24 @@ public class ManagedComponent implements ManagedInstance, 
ManagedComponentMBean
         }
     }
 
+    @Override
+    public ComponentVerifier.Result verify(String scope, Map<String, String> 
options) {
+        try {
+            ComponentVerifier.Scope scopeEnum = 
ComponentVerifier.Scope.valueOf(scope);
+
+            if (component instanceof VerifiableComponent) {
+                @SuppressWarnings("unchecked")
+                final Map<String, Object> properties = (Map)options;
+
+                return ((VerifiableComponent) 
component).getVerifier().verify(scopeEnum, properties);
+            } else {
+                return ResultBuilder.unsupported().build();
+            }
+        } catch (IllegalArgumentException e) {
+            return 
ResultBuilder.withStatus(ComponentVerifier.Result.Status.UNSUPPORTED)
+                .error(ResultErrorBuilder.withUnsupportedScope(scope).build())
+                .build();
+
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java 
b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 37d0edc..c3a7258 100755
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -431,6 +431,10 @@ public final class IntrospectionSupport {
     }
 
     public static Map<String, Object> extractProperties(Map<String, Object> 
properties, String optionPrefix) {
+        return extractProperties(properties, optionPrefix, true);
+    }
+
+    public static Map<String, Object> extractProperties(Map<String, Object> 
properties, String optionPrefix, boolean remove) {
         ObjectHelper.notNull(properties, "properties");
 
         Map<String, Object> rc = new LinkedHashMap<String, 
Object>(properties.size());
@@ -442,7 +446,10 @@ public final class IntrospectionSupport {
                 Object value = properties.get(name);
                 name = name.substring(optionPrefix.length());
                 rc.put(name, value);
-                it.remove();
+
+                if (remove) {
+                    it.remove();
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/function/ThrowingBiConsumer.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/function/ThrowingBiConsumer.java
 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingBiConsumer.java
new file mode 100644
index 0000000..9b03a70
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingBiConsumer.java
@@ -0,0 +1,22 @@
+/**
+ * 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.function;
+
+@FunctionalInterface
+public interface ThrowingBiConsumer<I1, I2, T extends Throwable> {
+    void accept(I1 i1, I2 i2) throws T;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/function/ThrowingConsumer.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/function/ThrowingConsumer.java 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingConsumer.java
new file mode 100644
index 0000000..82ee722
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingConsumer.java
@@ -0,0 +1,22 @@
+/**
+ * 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.function;
+
+@FunctionalInterface
+public interface ThrowingConsumer<I, T extends Throwable> {
+    void accept(I in) throws T;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/function/ThrowingFunction.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/function/ThrowingFunction.java 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingFunction.java
new file mode 100644
index 0000000..e7f2433
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingFunction.java
@@ -0,0 +1,22 @@
+/**
+ * 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.function;
+
+@FunctionalInterface
+public interface ThrowingFunction<I, R, T extends Throwable> {
+    R apply(I in) throws T;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/function/ThrowingHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/function/ThrowingHelper.java 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingHelper.java
new file mode 100644
index 0000000..75a3246
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingHelper.java
@@ -0,0 +1,68 @@
+/**
+ * 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.function;
+
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public final class ThrowingHelper {
+    private ThrowingHelper() {
+    }
+
+    public static <V, T extends Throwable> Supplier<V> 
wrapAsSupplier(ThrowingSupplier<V, T> supplier) {
+        return () -> {
+            try {
+                return supplier.get();
+            } catch (Throwable t) {
+                throw new RuntimeException(t);
+            }
+        };
+    }
+
+    public static <I, T extends Throwable> Consumer<I> 
wrapAsConsumer(ThrowingConsumer<I, T> consumer) {
+        return in -> {
+            try {
+                consumer.accept(in);
+            } catch (Throwable t) {
+                throw new RuntimeException(t);
+            }
+        };
+    }
+
+    public static <I1, I2, T extends Throwable> BiConsumer<I1, I2> 
wrapAsBiConsumer(ThrowingBiConsumer<I1, I2, T> consumer) {
+        return (i1, i2) -> {
+            try {
+                consumer.accept(i1, i2);
+            } catch (Throwable t) {
+                throw new RuntimeException(t);
+            }
+        };
+    }
+
+    public static <I, R, T extends Throwable> Function<I, R> 
wrapAsFunction(ThrowingFunction<I, R, T> function) {
+        return in -> {
+            try {
+                return function.apply(in);
+
+            } catch (Throwable t) {
+                throw new RuntimeException(t);
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/main/java/org/apache/camel/util/function/ThrowingSupplier.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/function/ThrowingSupplier.java 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingSupplier.java
new file mode 100644
index 0000000..ad28a88
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/util/function/ThrowingSupplier.java
@@ -0,0 +1,22 @@
+/**
+ * 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.function;
+
+@FunctionalInterface
+public interface ThrowingSupplier<V, T extends Throwable> {
+    V get() throws T;
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/test/java/org/apache/camel/impl/ConfigurationHelperTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/impl/ConfigurationHelperTest.java 
b/camel-core/src/test/java/org/apache/camel/impl/ConfigurationHelperTest.java
index e4b7737..42887d2 100644
--- 
a/camel-core/src/test/java/org/apache/camel/impl/ConfigurationHelperTest.java
+++ 
b/camel-core/src/test/java/org/apache/camel/impl/ConfigurationHelperTest.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentConfiguration;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.EndpointConfiguration;
 import org.apache.camel.URIField;

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/camel-core/src/test/java/org/apache/camel/impl/EndpointConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/impl/EndpointConfigurationTest.java 
b/camel-core/src/test/java/org/apache/camel/impl/EndpointConfigurationTest.java
index ce08662..383db7f 100644
--- 
a/camel-core/src/test/java/org/apache/camel/impl/EndpointConfigurationTest.java
+++ 
b/camel-core/src/test/java/org/apache/camel/impl/EndpointConfigurationTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.impl;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentConfiguration;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.EndpointConfiguration;
 import org.junit.AfterClass;

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-blueprint/src/test/java/org/apache/camel/blueprint/BlueprintComponentResolverTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-blueprint/src/test/java/org/apache/camel/blueprint/BlueprintComponentResolverTest.java
 
b/components/camel-blueprint/src/test/java/org/apache/camel/blueprint/BlueprintComponentResolverTest.java
index de4ccc0..ee93df1 100644
--- 
a/components/camel-blueprint/src/test/java/org/apache/camel/blueprint/BlueprintComponentResolverTest.java
+++ 
b/components/camel-blueprint/src/test/java/org/apache/camel/blueprint/BlueprintComponentResolverTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.blueprint;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentConfiguration;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.EndpointConfiguration;
 import org.apache.camel.impl.DefaultCamelContext;

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
 
b/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
index 85c667f..59ff0dc 100644
--- 
a/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
+++ 
b/components/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.core.osgi;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ComponentConfiguration;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.EndpointConfiguration;
 import org.apache.camel.component.file.FileComponent;

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/main/java/org/apache/camel/component/http/CompositeHttpConfigurer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/CompositeHttpConfigurer.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/CompositeHttpConfigurer.java
index 9d9cdc1..f5acd1c 100644
--- 
a/components/camel-http/src/main/java/org/apache/camel/component/http/CompositeHttpConfigurer.java
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/CompositeHttpConfigurer.java
@@ -36,6 +36,7 @@ public class CompositeHttpConfigurer implements 
HttpClientConfigurer {
         configurers.remove(configurer);
     }
 
+    @Override
     public void configureHttpClient(HttpClient client) {
         for (HttpClientConfigurer configurer : configurers) {
             configurer.configureHttpClient(client);

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
index b790277..0475465 100644
--- 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
@@ -24,9 +24,11 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Producer;
 import org.apache.camel.ResolveEndpointFailedException;
+import org.apache.camel.VerifiableComponent;
 import org.apache.camel.http.common.HttpBinding;
 import org.apache.camel.http.common.HttpCommonComponent;
 import org.apache.camel.http.common.HttpConfiguration;
@@ -35,7 +37,6 @@ import org.apache.camel.http.common.UrlRewrite;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RestProducerFactory;
-import org.apache.camel.util.CollectionHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IntrospectionSupport;
 import org.apache.camel.util.ObjectHelper;
@@ -51,7 +52,8 @@ import 
org.apache.commons.httpclient.params.HttpConnectionManagerParams;
  * The <a href="http://camel.apache.org/http.html";>HTTP Component</a>
  *
  */
-public class HttpComponent extends HttpCommonComponent implements 
RestProducerFactory {
+@Metadata(label = "verifiers", enums = "PARAMETERS,CONNECTIVITY")
+public class HttpComponent extends HttpCommonComponent implements 
RestProducerFactory, VerifiableComponent {
 
     @Metadata(label = "advanced")
     protected HttpClientConfigurer httpClientConfigurer;
@@ -368,4 +370,11 @@ public class HttpComponent extends HttpCommonComponent 
implements RestProducerFa
         // need to override and call super for component docs
         super.setAllowJavaSerializedObject(allowJavaSerializedObject);
     }
+
+    /**
+     * TODO: document
+     */
+    public ComponentVerifier getVerifier() {
+        return new HttpComponentVerifier(this);
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
new file mode 100644
index 0000000..f9ec8ca
--- /dev/null
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
@@ -0,0 +1,250 @@
+/**
+ * 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.component.http;
+
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.http.common.HttpHelper;
+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.impl.verifier.ResultErrorHelper;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpClientParams;
+
+final class HttpComponentVerifier extends DefaultComponentVerifier {
+    private final HttpComponent component;
+
+    HttpComponentVerifier(HttpComponent component) {
+        super(component.getCamelContext());
+
+        this.component = component;
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+        // The default is success
+        ResultBuilder builder = 
ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS);
+
+        // The httpUri is mandatory
+        builder.error(ResultErrorHelper.requiresOption("httpUri", parameters));
+
+        Optional<String> authMethod = getOption(parameters, "authMethod", 
String.class);
+        if (authMethod.isPresent()) {
+            // If auth method is set, username and password must be provided
+            builder.error(ResultErrorHelper.requiresOption("authUsername", 
parameters));
+            builder.error(ResultErrorHelper.requiresOption("authPassword", 
parameters));
+
+            // Check if the AuthMethod is known
+            AuthMethod auth = 
getCamelContext().getTypeConverter().convertTo(AuthMethod.class, 
authMethod.get());
+            if (auth != AuthMethod.Basic && auth != AuthMethod.Digest && auth 
!= AuthMethod.NTLM) {
+                
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", 
authMethod.get()).build());
+            }
+
+            // If auth method is NTLM, authDomain is mandatory
+            if (auth == AuthMethod.NTLM) {
+                builder.error(ResultErrorHelper.requiresOption("authDomain", 
parameters));
+            }
+        }
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        // Default is success
+        ResultBuilder builder = 
ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+
+        Optional<String> uri = getOption(parameters, "httpUri", String.class);
+        if (!uri.isPresent()) {
+            // lack of httpUri is a blocking issue
+            builder.error(ResultErrorHelper.requiresOption("httpUri", 
parameters));
+        } else {
+            builder.error(parameters, this::verifyHttpConnectivity);
+        }
+
+        return builder.build();
+    }
+
+    private void verifyHttpConnectivity(ResultBuilder builder, Map<String, 
Object> parameters) throws Exception {
+        Optional<String> uri = getOption(parameters, "httpUri", String.class);
+
+        HttpClient httpclient = createHttpClient(builder, parameters);
+        HttpMethod method = new GetMethod(uri.get());
+
+        try {
+            int code = httpclient.executeMethod(method);
+            String okCodes = getOption(parameters, "okStatusCodeRange", 
String.class).orElse("200-299");
+
+            if (!HttpHelper.isStatusCodeOk(code, okCodes)) {
+                if (code == 401) {
+                    // Unauthorized, add authUsername and authPassword to the 
list
+                    // of parameters in error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .parameter("authUsername")
+                            .parameter("authPassword")
+                            .build()
+                    );
+                } else if (code >= 300 && code < 400) {
+                    // redirect
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .parameter("httpUri")
+                            .attribute(ComponentVerifier.HTTP_REDIRECT, true)
+                            
.attribute(ComponentVerifier.HTTP_REDIRECT_LOCATION, () -> 
HttpUtil.responseHeaderValue(method, "location"))
+                            .build()
+                    );
+                } else if (code >= 400) {
+                    // generic http error
+                    builder.error(
+                        ResultErrorBuilder.withHttpCode(code)
+                            .description(method.getStatusText())
+                            .build()
+                    );
+                }
+            }
+        } catch (UnknownHostException e) {
+            builder.error(
+                ResultErrorBuilder.withException(e)
+                    .parameter("httpUri")
+                    .build()
+            );
+        }
+    }
+
+    // *********************************
+    // Helpers
+    // *********************************
+
+    private Optional<HttpClientConfigurer> 
configureAuthentication(ResultBuilder builder, Map<String, Object> parameters) {
+        Optional<String> authMethod = getOption(parameters, "authMethod", 
String.class);
+
+        if (authMethod.isPresent()) {
+            Optional<String> authUsername = getOption(parameters, 
"authUsername", String.class);
+            Optional<String> authPassword = getOption(parameters, 
"authPassword", String.class);
+
+            if (authUsername.isPresent() && authUsername.isPresent()) {
+                AuthMethod auth = 
getCamelContext().getTypeConverter().convertTo(AuthMethod.class, 
authMethod.get());
+                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
+                    return Optional.of(
+                        new BasicAuthenticationHttpClientConfigurer(false, 
authUsername.get(), authPassword.get())
+                    );
+                } else if (auth == AuthMethod.NTLM) {
+                    Optional<String> authDomain = getOption(parameters, 
"authDomain", String.class);
+                    Optional<String> authHost = getOption(parameters, 
"authHost", String.class);
+
+                    if (!authDomain.isPresent()) {
+                        
builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
+                    } else {
+                        return Optional.of(
+                            new NTLMAuthenticationHttpClientConfigurer(false, 
authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
+                        );
+                    }
+                } else {
+                    
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", 
authMethod.get()).build());
+                }
+            } else {
+                builder.error(ResultErrorHelper.requiresOption("authUsername", 
parameters));
+                builder.error(ResultErrorHelper.requiresOption("authPassword", 
parameters));
+            }
+        }
+        return Optional.empty();
+    }
+
+    private Optional<HttpClientConfigurer> configureProxy(ResultBuilder 
builder, Map<String, Object> parameters) {
+        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
+
+        // Add a Proxy
+        Optional<String> proxyHost = getOption(parameters, "proxyAuthHost", 
String.class);
+        if (!proxyHost.isPresent()) {
+            proxyHost = getOption(parameters, "proxyHost", String.class);
+        }
+
+        Optional<Integer> proxyPort = getOption(parameters, "proxyAuthPort", 
Integer.class);
+        if (!proxyPort.isPresent()) {
+            proxyPort = getOption(parameters, "proxyPort", Integer.class);
+        }
+
+        if (proxyHost.isPresent() || proxyPort.isPresent()) {
+            configurer.addConfigurer(new HttpProxyConfigurer(proxyHost, 
proxyPort));
+        }
+
+
+        // Configure proxy auth
+        Optional<String> authMethod = getOption(parameters, "proxyAuthMethod", 
String.class);
+        if (authMethod.isPresent()) {
+            Optional<String> authUsername = getOption(parameters, 
"proxyAuthUsername", String.class);
+            Optional<String> authPassword = getOption(parameters, 
"proxyAuthPassword", String.class);
+
+            if (authUsername.isPresent() && authUsername.isPresent()) {
+                AuthMethod auth = 
getCamelContext().getTypeConverter().convertTo(AuthMethod.class, authMethod);
+                if (auth == AuthMethod.Basic || auth == AuthMethod.Digest) {
+                    configurer.addConfigurer(
+                        new BasicAuthenticationHttpClientConfigurer(false, 
authUsername.get(), authPassword.get())
+                    );
+                } else if (auth == AuthMethod.NTLM) {
+                    Optional<String> authDomain = getOption(parameters, 
"proxyAuthDomain", String.class);
+                    Optional<String> authHost = getOption(parameters, 
"proxyAuthHost", String.class);
+
+                    if (!authDomain.isPresent()) {
+                        
builder.error(ResultErrorBuilder.withMissingOption("authDomain").build());
+                    } else {
+                        return Optional.of(
+                            new NTLMAuthenticationHttpClientConfigurer(false, 
authUsername.get(), authPassword.get(), authDomain.get(), authHost.orElse(null))
+                        );
+                    }
+                } else {
+                    
builder.error(ResultErrorBuilder.withIllegalOption("authMethod", 
authMethod.get()).build());
+                }
+            } else {
+                builder.error(ResultErrorHelper.requiresOption("authUsername", 
parameters));
+                builder.error(ResultErrorHelper.requiresOption("authPassword", 
parameters));
+            }
+        }
+
+        return Optional.of(configurer);
+    }
+
+    private HttpClient createHttpClient(ResultBuilder builder, Map<String, 
Object> parameters) throws Exception {
+        HttpClientParams clientParams = setProperties(new HttpClientParams(), 
"httpClient.", parameters);
+        HttpClient client = new HttpClient(clientParams);
+
+        CompositeHttpConfigurer configurer = new CompositeHttpConfigurer();
+        configureProxy(builder, 
parameters).ifPresent(configurer::addConfigurer);
+        configureAuthentication(builder, 
parameters).ifPresent(configurer::addConfigurer);
+
+        configurer.configureHttpClient(client);
+
+        return client;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProxyConfigurer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProxyConfigurer.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProxyConfigurer.java
new file mode 100644
index 0000000..ae2bd83
--- /dev/null
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpProxyConfigurer.java
@@ -0,0 +1,45 @@
+/**
+ * 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.component.http;
+
+import java.util.Optional;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.ProxyHost;
+
+public class HttpProxyConfigurer implements HttpClientConfigurer {
+    private final Optional<String> proxyHost;
+    private final Optional<Integer> proxyPort;
+
+    public HttpProxyConfigurer(Optional<String> proxyHost) {
+        this(proxyHost, Optional.empty());
+    }
+
+    public HttpProxyConfigurer(Optional<String> proxyHost, Optional<Integer> 
proxyPort) {
+        this.proxyHost = proxyHost;
+        this.proxyPort = proxyPort;
+    }
+
+    @Override
+    public void configureHttpClient(HttpClient client) {
+        if (proxyHost.isPresent() && proxyPort.isPresent()) {
+            client.getHostConfiguration().setProxyHost(new 
ProxyHost(proxyHost.get(), proxyPort.get()));
+        } if (proxyHost.isPresent()) {
+            client.getHostConfiguration().setProxyHost(new 
ProxyHost(proxyHost.get()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/main/java/org/apache/camel/component/http/HttpUtil.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpUtil.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpUtil.java
new file mode 100644
index 0000000..7b3600f
--- /dev/null
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpUtil.java
@@ -0,0 +1,37 @@
+/**
+ * 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.component.http;
+
+import java.util.Optional;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpMethod;
+
+public final class HttpUtil {
+    private HttpUtil() {
+    }
+
+    public static Optional<Header> responseHeader(HttpMethod method, String 
headerName) {
+        return Optional.ofNullable(method.getResponseHeader(headerName));
+    }
+
+    public static Optional<String> responseHeaderValue(HttpMethod method, 
String headerName) {
+        return responseHeader(method, headerName)
+            .map(m -> Optional.ofNullable(m.getValue()))
+            .orElseGet(Optional::empty);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
new file mode 100644
index 0000000..4db9137
--- /dev/null
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
@@ -0,0 +1,158 @@
+/**
+ * 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.component.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.ComponentVerifier;
+import org.apache.camel.component.http.handler.BasicValidationHandler;
+import org.apache.camel.test.AvailablePortFinder;
+import org.eclipse.jetty.server.Server;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class CamelComponentVerifierTest extends BaseHttpTest {
+    private static final String AUTH_USERNAME = "camel";
+    private static final String AUTH_PASSWORD = "password";
+    private static final int PORT = AvailablePortFinder.getNextAvailable();
+
+    private Server localServer;
+    
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        localServer = new Server(PORT);
+        localServer.setHandler(handlers(
+            contextHandler("/basic", new BasicValidationHandler("GET", null, 
null, getExpectedContent()))
+        ));
+
+        localServer.start();
+
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (localServer != null) {
+            localServer.stop();
+        }
+    }
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    // *************************************************
+    // Helpers
+    // *************************************************
+
+    protected String getLocalServerUri(String contextPath) throws Exception {
+        return new StringBuilder()
+            .append("http://";)
+            .append("localhost")
+            .append(":")
+            .append(PORT)
+            .append(contextPath != null ? contextPath : "")
+            .toString();
+    }
+
+    // *************************************************
+    // Tests
+    // *************************************************
+
+    @Test
+    public void testConnectivity() throws Exception {
+        HttpComponent component = context().getComponent("http", 
HttpComponent.class);
+        HttpComponentVerifier verifier = 
(HttpComponentVerifier)component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/basic"));
+
+        ComponentVerifier.Result result = 
verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, 
result.getStatus());
+    }
+
+    @Test
+    public void testConnectivityWithWrongUri() throws Exception {
+        HttpComponent component = context().getComponent("http", 
HttpComponent.class);
+        HttpComponentVerifier verifier = 
(HttpComponentVerifier)component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", "http://www.not-existing-uri.unknown";);
+
+        ComponentVerifier.Result result = 
verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, 
result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifier.Error error = result.getErrors().get(0);
+
+        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, error.getCode());
+        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_EXCEPTION, 
error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
+        Assert.assertTrue(error.getParameters().contains("httpUri"));
+    }
+
+    @Ignore
+    @Test
+    public void testConnectivityWithAuthentication() throws Exception {
+        HttpComponent component = context().getComponent("http", 
HttpComponent.class);
+        HttpComponentVerifier verifier = 
(HttpComponentVerifier)component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/auth"));
+        parameters.put("authUsername", AUTH_USERNAME);
+        parameters.put("authPassword", AUTH_PASSWORD);
+
+        ComponentVerifier.Result result = 
verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.OK, 
result.getStatus());
+    }
+
+    @Ignore
+    @Test
+    public void testConnectivityWithWrongAuthenticationData() throws Exception 
{
+        HttpComponent component = context().getComponent("http", 
HttpComponent.class);
+        HttpComponentVerifier verifier = 
(HttpComponentVerifier)component.getVerifier();
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("httpUri", getLocalServerUri("/auth"));
+        parameters.put("authUsername", "unknown");
+        parameters.put("authPassword", AUTH_PASSWORD);
+
+        ComponentVerifier.Result result = 
verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, 
result.getStatus());
+        Assert.assertEquals(1, result.getErrors().size());
+
+        ComponentVerifier.Error error = result.getErrors().get(0);
+
+        Assert.assertEquals("401", error.getCode());
+        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, 
error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
+        Assert.assertEquals(401, 
error.getAttributes().get(ComponentVerifier.HTTP_CODE));
+        Assert.assertTrue(error.getParameters().contains("authUsername"));
+        Assert.assertTrue(error.getParameters().contains("authPassword"));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/main/java/org/apache/camel/component/http4/BasicAuthenticationHttpClientConfigurer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http4/src/main/java/org/apache/camel/component/http4/BasicAuthenticationHttpClientConfigurer.java
 
b/components/camel-http4/src/main/java/org/apache/camel/component/http4/BasicAuthenticationHttpClientConfigurer.java
index 8671369..42ec06c 100644
--- 
a/components/camel-http4/src/main/java/org/apache/camel/component/http4/BasicAuthenticationHttpClientConfigurer.java
+++ 
b/components/camel-http4/src/main/java/org/apache/camel/component/http4/BasicAuthenticationHttpClientConfigurer.java
@@ -30,8 +30,8 @@ public class BasicAuthenticationHttpClientConfigurer 
implements HttpClientConfig
     private final String host;
 
     public BasicAuthenticationHttpClientConfigurer(String user, String pwd, 
String domain, String host) {
-        username = user;
-        password = pwd;
+        this.username = user;
+        this.password = pwd;
         this.domain = domain;
         this.host = host;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/c6d54c03/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
 
b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
index 9917976..1f84508 100644
--- 
a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
+++ 
b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponent.java
@@ -27,8 +27,10 @@ import java.util.concurrent.TimeUnit;
 import javax.net.ssl.HostnameVerifier;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ComponentVerifier;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Producer;
+import org.apache.camel.VerifiableComponent;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.http.common.HttpBinding;
 import org.apache.camel.http.common.HttpCommonComponent;
@@ -68,7 +70,8 @@ import org.slf4j.LoggerFactory;
  *
  * @version 
  */
-public class HttpComponent extends HttpCommonComponent implements 
RestProducerFactory {
+@Metadata(label = "verifiers", enums = "PARAMETERS,CONNECTIVITY")
+public class HttpComponent extends HttpCommonComponent implements 
RestProducerFactory, VerifiableComponent {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(HttpComponent.class);
 
@@ -551,5 +554,11 @@ public class HttpComponent extends HttpCommonComponent 
implements RestProducerFa
         
         super.doStop();
     }
-    
+
+    /**
+     * TODO: document
+     */
+    public ComponentVerifier getVerifier() {
+        return new HttpComponentVerifier(this);
+    }
 }

Reply via email to