diff --git a/camel-core/src/main/java/org/apache/camel/Component.java b/camel-core/src/main/java/org/apache/camel/Component.java index d87347027729a..b21e7a4ac586f 100644 --- a/camel-core/src/main/java/org/apache/camel/Component.java +++ b/camel-core/src/main/java/org/apache/camel/Component.java @@ -16,6 +16,12 @@ */ package org.apache.camel; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + +import org.apache.camel.component.extension.ComponentExtension; + /** * A component is * a factory of {@link Endpoint} objects. @@ -73,4 +79,23 @@ public interface Component extends CamelContextAware { */ @Deprecated ComponentConfiguration createComponentConfiguration(); + + /** + * Gets a list of supported extensions. + * + * @return the list of extensions. + */ + default Collection> getSupportedExtensions() { + return Collections.emptyList(); + } + + /** + * Gets the extension of the given type. + * + * @param extensionType tye type of the extensions + * @return an optional extension + */ + default Optional getExtension(Class extensionType) { + return Optional.empty(); + } } diff --git a/camel-core/src/main/java/org/apache/camel/ComponentAware.java b/camel-core/src/main/java/org/apache/camel/ComponentAware.java new file mode 100644 index 0000000000000..88f7a31862c8c --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/ComponentAware.java @@ -0,0 +1,61 @@ +/** + * 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; + +/** + * An interface to represent an object which wishes to be injected with + * a {@link Component}. + */ +public interface ComponentAware { + + /** + * Injects the {@link Component} + * + * @param component the component + */ + void setComponent(Component component); + + /** + * Get the {@link Component} + * + * @return the component + */ + Component getComponent(); + + /** + * Get the {@link Component} as the specified type. + * + * @param type the proprietary class or interface of the underlying concrete Component. + * @return an instance of the underlying concrete Component as the required type. + * @throws IllegalArgumentException if the component class can't be cast to required type, + */ + default T getComponent(Class type) { + final Component component = getComponent(); + + if (component == null) { + return null; + } + + if (Component.class.isAssignableFrom(type)) { + return type.cast(component); + } + + throw new IllegalArgumentException( + "Unable to unwrap the Component type (" + component.getClass() + ") to the required type (" + type + ")" + ); + } +} diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java index bcbda7ce9187d..d95a7e7d68589 100644 --- a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java +++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java @@ -16,14 +16,9 @@ */ package org.apache.camel; -import java.io.Serializable; -import java.util.List; import java.util.Map; -import java.util.Set; -import org.apache.camel.ComponentVerifierHelper.ExceptionErrorAttribute; -import org.apache.camel.impl.verifier.ResultErrorBuilder; -import org.apache.camel.util.ObjectHelper; +import org.apache.camel.component.extension.ComponentVerifierExtension; /** * Defines the interface used for validating component/endpoint parameters. The central method of this @@ -31,356 +26,8 @@ *

* The return value is a {@link Result} of the verification * + * @deprecated use {@link ComponentVerifierExtension} */ -public interface ComponentVerifier { - - /** - * Verify the given parameters against a provided scope. - * - *

- * The supported scopes are: - *

    - *
  • {@link Scope#PARAMETERS}: to validate that all the mandatory options are provided and syntactically correct.
  • - *
  • {@link Scope#CONNECTIVITY}: to validate that the given options (i.e. credentials, addresses) are correct. Verifying with this - * scope typically implies reaching out to the backend via some sort of network connection.
  • - *
- * - * @param scope the scope of the verification - * @param parameters the parameters to verify which are interpreted individually by each component verifier - * @return the verification result - */ - Result verify(Scope scope, Map parameters); - - /** - * The result of a verification - */ - interface Result extends Serializable { - - /** - * Status of the verification - */ - enum Status { - /** - * Verification succeeded - */ - OK, - /** - * Error occurred during the verification - */ - ERROR, - /** - * Verification is not supported. This can depend on the given scope. - */ - UNSUPPORTED - } - - /** - * Scope of the verification. This is the scope given to the call to {@link #verify(Scope, Map)} and - * can be used for correlation. - * - * @return the scope against which the parameters have been validated. - */ - Scope getScope(); - - /** - * Result of the validation as status. This should be the first datum to check after a verification - * happened. - * - * @return the status - */ - Status getStatus(); - - /** - * Collection of errors happened for the verification. This list is empty (but non null) if the verification - * succeeded. - * - * @return a list of errors. Can be empty when verification was successful - */ - List getErrors(); - } - - /** - * The scope defines how the parameters should be verified. - */ - enum Scope { - /** - * Only validate the parameters for their syntactic soundness. Verifications in this scope should - * be as fast as possible - */ - PARAMETERS, - - /** - * Reach out to the backend and verify that a connection can be established. This means, if the verification - * in this scope succeeds, then it can safely be assumed that the component can be used. - */ - CONNECTIVITY; - - private static final Scope[] VALUES = values(); - - /** - * Get an instance of this scope from a string representation - * - * @param scope the scope as string, which can be in any case - * @return the scope enum represented by this string - */ - public static Scope fromString(String scope) { - for (Scope value : VALUES) { - if (ObjectHelper.equal(scope, value.name(), true)) { - return value; - } - } - throw new IllegalArgumentException("Unknown scope <" + scope + ">"); - } - } - - // ============================================================================================= - - /** - * This interface represents a detailed error in case when the verification fails. - */ - interface VerificationError extends Serializable { - - /** - * The overall error code, which can be either a {@link StandardCode} or a custom code. It is - * recommended to stick to the predefined standard codes - * - * @return the general error code. - */ - Code getCode(); - - /** - * A human readable description of the error in plain english - * - * @return the error description (if available) - */ - String getDescription(); - - /** - * A set of input parameter names which fails the verification. These are keys to the parameter provided - * to {@link #verify(Scope, Map)}. - * - * @return the parameter names which are malformed and caused the failure of the validation - */ - Set getParameterKeys(); - - /** - * Details about the failed verification. The keys can be either predefined values - * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form - * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with - * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores - * as separators) - * - * @return a number of key/value pair with additional information related to the verification. - */ - Map getDetails(); - - /** - * Get a single detail for a given attribute - * - * @param attribute the attribute to lookup - * @return the detail value or null if no such attribute exists - */ - default Object getDetail(Attribute attribute) { - Map details = getDetails(); - if (details != null) { - return details.get(attribute); - } - return null; - } - - /** - * Get a single detail for a given attribute - * - * @param attribute the attribute to lookup - * @return the detail value or null if no such attribute exists - */ - default Object getDetail(String attribute) { - return getDetail(asAttribute(attribute)); - } - - /** - * Convert a string to an {@link Code} - * - * @param code the code to convert. It should be in all lower case (with - * underscore as a separator) to avoid overlap with {@link StandardCode} - * @return error code - */ - static Code asCode(String code) { - return new ComponentVerifierHelper.ErrorCode(code); - } - - /** - * Convert a string to an {@link Attribute} - * - * @param attribute the string representation of an attribute to convert. It should be in all lower case (with - * underscore as a separator) to avoid overlap with standard attributes like {@link ExceptionAttribute}, - * {@link HttpAttribute} or {@link GroupAttribute} - * @return generated attribute - */ - static Attribute asAttribute(String attribute) { - return new ComponentVerifierHelper.ErrorAttribute(attribute); - } - - /** - * Interface defining an error code. This is implemented by the {@link StandardCode} but also - * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)} - * If possible, the standard codes should be reused - */ - interface Code extends Serializable { - /** - * Name of the code. All uppercase for standard codes, all lower case for custom codes. - * Separator between two words is an underscore. - * - * @return code name - */ - String name(); - - /** - * Bean style accessor to name. - * This is required for framework like Jackson using bean convention for object serialization. - * - * @return code name - */ - default String getName() { - return name(); - } - } - - /** - * Standard set of error codes - */ - interface StandardCode extends Code { - /** - * Authentication failed - */ - StandardCode AUTHENTICATION = new ComponentVerifierHelper.StandardErrorCode("AUTHENTICATION"); - /** - * An exception occurred - */ - StandardCode EXCEPTION = new ComponentVerifierHelper.StandardErrorCode("EXCEPTION"); - /** - * Internal error while performing the verification - */ - StandardCode INTERNAL = new ComponentVerifierHelper.StandardErrorCode("INTERNAL"); - /** - * A mandatory parameter is missing - */ - StandardCode MISSING_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("MISSING_PARAMETER"); - /** - * A given parameter is not known to the component - */ - StandardCode UNKNOWN_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("UNKNOWN_PARAMETER"); - /** - * A given parameter is illegal - */ - StandardCode ILLEGAL_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER"); - /** - * A combination of parameters is illegal. See {@link VerificationError#getParameterKeys()} for the set - * of affected parameters - */ - StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION"); - /** - * A parameter value is not valid - */ - StandardCode ILLEGAL_PARAMETER_VALUE = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_VALUE"); - /** - * A group of parameters is not complete in order to be valid - */ - StandardCode INCOMPLETE_PARAMETER_GROUP = new ComponentVerifierHelper.StandardErrorCode("INCOMPLETE_PARAMETER_GROUP"); - /** - * The verification is not supported - */ - StandardCode UNSUPPORTED = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED"); - /** - * The requested {@link Scope} is not supported - */ - StandardCode UNSUPPORTED_SCOPE = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED_SCOPE"); - /** - * The requested {@link Component} is not supported - */ - StandardCode UNSUPPORTED_COMPONENT = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED_COMPONENT"); - /** - * Generic error which is explained in more details with {@link VerificationError#getDetails()} - */ - StandardCode GENERIC = new ComponentVerifierHelper.StandardErrorCode("GENERIC"); - } - - /** - * Interface defining an attribute which is a key for the detailed error messages. This is implemented by several - * standard enums like {@link ExceptionAttribute}, {@link HttpAttribute} or {@link GroupAttribute} but can also - * implemented for component specific details. This is best done via {@link #asAttribute(String)} - * or using one of the other builder method in this error builder (like {@link ResultErrorBuilder#detail(String, Object)} - *

- * With respecting to name, the same rules as for {@link Code} apply: Standard attributes are all upper case with _ - * as separators, whereas custom attributes are lower case with underscore separators. - */ - interface Attribute extends Serializable { - /** - * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes. - * Separator between words is an underscore. - * - * @return attribute name - */ - String name(); - - /** - * Bean style accessor to name; - * This is required for framework like Jackson using bean convention for object serialization. - * - * @return attribute name - */ - default String getName() { - return name(); - } - } - - /** - * Attributes for details about an exception that was raised - */ - interface ExceptionAttribute extends Attribute { - /** - * The exception object that has been thrown. Note that this can be a complex - * object and can cause large content when e.g. serialized as JSON - */ - ExceptionAttribute EXCEPTION_INSTANCE = new ExceptionErrorAttribute("EXCEPTION_INSTANCE"); - /** - * The exception class - */ - ExceptionAttribute EXCEPTION_CLASS = new ExceptionErrorAttribute("EXCEPTION_CLASS"); - } - - /** - * HTTP related error details - */ - interface HttpAttribute extends Attribute { - /** - * The erroneous HTTP code that occurred - */ - HttpAttribute HTTP_CODE = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_CODE"); - /** - * HTTP response's body - */ - HttpAttribute HTTP_TEXT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_TEXT"); - /** - * If given as details, specifies that a redirect happened and the - * content of this detail is the redirect URL - */ - HttpAttribute HTTP_REDIRECT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_REDIRECT"); - } - - /** - * Group related details - */ - interface GroupAttribute extends Attribute { - /** - * Group name - */ - GroupAttribute GROUP_NAME = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_NAME"); - /** - * Options for the group - */ - GroupAttribute GROUP_OPTIONS = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_OPTIONS"); - } - } - +@Deprecated +public interface ComponentVerifier extends ComponentVerifierExtension { } diff --git a/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java index 2b95404f92870..2e2b6f68b8550 100644 --- a/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java +++ b/camel-core/src/main/java/org/apache/camel/VerifiableComponent.java @@ -18,7 +18,10 @@ /** * An interface to represent an object which support validation + * + * @deprecated see {@link org.apache.camel.extension.ComponentExtension} */ +@Deprecated public interface VerifiableComponent { /** * Get the {@link ComponentVerifier} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java new file mode 100644 index 0000000000000..8d90d3193961c --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtension.java @@ -0,0 +1,26 @@ +/** + * 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.extension; + +/** + * Marker interface for component extensions. + *

+ * An extension is a feature provided by the component such as ComponentVerifier, + * ServiceMetaData. + */ +public interface ComponentExtension { +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.java new file mode 100644 index 0000000000000..3487b3cf3cde6 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentExtensionHelper.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.component.extension; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Component; +import org.apache.camel.ComponentAware; + +public final class ComponentExtensionHelper { + private ComponentExtensionHelper() { + } + + public static T trySetCamelContext(T object, CamelContext camelContext) { + if (object instanceof CamelContextAware) { + ((CamelContextAware) object).setCamelContext(camelContext); + } + + return object; + } + + public static T trySetComponent(T object, Component component) { + if (object instanceof ComponentAware) { + ((ComponentAware) object).setComponent(component); + } + + return object; + } +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java new file mode 100644 index 0000000000000..f9acf0e42a11e --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/ComponentVerifierExtension.java @@ -0,0 +1,385 @@ +/** + * 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.extension; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.camel.Component; +import org.apache.camel.component.extension.verifier.ComponentVerifierExtensionHelper; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; +import org.apache.camel.util.ObjectHelper; +/** + * Defines the interface used for validating component/endpoint parameters. The central method of this + * interface is {@link #verify(ComponentVerifierExtension.Scope, Map)} which takes a scope and a set of parameters which should be verified. + *

+ * The return value is a {@link ComponentVerifierExtension.Result} of the verification + * + */ +public interface ComponentVerifierExtension extends ComponentExtension { + + /** + * Verify the given parameters against a provided scope. + * + *

+ * The supported scopes are: + *

    + *
  • {@link ComponentVerifierExtension.Scope#PARAMETERS}: to validate that all the mandatory options are provided and syntactically correct.
  • + *
  • {@link ComponentVerifierExtension.Scope#CONNECTIVITY}: to validate that the given options (i.e. credentials, addresses) are correct. Verifying with this + * scope typically implies reaching out to the backend via some sort of network connection.
  • + *
+ * + * @param scope the scope of the verification + * @param parameters the parameters to verify which are interpreted individually by each component verifier + * @return the verification result + */ + ComponentVerifierExtension.Result verify(ComponentVerifierExtension.Scope scope, Map parameters); + + /** + * The result of a verification + */ + interface Result extends Serializable { + + /** + * Status of the verification + */ + enum Status { + /** + * Verification succeeded + */ + OK, + /** + * Error occurred during the verification + */ + ERROR, + /** + * Verification is not supported. This can depend on the given scope. + */ + UNSUPPORTED + } + + /** + * Scope of the verification. This is the scope given to the call to {@link #verify(ComponentVerifierExtension.Scope, Map)} and + * can be used for correlation. + * + * @return the scope against which the parameters have been validated. + */ + ComponentVerifierExtension.Scope getScope(); + + /** + * Result of the validation as status. This should be the first datum to check after a verification + * happened. + * + * @return the status + */ + ComponentVerifierExtension.Result.Status getStatus(); + + /** + * Collection of errors happened for the verification. This list is empty (but non null) if the verification + * succeeded. + * + * @return a list of errors. Can be empty when verification was successful + */ + List getErrors(); + } + + /** + * The scope defines how the parameters should be verified. + */ + enum Scope { + /** + * Only validate the parameters for their syntactic soundness. Verifications in this scope should + * be as fast as possible + */ + PARAMETERS, + + /** + * Reach out to the backend and verify that a connection can be established. This means, if the verification + * in this scope succeeds, then it can safely be assumed that the component can be used. + */ + CONNECTIVITY; + + private static final ComponentVerifierExtension.Scope[] VALUES = values(); + + /** + * Get an instance of this scope from a string representation + * + * @param scope the scope as string, which can be in any case + * @return the scope enum represented by this string + */ + public static ComponentVerifierExtension.Scope fromString(String scope) { + for (ComponentVerifierExtension.Scope value : VALUES) { + if (ObjectHelper.equal(scope, value.name(), true)) { + return value; + } + } + throw new IllegalArgumentException("Unknown scope <" + scope + ">"); + } + } + + // ============================================================================================= + + /** + * This interface represents a detailed error in case when the verification fails. + */ + interface VerificationError extends Serializable { + + /** + * The overall error code, which can be either a {@link StandardCode} or a custom code. It is + * recommended to stick to the predefined standard codes + * + * @return the general error code. + */ + Code getCode(); + + /** + * A human readable description of the error in plain english + * + * @return the error description (if available) + */ + String getDescription(); + + /** + * A set of input parameter names which fails the verification. These are keys to the parameter provided + * to {@link #verify(ComponentVerifierExtension.Scope, Map)}. + * + * @return the parameter names which are malformed and caused the failure of the validation + */ + Set getParameterKeys(); + + /** + * Details about the failed verification. The keys can be either predefined values + * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form + * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with + * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores + * as separators) + * + * @return a number of key/value pair with additional information related to the verification. + */ + Map getDetails(); + + /** + * Get a single detail for a given attribute + * + * @param attribute the attribute to lookup + * @return the detail value or null if no such attribute exists + */ + default Object getDetail(ComponentVerifierExtension.VerificationError.Attribute attribute) { + Map details = getDetails(); + if (details != null) { + return details.get(attribute); + } + return null; + } + + /** + * Get a single detail for a given attribute + * + * @param attribute the attribute to lookup + * @return the detail value or null if no such attribute exists + */ + default Object getDetail(String attribute) { + return getDetail(asAttribute(attribute)); + } + + /** + * Convert a string to an {@link Code} + * + * @param code the code to convert. It should be in all lower case (with + * underscore as a separator) to avoid overlap with {@link StandardCode} + * @return error code + */ + static Code asCode(String code) { + return new ComponentVerifierExtensionHelper.ErrorCode(code); + } + + /** + * Convert a string to an {@link Attribute} + * + * @param attribute the string representation of an attribute to convert. It should be in all lower case (with + * underscore as a separator) to avoid overlap with standard attributes like {@linkExceptionAttribute}, + * {@linkHttpAttribute} or {@link GroupAttribute} + * @return generated attribute + */ + static Attribute asAttribute(String attribute) { + return new ComponentVerifierExtensionHelper.ErrorAttribute(attribute); + } + + /** + * Interface defining an error code. This is implemented by the {@link StandardCode} but also + * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)} + * If possible, the standard codes should be reused + */ + interface Code extends Serializable { + /** + * Name of the code. All uppercase for standard codes, all lower case for custom codes. + * Separator between two words is an underscore. + * + * @return code name + */ + String name(); + + /** + * Bean style accessor to name. + * This is required for framework like Jackson using bean convention for object serialization. + * + * @return code name + */ + default String getName() { + return name(); + } + } + + /** + * Standard set of error codes + */ + interface StandardCode extends Code { + /** + * Authentication failed + */ + StandardCode AUTHENTICATION = new ComponentVerifierExtensionHelper.StandardErrorCode("AUTHENTICATION"); + /** + * An exception occurred + */ + StandardCode EXCEPTION = new ComponentVerifierExtensionHelper.StandardErrorCode("EXCEPTION"); + /** + * Internal error while performing the verification + */ + StandardCode INTERNAL = new ComponentVerifierExtensionHelper.StandardErrorCode("INTERNAL"); + /** + * A mandatory parameter is missing + */ + StandardCode MISSING_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("MISSING_PARAMETER"); + /** + * A given parameter is not known to the component + */ + StandardCode UNKNOWN_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("UNKNOWN_PARAMETER"); + /** + * A given parameter is illegal + */ + StandardCode ILLEGAL_PARAMETER = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER"); + /** + * A combination of parameters is illegal. See {@link ComponentVerifierExtension.VerificationError#getParameterKeys()} for the set + * of affected parameters + */ + StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION"); + /** + * A parameter value is not valid + */ + StandardCode ILLEGAL_PARAMETER_VALUE = new ComponentVerifierExtensionHelper.StandardErrorCode("ILLEGAL_PARAMETER_VALUE"); + /** + * A group of parameters is not complete in order to be valid + */ + StandardCode INCOMPLETE_PARAMETER_GROUP = new ComponentVerifierExtensionHelper.StandardErrorCode("INCOMPLETE_PARAMETER_GROUP"); + /** + * The verification is not supported + */ + StandardCode UNSUPPORTED = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED"); + /** + * The requested {@link ComponentVerifierExtension.Scope} is not supported + */ + StandardCode UNSUPPORTED_SCOPE = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED_SCOPE"); + /** + * The requested {@link Component} is not supported + */ + StandardCode UNSUPPORTED_COMPONENT = new ComponentVerifierExtensionHelper.StandardErrorCode("UNSUPPORTED_COMPONENT"); + /** + * Generic error which is explained in more details with {@link ComponentVerifierExtension.VerificationError#getDetails()} + */ + StandardCode GENERIC = new ComponentVerifierExtensionHelper.StandardErrorCode("GENERIC"); + } + + /** + * Interface defining an attribute which is a key for the detailed error messages. This is implemented by several + * standard enums like {@link ExceptionAttribute}, {@link HttpAttribute} or {@link GroupAttribute} but can also + * implemented for component specific details. This is best done via {@link #asAttribute(String)} + * or using one of the other builder method in this error builder (like {@link ResultErrorBuilder#detail(String, Object)} + *

+ * With respecting to name, the same rules as for {@link Code} apply: Standard attributes are all upper case with _ + * as separators, whereas custom attributes are lower case with underscore separators. + */ + interface Attribute extends Serializable { + /** + * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes. + * Separator between words is an underscore. + * + * @return attribute name + */ + String name(); + + /** + * Bean style accessor to name; + * This is required for framework like Jackson using bean convention for object serialization. + * + * @return attribute name + */ + default String getName() { + return name(); + } + } + + /** + * Attributes for details about an exception that was raised + */ + interface ExceptionAttribute extends Attribute { + /** + * The exception object that has been thrown. Note that this can be a complex + * object and can cause large content when e.g. serialized as JSON + */ + ExceptionAttribute EXCEPTION_INSTANCE = new ComponentVerifierExtensionHelper.ExceptionErrorAttribute("EXCEPTION_INSTANCE"); + /** + * The exception class + */ + ExceptionAttribute EXCEPTION_CLASS = new ComponentVerifierExtensionHelper.ExceptionErrorAttribute("EXCEPTION_CLASS"); + } + + /** + * HTTP related error details + */ + interface HttpAttribute extends Attribute { + /** + * The erroneous HTTP code that occurred + */ + HttpAttribute HTTP_CODE = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_CODE"); + /** + * HTTP response's body + */ + HttpAttribute HTTP_TEXT = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_TEXT"); + /** + * If given as details, specifies that a redirect happened and the + * content of this detail is the redirect URL + */ + HttpAttribute HTTP_REDIRECT = new ComponentVerifierExtensionHelper.HttpErrorAttribute("HTTP_REDIRECT"); + } + + /** + * Group related details + */ + interface GroupAttribute extends Attribute { + /** + * Group name + */ + GroupAttribute GROUP_NAME = new ComponentVerifierExtensionHelper.GroupErrorAttribute("GROUP_NAME"); + /** + * Options for the group + */ + GroupAttribute GROUP_OPTIONS = new ComponentVerifierExtensionHelper.GroupErrorAttribute("GROUP_OPTIONS"); + } + } +} \ No newline at end of file diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java new file mode 100644 index 0000000000000..9361e6650f12b --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/MetaDataExtension.java @@ -0,0 +1,74 @@ +/** + * 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.extension; + +import java.util.Map; +import java.util.Optional; + +import org.apache.camel.Exchange; +import org.apache.camel.TypeConversionException; + +public interface MetaDataExtension extends ComponentExtension { + /** + * @param parameters + * @return the {@link MetaData} + */ + Optional meta(Map parameters); + + interface MetaData { + // Common meta-data attributes + String CONTENT_TYPE = Exchange.CONTENT_TYPE; + String JAVA_TYPE = "Java-Type"; + + /** + * + * Returns an attribute associated with this meta data by name. + * + * @param name the attribute name + * @return the attribute + */ + Object getAttribute(String name); + + /** + * + * Returns an attribute associated with this meta data by name and + * specifying the type required. + * + * @param name the attribute name + * @param type the type of the attribute + * @return the value of the given attribute or null if there is no attribute for the given name + * @throws TypeConversionException is thrown if error during type conversion + */ + T getAttribute(String name, Class type); + + /** + * Returns the payload of the meta data as a POJO. + * + * @return the body, can be null + */ + Object getPayload(); + + /** + * Returns the payload of the meta data as specified type. + * + * @param type the type that the payload should be converted yo. + * @return the payload of the meta data as the specified type. + * @throws TypeConversionException is thrown if error during type conversion + */ + T getPayload(Class type); + } +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java new file mode 100644 index 0000000000000..c8bd5779f39e8 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/AbstractMetaDataExtension.java @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.extension.metadata; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Component; +import org.apache.camel.ComponentAware; +import org.apache.camel.component.extension.MetaDataExtension; + +public abstract class AbstractMetaDataExtension implements MetaDataExtension, ComponentAware, CamelContextAware { + private CamelContext camelContext; + private Component component; + + protected AbstractMetaDataExtension() { + this(null, null); + } + + protected AbstractMetaDataExtension(Component component) { + this(component, component.getCamelContext()); + } + + protected AbstractMetaDataExtension(CamelContext camelContext) { + this(null, camelContext); + } + + protected AbstractMetaDataExtension(Component component, CamelContext camelContext) { + this.component = component; + this.camelContext = camelContext; + } + + @Override + public void setComponent(Component component) { + this.component = component; + } + + @Override + public Component getComponent() { + return component; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java new file mode 100644 index 0000000000000..b1e2df4b5f5d9 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/DefaultMetaData.java @@ -0,0 +1,63 @@ +/** + * 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.extension.metadata; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.component.extension.MetaDataExtension; + +public class DefaultMetaData implements MetaDataExtension.MetaData { + private final Map attributes; + private final Object payload; + private CamelContext camelContext; + + public DefaultMetaData(CamelContext camelContext, Map attributes, Object payload) { + this.camelContext = camelContext; + this.attributes = attributes; + this.payload = payload; + } + + @Override + public Object getAttribute(String name) { + return attributes.get(name); + } + + @Override + public T getAttribute(String name, Class type) { + Object value = attributes.get(name); + if (camelContext != null) { + return camelContext.getTypeConverter().convertTo(type, value); + } + + throw new IllegalStateException("Unable to perform conversion as CamelContext is not set"); + } + + @Override + public Object getPayload() { + return payload; + } + + @Override + public T getPayload(Class type) { + if (camelContext != null) { + return camelContext.getTypeConverter().convertTo(type, payload); + } + + throw new IllegalStateException("Unable to perform conversion as CamelContext is not set"); + } +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java new file mode 100644 index 0000000000000..0957c64cb9b5c --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/MetaDataBuilder.java @@ -0,0 +1,64 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.extension.metadata; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.component.extension.MetaDataExtension; + +public final class MetaDataBuilder { + private final CamelContext camelContext; + private Object payload; + private Map attributes; + + private MetaDataBuilder(CamelContext camelContext) { + this.camelContext = camelContext; + } + + public MetaDataBuilder withPayload(Object payload) { + this.payload = payload; + return this; + } + + public MetaDataBuilder withAttribute(String name, Object value) { + if (this.attributes == null) { + this.attributes = new HashMap<>(); + } + + this.attributes.put(name, value); + return this; + } + + public MetaDataExtension.MetaData build() { + return new DefaultMetaData( + camelContext, + attributes == null ? Collections.emptyMap() : attributes, + payload + ); + } + + // ***************************** + // + // ***************************** + + public static MetaDataBuilder on(CamelContext camelContext) { + return new MetaDataBuilder(camelContext); + } +} diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html new file mode 100644 index 0000000000000..66873076800ca --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/metadata/package.html @@ -0,0 +1,25 @@ + + + + + + +MetaData component extension + + + diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/package.html new file mode 100644 index 0000000000000..be2383ac3d9ff --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/package.html @@ -0,0 +1,25 @@ + + + + + + +Component extension + + + diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java similarity index 98% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java index 43d69935d9836..e8d256a1a8002 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/CatalogVerifierCustomizer.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/CatalogVerifierCustomizer.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; public class CatalogVerifierCustomizer { private boolean includeUnknown = true; diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java similarity index 92% rename from camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java index 358498b90eb6e..690a5715a5d14 100644 --- a/camel-core/src/main/java/org/apache/camel/ComponentVerifierException.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierException.java @@ -14,7 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel; +package org.apache.camel.component.extension.verifier; + +import org.apache.camel.CamelException; public class ComponentVerifierException extends CamelException { public ComponentVerifierException() { diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java similarity index 63% rename from camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java index 7fc811502ff6a..583ccf714e06a 100644 --- a/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ComponentVerifierExtensionHelper.java @@ -14,25 +14,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel; +package org.apache.camel.component.extension.verifier; -import org.apache.camel.ComponentVerifier.VerificationError.Attribute; -import org.apache.camel.ComponentVerifier.VerificationError.Code; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Code; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode; /** * Package visible helper class holding implementation classes for - * constant like error code and attributes in {@link ComponentVerifier.VerificationError} + * constant like error code and attributes in {@link ComponentVerifierExtension.VerificationError} */ -class ComponentVerifierHelper { +public final class ComponentVerifierExtensionHelper { /** * Custom class for error codes */ - static class ErrorCode implements Code { + public static class ErrorCode implements Code { private final String name; - ErrorCode(String name) { + public ErrorCode(String name) { if (name == null) { throw new IllegalArgumentException("Name of an error code must not be null"); } @@ -69,11 +74,11 @@ public String toString() { } } - static class ErrorAttribute implements Attribute { + public static class ErrorAttribute implements Attribute { private final String name; - ErrorAttribute(String name) { + public ErrorAttribute(String name) { if (name == null) { throw new IllegalArgumentException("Name of an error attribute must not be null"); } @@ -114,26 +119,26 @@ public String toString() { // =========================================================================================================== // Helper classes for implementing the constants in ComponentVerifier: - static class StandardErrorCode extends ErrorCode implements ComponentVerifier.VerificationError.StandardCode { - StandardErrorCode(String name) { + public static class StandardErrorCode extends ErrorCode implements StandardCode { + public StandardErrorCode(String name) { super(name); } } - static class ExceptionErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.ExceptionAttribute { - ExceptionErrorAttribute(String name) { + public static class ExceptionErrorAttribute extends ErrorAttribute implements ExceptionAttribute { + public ExceptionErrorAttribute(String name) { super(name); } } - static class HttpErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.HttpAttribute { - HttpErrorAttribute(String name) { + public static class HttpErrorAttribute extends ErrorAttribute implements HttpAttribute { + public HttpErrorAttribute(String name) { super(name); } } - static class GroupErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.GroupAttribute { - GroupErrorAttribute(String name) { + public static class GroupErrorAttribute extends ErrorAttribute implements GroupAttribute { + public GroupErrorAttribute(String name) { super(name); } } diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java similarity index 91% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java index f05cdb1a2c957..a5495cae1bbf7 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.Map; import java.util.Optional; @@ -22,9 +22,10 @@ import java.util.stream.Collectors; 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.component.extension.ComponentVerifierExtension; import org.apache.camel.runtimecatalog.EndpointValidationResult; import org.apache.camel.runtimecatalog.RuntimeCamelCatalog; import org.apache.camel.util.CamelContextHelper; @@ -33,11 +34,15 @@ import static org.apache.camel.util.StreamUtils.stream; -public class DefaultComponentVerifier implements ComponentVerifier { +public class DefaultComponentVerifierExtension implements ComponentVerifierExtension, ComponentVerifier, CamelContextAware { private final String defaultScheme; - private final CamelContext camelContext; + private CamelContext camelContext; - public DefaultComponentVerifier(String defaultScheme, CamelContext camelContext) { + public DefaultComponentVerifierExtension(String defaultScheme) { + this(defaultScheme, null); + } + + public DefaultComponentVerifierExtension(String defaultScheme, CamelContext camelContext) { this.defaultScheme = defaultScheme; this.camelContext = camelContext; } @@ -46,6 +51,16 @@ public DefaultComponentVerifier(String defaultScheme, CamelContext camelContext) // // ************************************* + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + @Override public Result verify(Scope scope, Map parameters) { // Camel context is mandatory @@ -149,9 +164,6 @@ protected void verifyParametersAgainstCatalog(ResultBuilder builder, Map T setProperties(T instance, Map properties) throws Exception { if (camelContext == null) { diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java similarity index 68% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java index ad36d5f056abd..17a82c055d5b4 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResult.java @@ -14,25 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.List; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.extension.ComponentVerifierExtension; -public class DefaultResult implements ComponentVerifier.Result { - private final ComponentVerifier.Scope scope; +public class DefaultResult implements ComponentVerifierExtension.Result { + private final ComponentVerifierExtension.Scope scope; private final Status status; - private final List verificationErrors; + private final List verificationErrors; - public DefaultResult(ComponentVerifier.Scope scope, Status status, List verificationErrors) { + public DefaultResult(ComponentVerifierExtension.Scope scope, Status status, List verificationErrors) { this.scope = scope; this.status = status; this.verificationErrors = verificationErrors; } @Override - public ComponentVerifier.Scope getScope() { + public ComponentVerifierExtension.Scope getScope() { return scope; } @@ -42,7 +42,7 @@ public Status getStatus() { } @Override - public List getErrors() { + public List getErrors() { return verificationErrors; } diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java similarity index 93% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java index 8bc872773816b..2255dc1baa2dc 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/DefaultResultVerificationError.java @@ -14,12 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.Map; import java.util.Set; -import org.apache.camel.ComponentVerifier.VerificationError; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; public class DefaultResultVerificationError implements VerificationError { private final Code code; diff --git a/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java similarity index 96% rename from camel-core/src/main/java/org/apache/camel/IllegalOptionException.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java index 527eb9dc7b4d4..a8d717db2e0c6 100644 --- a/camel-core/src/main/java/org/apache/camel/IllegalOptionException.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/IllegalOptionException.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel; +package org.apache.camel.component.extension.verifier; public class IllegalOptionException extends ComponentVerifierException { private final String optionName; diff --git a/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java similarity index 95% rename from camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java index 3f1d561a9f697..a03d9f02b96d9 100644 --- a/camel-core/src/main/java/org/apache/camel/NoSuchOptionException.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/NoSuchOptionException.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel; +package org.apache.camel.component.extension.verifier; public class NoSuchOptionException extends ComponentVerifierException { private final String optionName; diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java similarity index 98% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java index 1df438335519d..62f81c4217f38 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/OptionsGroup.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/OptionsGroup.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.io.Serializable; import java.util.Arrays; diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java similarity index 69% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java index 5e8ddae9d234c..637bd08fd2b47 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultBuilder.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.ArrayList; import java.util.Collections; @@ -22,16 +22,14 @@ 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.component.extension.ComponentVerifierExtension; import org.apache.camel.util.function.ThrowingBiConsumer; import org.apache.camel.util.function.ThrowingConsumer; public final class ResultBuilder { - private Optional scope; - private Optional status; - private List verificationErrors; + private Optional scope; + private Optional status; + private List verificationErrors; public ResultBuilder() { this.scope = Optional.empty(); @@ -42,33 +40,33 @@ public ResultBuilder() { // Accessors // ********************************** - public ResultBuilder scope(ComponentVerifier.Scope scope) { + public ResultBuilder scope(ComponentVerifierExtension.Scope scope) { this.scope = Optional.of(scope); return this; } - public ResultBuilder status(ComponentVerifier.Result.Status status) { + public ResultBuilder status(ComponentVerifierExtension.Result.Status status) { this.status = Optional.of(status); return this; } - public ResultBuilder error(ComponentVerifier.VerificationError verificationError) { + public ResultBuilder error(ComponentVerifierExtension.VerificationError verificationError) { if (this.verificationErrors == null) { this.verificationErrors = new ArrayList<>(); } this.verificationErrors.add(verificationError); - this.status = Optional.of(ComponentVerifier.Result.Status.ERROR); + this.status = Optional.of(ComponentVerifierExtension.Result.Status.ERROR); return this; } - public ResultBuilder error(Optional error) { + public ResultBuilder error(Optional error) { error.ifPresent(e -> error(e)); return this; } - public ResultBuilder error(Supplier> supplier) { + public ResultBuilder error(Supplier> supplier) { return error(supplier.get()); } @@ -100,7 +98,7 @@ public ResultBuilder error(T data, ThrowingBiConsumer verificationErrors) { + public ResultBuilder errors(List verificationErrors) { verificationErrors.forEach(this::error); return this; } @@ -109,10 +107,10 @@ public ResultBuilder errors(List verificati // Build // ********************************** - public ComponentVerifier.Result build() { + public ComponentVerifierExtension.Result build() { return new DefaultResult( - scope.orElse(ComponentVerifier.Scope.PARAMETERS), - status.orElse(ComponentVerifier.Result.Status.UNSUPPORTED), + scope.orElse(ComponentVerifierExtension.Scope.PARAMETERS), + status.orElse(ComponentVerifierExtension.Result.Status.UNSUPPORTED), verificationErrors != null ? Collections.unmodifiableList(verificationErrors) : Collections.emptyList() ); } @@ -121,23 +119,23 @@ public ComponentVerifier.Result build() { // Helpers // ********************************** - public static ResultBuilder withStatus(ComponentVerifier.Result.Status status) { + public static ResultBuilder withStatus(ComponentVerifierExtension.Result.Status status) { return new ResultBuilder().status(status); } - public static ResultBuilder withStatusAndScope(ComponentVerifier.Result.Status status, ComponentVerifier.Scope scope) { + public static ResultBuilder withStatusAndScope(ComponentVerifierExtension.Result.Status status, ComponentVerifierExtension.Scope scope) { return new ResultBuilder().status(status).scope(scope); } - public static ResultBuilder withScope(ComponentVerifier.Scope scope) { + public static ResultBuilder withScope(ComponentVerifierExtension.Scope scope) { return new ResultBuilder().scope(scope); } public static ResultBuilder unsupported() { - return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, ComponentVerifier.Scope.PARAMETERS); + return withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, ComponentVerifierExtension.Scope.PARAMETERS); } - public static ResultBuilder unsupportedScope(ComponentVerifier.Scope scope) { - return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope); + public static ResultBuilder unsupportedScope(ComponentVerifierExtension.Scope scope) { + return withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, scope); } } diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java similarity index 98% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java index daadb48509d9b..313e9c2b70c43 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorBuilder.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.Collection; import java.util.Collections; @@ -25,7 +25,7 @@ import java.util.Set; import java.util.function.Supplier; -import org.apache.camel.ComponentVerifier.VerificationError; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; import org.apache.camel.util.ObjectHelper; public final class ResultErrorBuilder { diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java similarity index 97% rename from camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java rename to camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java index fb0dfc0c64de1..d03307e590ccf 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/ResultErrorHelper.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.verifier; +package org.apache.camel.component.extension.verifier; import java.util.ArrayList; import java.util.Arrays; @@ -28,7 +28,7 @@ import java.util.TreeSet; import java.util.stream.Collectors; -import org.apache.camel.ComponentVerifier.VerificationError; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; import org.apache.camel.util.ObjectHelper; /** diff --git a/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html new file mode 100644 index 0000000000000..cfeb0f5e5a496 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/component/extension/verifier/package.html @@ -0,0 +1,25 @@ + + + + + + +Verifier component extension + + + diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java index 264750cdede7d..e2651a2d20ded 100644 --- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java +++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java @@ -27,6 +27,7 @@ import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.model.rest.RestConstants; import org.apache.camel.spi.Metadata; @@ -50,6 +51,10 @@ public class RestComponent extends DefaultComponent implements VerifiableCompone @Metadata(label = "producer") private String host; + public RestComponent() { + registerExtension(RestComponentVerifierExtension::new); + } + @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { String restConfigurationName = getAndRemoveParameter(parameters, "componentName", String.class, componentName); @@ -235,13 +240,8 @@ private void mergeProperties(Supplier> base, Supplier getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } } diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java similarity index 87% rename from camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java rename to camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java index 4013e5f23cf14..7a7fe7611733f 100644 --- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifier.java +++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponentVerifierExtension.java @@ -18,14 +18,15 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.apache.camel.Component; import org.apache.camel.ComponentVerifier; -import org.apache.camel.VerifiableComponent; -import org.apache.camel.impl.verifier.CatalogVerifierCustomizer; -import org.apache.camel.impl.verifier.DefaultComponentVerifier; -import org.apache.camel.impl.verifier.ResultBuilder; -import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.CatalogVerifierCustomizer; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; import org.apache.camel.runtimecatalog.JSonSchemaHelper; import org.apache.camel.runtimecatalog.RuntimeCamelCatalog; import org.apache.camel.spi.RestConsumerFactory; @@ -33,14 +34,11 @@ import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.function.Suppliers; -public class RestComponentVerifier extends DefaultComponentVerifier { +public class RestComponentVerifierExtension extends DefaultComponentVerifierExtension implements ComponentVerifier { private static final CatalogVerifierCustomizer CUSTOMIZER = new CatalogVerifierCustomizer().excludeUnknown(); - private final RestComponent component; - RestComponentVerifier(RestComponent component) { - super("rest", component.getCamelContext()); - - this.component = component; + RestComponentVerifierExtension() { + super("rest"); } // ********************************* @@ -83,8 +81,11 @@ protected void verifyUnderlyingComponent(Scope scope, ResultBuilder builder, Map String componentName = (String)parameters.get("componentName"); if (ObjectHelper.isNotEmpty(componentName)) { try { - Component component = getTransportComponent(componentName); - if (component instanceof VerifiableComponent) { + final Component component = getTransportComponent(componentName); + final Optional extension = component.getExtension(ComponentVerifierExtension.class); + + if (extension.isPresent()) { + final ComponentVerifierExtension verifier = extension.get(); final RuntimeCamelCatalog catalog = getCamelContext().getRuntimeCamelCatalog(); final String json = catalog.componentJSonSchema("rest"); final Map restParameters = new HashMap<>(parameters); @@ -110,8 +111,6 @@ protected void verifyUnderlyingComponent(Scope scope, ResultBuilder builder, Map } } - ComponentVerifier verifier = ((VerifiableComponent)component).getVerifier(); - // restParameters now should contains rest-component related // properties with "rest." prefix and all the remaining can // be used to customize the underlying component (i.e. http 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 9c97c2b4cb4c8..e8d994ed76829 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 @@ -18,10 +18,14 @@ import java.net.URI; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.apache.camel.CamelContext; import org.apache.camel.Component; @@ -29,6 +33,8 @@ import org.apache.camel.Endpoint; import org.apache.camel.EndpointConfiguration; import org.apache.camel.ResolveEndpointFailedException; +import org.apache.camel.component.extension.ComponentExtension; +import org.apache.camel.component.extension.ComponentExtensionHelper; import org.apache.camel.spi.Metadata; import org.apache.camel.support.ServiceSupport; import org.apache.camel.util.CamelContextHelper; @@ -37,9 +43,11 @@ import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; import org.apache.camel.util.UnsafeUriCharactersEncoder; +import org.apache.camel.util.function.Suppliers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * Default component to use for base for components implementations. */ @@ -47,6 +55,8 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone private static final Logger LOG = LoggerFactory.getLogger(DefaultComponent.class); private static final Pattern RAW_PATTERN = Pattern.compile("RAW(.*&&.*)"); + private final List> extensions = new ArrayList<>(); + private CamelContext camelContext; @Metadata(label = "advanced", defaultValue = "true", @@ -476,4 +486,30 @@ protected String ifStartsWithReturnRemainder(String prefix, String text) { return null; } + protected final void registerExtension(ComponentExtension extension) { + extensions.add(() -> extension); + } + + protected final void registerExtension(Supplier supplier) { + extensions.add(Suppliers.memorize(supplier)); + } + + @Override + public Collection> getSupportedExtensions() { + return extensions.stream() + .map(Supplier::get) + .map(ComponentExtension::getClass) + .collect(Collectors.toList()); + } + + @Override + public Optional getExtension(Class extensionType) { + return extensions.stream() + .map(Supplier::get) + .filter(extensionType::isInstance) + .findFirst() + .map(extensionType::cast) + .map(e -> ComponentExtensionHelper.trySetComponent(e, this)) + .map(e -> ComponentExtensionHelper.trySetCamelContext(e, getCamelContext())); + } } 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 78af22a9371fe..931690f8e9af3 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 @@ -34,8 +34,8 @@ 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.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; import org.apache.camel.spi.ManagementStrategy; import org.apache.camel.util.CastUtils; import org.apache.camel.util.JsonSchemaHelper; @@ -158,7 +158,6 @@ public ComponentVerifier.Result verify(String scope, Map options return ResultBuilder.withStatus(ComponentVerifier.Result.Status.UNSUPPORTED) .error(ResultErrorBuilder.withUnsupportedScope(scope).build()) .build(); - } } } diff --git a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java index 1ee219c5c4759..c368d034e4f14 100644 --- a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java +++ b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java @@ -32,6 +32,7 @@ import java.util.TreeMap; import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; import org.apache.camel.Component; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; @@ -766,5 +767,4 @@ public static void resolvePropertyPlaceholders(CamelContext camelContext, Object } } } - } diff --git a/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java similarity index 93% rename from camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java rename to camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java index 2eb944c87aefe..1111e6748fc6e 100644 --- a/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java +++ b/camel-core/src/test/java/org/apache/camel/component/extension/verifier/ComponentVerifierTest.java @@ -14,10 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel; +package org.apache.camel.component.extension.verifier; import junit.framework.TestCase; -import org.apache.camel.ComponentVerifier.VerificationError; -import org.apache.camel.impl.verifier.ResultErrorBuilder; +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; import org.junit.Assert; public class ComponentVerifierTest extends TestCase { diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..a5adc8c1a9d6a --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierExtensionTest.java @@ -0,0 +1,141 @@ +/** + * 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.rest; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Consumer; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Endpoint; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; +import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.spi.RestConfiguration; +import org.apache.camel.spi.RestConsumerFactory; +import org.apache.camel.spi.RestProducerFactory; +import org.junit.Assert; + +public class RestComponentVerifierExtensionTest extends ContextTestSupport { + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry registry = super.createRegistry(); + registry.bind("rest", new RestComponent()); + registry.bind("rest-component", new MyComponent()); + return registry; + } + + public void testParameters() throws Exception { + RestComponent component = context.getComponent("rest", RestComponent.class); + RestComponentVerifierExtension verifier = component.getExtension(RestComponentVerifierExtension.class).orElseThrow(() -> new IllegalStateException()); + + Map parameters = new HashMap<>(); + parameters.put("componentName", "rest-component"); + parameters.put("host", "http://localhost:1234"); + parameters.put("path", "verify"); + parameters.put("method", "get"); + + // This parameter does not belong to the rest component and validation + // is delegated to the underlying component + parameters.put("authProxy", "http://localhost:8080"); + + RestComponentVerifierExtension.Result result = verifier.verify(RestComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(RestComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + public void testMissingParameters() throws Exception { + RestComponent component = context.getComponent("rest", RestComponent.class); + RestComponentVerifierExtension verifier = component.getExtension(RestComponentVerifierExtension.class).orElseThrow(() -> new IllegalStateException()); + + Map parameters = new HashMap<>(); + parameters.put("componentName", "rest-component"); + parameters.put("host", "http://localhost:" + 1234); + parameters.put("path", "verify"); + + // This parameter does not belong to the rest component and validation + // is delegated to the underlying component + parameters.put("authProxy", "http://localhost:8080"); + + RestComponentVerifierExtension.Result result = verifier.verify(RestComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(RestComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(RestComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size()); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("method")); + } + + // *************************************************** + // + // *************************************************** + + private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory { + + public MyComponent() { + registerExtension( + new ComponentVerifierExtension() { + @Override + public Result verify(Scope scope, Map parameters) { + return ResultBuilder.withStatusAndScope(RestComponentVerifierExtension.Result.Status.OK, scope) + .error(ResultErrorHelper.requiresOption("authProxy", parameters)) + .build(); + } + } + ); + } + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + public Producer createProducer( + CamelContext camelContext, + String host, + String verb, + String basePath, + String uriTemplate, + String queryParameters, + String consumes, + String produces, + Map parameters) + throws Exception { + throw new UnsupportedOperationException(); + } + + @Override + public Consumer createConsumer( + CamelContext camelContext, + Processor processor, + String verb, + String basePath, + String uriTemplate, + String consumes, + String produces, + RestConfiguration configuration, + Map parameters) + throws Exception { + throw new UnsupportedOperationException(); + } + } +} diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java index 73fb1303bde12..ca8851ef3e597 100644 --- a/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java +++ b/camel-core/src/test/java/org/apache/camel/component/rest/RestComponentVerifierTest.java @@ -26,11 +26,11 @@ import org.apache.camel.Endpoint; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.impl.JndiRegistry; -import org.apache.camel.impl.verifier.ResultBuilder; -import org.apache.camel.impl.verifier.ResultErrorHelper; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestConsumerFactory; import org.apache.camel.spi.RestProducerFactory; @@ -47,7 +47,7 @@ protected JndiRegistry createRegistry() throws Exception { public void testParameters() throws Exception { RestComponent component = context.getComponent("rest", RestComponent.class); - RestComponentVerifier verifier = (RestComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("componentName", "rest-component"); @@ -66,7 +66,7 @@ public void testParameters() throws Exception { public void testMissingParameters() throws Exception { RestComponent component = context.getComponent("rest", RestComponent.class); - RestComponentVerifier verifier = (RestComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("componentName", "rest-component"); @@ -90,7 +90,19 @@ public void testMissingParameters() throws Exception { // // *************************************************** - private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory, VerifiableComponent { + private final class MyComponent extends DefaultComponent implements RestProducerFactory, RestConsumerFactory { + public MyComponent() { + registerExtension( + new ComponentVerifierExtension() { + @Override + public Result verify(Scope scope, Map parameters) { + return ResultBuilder.withStatusAndScope(RestComponentVerifierExtension.Result.Status.OK, scope) + .error(ResultErrorHelper.requiresOption("authProxy", parameters)) + .build(); + } + } + ); + } @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { throw new UnsupportedOperationException(); @@ -125,13 +137,5 @@ public Consumer createConsumer( throws Exception { throw new UnsupportedOperationException(); } - - @Override - public ComponentVerifier getVerifier() { - return (scope, parameters) -> - ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope) - .error(ResultErrorHelper.requiresOption("authProxy", parameters)) - .build(); - } } } diff --git a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java index 8a903b87732db..9ade84133e124 100644 --- a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java +++ b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java @@ -19,13 +19,16 @@ import java.util.HashMap; import java.util.Map; -import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; import org.apache.camel.ContextTestSupport; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.ComponentVerifierExtension.Result; +import org.apache.camel.component.extension.ComponentVerifierExtension.Scope; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; import org.junit.Assert; public class DefaultComponentVerifierTest extends ContextTestSupport { - private ComponentVerifier verifier; + private ComponentVerifierExtension verifier; @Override public boolean isUseRouteBuilder() { @@ -36,7 +39,7 @@ public boolean isUseRouteBuilder() { protected void setUp() throws Exception { super.setUp(); - this.verifier = new DefaultComponentVerifier("timer", context); + this.verifier = new DefaultComponentVerifierExtension("timer", context); } // ************************************* @@ -48,16 +51,16 @@ public void testParameters() throws Exception { parameters.put("timerName", "dummy"); parameters.put("period", "1s"); - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters); - Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + Result result = verifier.verify(Scope.PARAMETERS, parameters); + Assert.assertEquals(Result.Status.OK, result.getStatus()); } public void testParametersWithMissingMandatoryOptions() throws Exception { Map parameters = new HashMap<>(); parameters.put("period", "1s"); - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters); - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Result result = verifier.verify(Scope.PARAMETERS, parameters); + Assert.assertEquals(Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); @@ -70,8 +73,8 @@ public void testParametersWithWrongOptions() throws Exception { parameters.put("period", "1s"); parameters.put("fixedRate", "wrong"); - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters); - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Result result = verifier.verify(Scope.PARAMETERS, parameters); + Assert.assertEquals(Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); Assert.assertEquals(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE, result.getErrors().get(0).getCode()); diff --git a/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java b/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java index 15b82fcc15444..0c728298d6789 100644 --- a/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java +++ b/camel-core/src/test/java/org/apache/camel/impl/verifier/ResultErrorHelperTest.java @@ -21,8 +21,11 @@ import java.util.Map; import java.util.stream.Collectors; -import org.apache.camel.ComponentVerifier.VerificationError; -import org.apache.camel.ComponentVerifier.VerificationError.StandardCode; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError; +import org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode; +import org.apache.camel.component.extension.verifier.OptionsGroup; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -49,7 +52,7 @@ public void shouldValidateCorrectParameters() { @Test public void shouldValidateParameterExclusions() { // combining param2 and param3 is not OK - final List results = ResultErrorHelper.requiresAny(map("param1", "param2", "param3"), + final List results = ResultErrorHelper.requiresAny(map("param1", "param2", "param3"), groups); assertEquals(3, results.size()); diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java index 491e7660b128b..ce1737cd1491e 100644 --- a/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedComponentTest.java @@ -26,9 +26,9 @@ import org.apache.camel.Endpoint; import org.apache.camel.VerifiableComponent; import org.apache.camel.component.direct.DirectComponent; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; import org.apache.camel.impl.DefaultComponent; -import org.apache.camel.impl.verifier.DefaultComponentVerifier; -import org.apache.camel.impl.verifier.ResultBuilder; public class ManagedComponentTest extends ManagementTestSupport { private static final String[] VERIFY_SIGNATURE = new String[] { @@ -100,7 +100,7 @@ public void testVerify() throws Exception { private static class MyVerifiableComponent extends DefaultComponent implements VerifiableComponent { @Override public ComponentVerifier getVerifier() { - return new DefaultComponentVerifier("my-verifiable-component", getCamelContext()) { + return new DefaultComponentVerifierExtension("my-verifiable-component", getCamelContext()) { @Override protected Result verifyConnectivity(Map parameters) { return ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY).build(); 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 01c1730ad6a18..2e2f6ed07f9dc 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 @@ -30,6 +30,7 @@ import org.apache.camel.ResolveEndpointFailedException; import org.apache.camel.SSLContextParametersAware; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.http.common.HttpBinding; import org.apache.camel.http.common.HttpCommonComponent; import org.apache.camel.http.common.HttpConfiguration; @@ -64,11 +65,13 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa private boolean useGlobalSslContextParameters; public HttpComponent() { - super(HttpEndpoint.class); + this(HttpEndpoint.class); } public HttpComponent(Class endpointClass) { super(endpointClass); + + registerExtension(HttpComponentVerifierExtension::new); } /** @@ -387,10 +390,8 @@ public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParamete this.useGlobalSslContextParameters = useGlobalSslContextParameters; } - /** - * TODO: document - */ + @Override public ComponentVerifier getVerifier() { - return new HttpComponentVerifier(this); + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } } 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/HttpComponentVerifierExtension.java similarity index 95% rename from components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java rename to components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifierExtension.java index 309ff3e50e093..620c68817d72f 100644 --- 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/HttpComponentVerifierExtension.java @@ -20,24 +20,20 @@ import java.util.Map; import java.util.Optional; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; 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; +final class HttpComponentVerifierExtension extends DefaultComponentVerifierExtension { - HttpComponentVerifier(HttpComponent component) { - super("http", component.getCamelContext()); - - this.component = component; + HttpComponentVerifierExtension() { + super("http"); } // ********************************* diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..0ac95604a3fc8 --- /dev/null +++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierExtensionTest.java @@ -0,0 +1,151 @@ +/** + * 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.Component; +import org.apache.camel.component.extension.ComponentVerifierExtension; +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.Test; + +public class HttpComponentVerifierExtensionTest 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 (parameters) + // ************************************************* + + @Test + public void testParameters() throws Exception { + Component component = context().getComponent("http"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/basic")); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testMissingMandatoryParameters() throws Exception { + Component component = context().getComponent("http"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); + Assert.assertTrue(error.getParameterKeys().contains("httpUri")); + } + + // ************************************************* + // Tests (connectivity) + // ************************************************* + + @Test + public void testConnectivity() throws Exception { + Component component = context().getComponent("http"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/basic")); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongUri() throws Exception { + Component component = context().getComponent("http"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", "http://www.not-existing-uri.unknown"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode()); + Assert.assertTrue(error.getParameterKeys().contains("httpUri")); + } +} 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/HttpComponentVerifierTest.java similarity index 63% rename from components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java rename to components/camel-http/src/test/java/org/apache/camel/component/http/HttpComponentVerifierTest.java index 76d918e961875..764baf7dc33cc 100644 --- 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/HttpComponentVerifierTest.java @@ -20,17 +20,15 @@ import java.util.Map; import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; 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 { +public class HttpComponentVerifierTest extends BaseHttpTest { private static final String AUTH_USERNAME = "camel"; private static final String AUTH_PASSWORD = "password"; private static final int PORT = AvailablePortFinder.getNextAvailable(); @@ -80,13 +78,13 @@ protected String getLocalServerUri(String contextPath) throws Exception { } // ************************************************* - // Tests + // Tests (parameters) // ************************************************* @Test public void testParameters() throws Exception { HttpComponent component = context().getComponent("http", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/basic")); @@ -99,7 +97,7 @@ public void testParameters() throws Exception { @Test public void testMissingMandatoryParameters() throws Exception { HttpComponent component = context().getComponent("http", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); @@ -108,20 +106,20 @@ public void testMissingMandatoryParameters() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); Assert.assertTrue(error.getParameterKeys().contains("httpUri")); } // ************************************************* - // Tests + // Tests (connectivity) // ************************************************* @Test public void testConnectivity() throws Exception { HttpComponent component = context().getComponent("http", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/basic")); @@ -134,7 +132,7 @@ public void testConnectivity() throws Exception { @Test public void testConnectivityWithWrongUri() throws Exception { HttpComponent component = context().getComponent("http", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", "http://www.not-existing-uri.unknown"); @@ -144,49 +142,9 @@ public void testConnectivityWithWrongUri() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, error.getCode()); Assert.assertTrue(error.getParameterKeys().contains("httpUri")); } - - @Ignore - @Test - public void testConnectivityWithAuthentication() throws Exception { - HttpComponent component = context().getComponent("http", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); - - Map 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 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()); - - VerificationError error = result.getErrors().get(0); - - Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode()); - Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE)); - Assert.assertTrue(error.getParameterKeys().contains("authUsername")); - Assert.assertTrue(error.getParameterKeys().contains("authPassword")); - } } \ No newline at end of file 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 fc891cf057a20..6a99af38f1244 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 @@ -32,6 +32,7 @@ import org.apache.camel.ResolveEndpointFailedException; import org.apache.camel.SSLContextParametersAware; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.http.common.HttpBinding; import org.apache.camel.http.common.HttpCommonComponent; import org.apache.camel.http.common.HttpHelper; @@ -105,11 +106,13 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa private boolean useGlobalSslContextParameters; public HttpComponent() { - super(HttpEndpoint.class); + this(HttpEndpoint.class); } public HttpComponent(Class endpointClass) { super(endpointClass); + + registerExtension(HttpComponentVerifierExtension::new); } /** @@ -549,10 +552,8 @@ public void doStop() throws Exception { super.doStop(); } - /** - * TODO: document - */ + @Override public ComponentVerifier getVerifier() { - return new HttpComponentVerifier(this); + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } } diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java similarity index 94% rename from components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java rename to components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java index 46e3bc4793b94..3aee9ebc867b6 100644 --- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java +++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifierExtension.java @@ -21,10 +21,11 @@ import java.util.Map; import java.util.Optional; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; 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.util.FileUtil; import org.apache.camel.util.ObjectHelper; import org.apache.http.client.config.RequestConfig; @@ -34,13 +35,10 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -final class HttpComponentVerifier extends DefaultComponentVerifier { - private final HttpComponent component; +final class HttpComponentVerifierExtension extends DefaultComponentVerifierExtension { - HttpComponentVerifier(HttpComponent component) { - super("http4", component.getCamelContext()); - - this.component = component; + HttpComponentVerifierExtension() { + super("http4"); } // ********************************* @@ -50,7 +48,7 @@ final class HttpComponentVerifier extends DefaultComponentVerifier { @Override protected Result verifyParameters(Map parameters) { // Default is success - final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS); + final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, ComponentVerifierExtension.Scope.PARAMETERS); // Make a copy to avoid clashing with parent validation final HashMap verifyParams = new HashMap<>(parameters); // Check if validation is rest-related @@ -77,7 +75,7 @@ protected Result verifyParameters(Map parameters) { @Override protected Result verifyConnectivity(Map parameters) { // Default is success - final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); + final ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, ComponentVerifierExtension.Scope.CONNECTIVITY); // Make a copy to avoid clashing with parent validation final HashMap verifyParams = new HashMap<>(parameters); // Check if validation is rest-related diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..a853919b63d73 --- /dev/null +++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierExtensionTest.java @@ -0,0 +1,263 @@ +/** + * 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.http4; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.Component; +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.http4.handler.AuthenticationValidationHandler; +import org.apache.camel.component.http4.handler.BasicValidationHandler; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.impl.bootstrap.HttpServer; +import org.apache.http.impl.bootstrap.ServerBootstrap; +import org.apache.http.localserver.RequestBasicAuth; +import org.apache.http.localserver.ResponseBasicUnauthorized; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpProcessor; +import org.apache.http.protocol.HttpRequestHandler; +import org.apache.http.protocol.ImmutableHttpProcessor; +import org.apache.http.protocol.ResponseContent; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CamelComponentVerifierExtensionTest extends BaseHttpTest { + private static final String AUTH_USERNAME = "camel"; + private static final String AUTH_PASSWORD = "password"; + + private HttpServer localServer; + + @Before + @Override + public void setUp() throws Exception { + localServer = ServerBootstrap.bootstrap() + .setHttpProcessor(getHttpProcessor()) + .registerHandler("/basic", new BasicValidationHandler("GET", null, null, getExpectedContent())) + .registerHandler("/auth", new AuthenticationValidationHandler("GET", null, null, getExpectedContent(), AUTH_USERNAME, AUTH_PASSWORD)) + .registerHandler("/redirect", redirectTo(HttpStatus.SC_MOVED_PERMANENTLY, "/redirected")) + .registerHandler("/redirected", new BasicValidationHandler("GET", null, null, getExpectedContent())) + .create(); + + localServer.start(); + + super.setUp(); + } + + @After + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (localServer != null) { + localServer.stop(); + } + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + private HttpProcessor getHttpProcessor() { + return new ImmutableHttpProcessor( + Arrays.asList( + new RequestBasicAuth() + ), + Arrays.asList( + new ResponseContent(), + new ResponseBasicUnauthorized()) + ); + } + + // ************************************************* + // Helpers + // ************************************************* + + protected String getLocalServerUri(String contextPath) { + return new StringBuilder() + .append("http://") + .append(localServer.getInetAddress().getHostName()) + .append(":") + .append(localServer.getLocalPort()) + .append(contextPath != null + ? contextPath.startsWith("/") ? contextPath : "/" + contextPath + : "") + .toString(); + } + + private HttpRequestHandler redirectTo(int code, String path) { + return new HttpRequestHandler() { + @Override + public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { + response.setHeader("location", getLocalServerUri(path)); + response.setStatusCode(code); + } + }; + } + + // ************************************************* + // Tests (parameters) + // ************************************************* + + @Test + public void testParameters() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/basic")); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testMissingMandatoryParameters() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); + Assert.assertTrue(error.getParameterKeys().contains("httpUri")); + } + + // ************************************************* + // Tests (connectivity) + // ************************************************* + + @Test + public void testConnectivity() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/basic")); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongUri() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", "http://www.not-existing-uri.unknown"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode()); + Assert.assertTrue(error.getParameterKeys().contains("httpUri")); + } + + @Test + public void testConnectivityWithAuthentication() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/auth")); + parameters.put("authUsername", AUTH_USERNAME); + parameters.put("authPassword", AUTH_PASSWORD); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongAuthenticationData() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/auth")); + parameters.put("authUsername", "unknown"); + parameters.put("authPassword", AUTH_PASSWORD); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, error.getCode()); + Assert.assertEquals(401, error.getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertTrue(error.getParameterKeys().contains("authUsername")); + Assert.assertTrue(error.getParameterKeys().contains("authPassword")); + } + + @Test + public void testConnectivityWithRedirect() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/redirect")); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithRedirectDisabled() throws Exception { + Component component = context().getComponent("http4"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpUri", getLocalServerUri("/redirect")); + parameters.put("httpClient.redirectsEnabled", "false"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.GENERIC, error.getCode()); + Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_REDIRECT)); + Assert.assertTrue(error.getParameterKeys().contains("httpUri")); + } +} \ No newline at end of file diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java index dc4ef3ff14e91..5144a8d539949 100644 --- a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java +++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java @@ -22,7 +22,6 @@ import java.util.Map; import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; import org.apache.camel.component.http4.handler.AuthenticationValidationHandler; import org.apache.camel.component.http4.handler.BasicValidationHandler; import org.apache.http.HttpException; @@ -118,13 +117,13 @@ public void handle(HttpRequest request, HttpResponse response, HttpContext conte } // ************************************************* - // Tests + // Tests (parameters) // ************************************************* @Test public void testParameters() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/basic")); @@ -137,7 +136,7 @@ public void testParameters() throws Exception { @Test public void testMissingMandatoryParameters() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); @@ -146,16 +145,20 @@ public void testMissingMandatoryParameters() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, error.getCode()); Assert.assertTrue(error.getParameterKeys().contains("httpUri")); } + // ************************************************* + // Tests (connectivity) + // ************************************************* + @Test public void testConnectivity() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/basic")); @@ -168,7 +171,7 @@ public void testConnectivity() throws Exception { @Test public void testConnectivityWithWrongUri() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", "http://www.not-existing-uri.unknown"); @@ -178,16 +181,16 @@ public void testConnectivityWithWrongUri() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, error.getCode()); Assert.assertTrue(error.getParameterKeys().contains("httpUri")); } @Test public void testConnectivityWithAuthentication() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/auth")); @@ -202,7 +205,7 @@ public void testConnectivityWithAuthentication() throws Exception { @Test public void testConnectivityWithWrongAuthenticationData() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/auth")); @@ -214,10 +217,10 @@ public void testConnectivityWithWrongAuthenticationData() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode()); - Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, error.getCode()); + Assert.assertEquals(401, error.getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); Assert.assertTrue(error.getParameterKeys().contains("authUsername")); Assert.assertTrue(error.getParameterKeys().contains("authPassword")); } @@ -225,7 +228,7 @@ public void testConnectivityWithWrongAuthenticationData() throws Exception { @Test public void testConnectivityWithRedirect() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/redirect")); @@ -238,7 +241,7 @@ public void testConnectivityWithRedirect() throws Exception { @Test public void testConnectivityWithRedirectDisabled() throws Exception { HttpComponent component = context().getComponent("http4", HttpComponent.class); - HttpComponentVerifier verifier = (HttpComponentVerifier)component.getVerifier(); + ComponentVerifier verifier = component.getVerifier(); Map parameters = new HashMap<>(); parameters.put("httpUri", getLocalServerUri("/redirect")); @@ -249,10 +252,10 @@ public void testConnectivityWithRedirectDisabled() throws Exception { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - VerificationError error = result.getErrors().get(0); + ComponentVerifier.VerificationError error = result.getErrors().get(0); - Assert.assertEquals(VerificationError.StandardCode.GENERIC, error.getCode()); - Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(VerificationError.HttpAttribute.HTTP_REDIRECT)); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.GENERIC, error.getCode()); + Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_REDIRECT)); Assert.assertTrue(error.getParameterKeys().contains("httpUri")); } } \ No newline at end of file diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java index 5609031a64505..0ef308e7a78fb 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java @@ -28,6 +28,7 @@ import org.apache.camel.Endpoint; import org.apache.camel.SSLContextParametersAware; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase; import org.apache.camel.component.salesforce.internal.OperationName; @@ -199,10 +200,13 @@ public class SalesforceComponent extends DefaultComponent implements VerifiableC private SubscriptionHelper subscriptionHelper; public SalesforceComponent() { + this(null); } public SalesforceComponent(CamelContext context) { super(context); + + registerExtension(SalesforceComponentVerifierExtension::new); } protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { @@ -656,7 +660,8 @@ public Map> getClassMap() { return classMap; } + @Override public ComponentVerifier getVerifier() { - return new SalesforceComponentVerifier(this); + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } } diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java similarity index 93% rename from components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java rename to components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java index 438f1448949d8..be71dde7ff195 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtension.java @@ -21,16 +21,16 @@ import java.util.Map; import java.util.Optional; -import org.apache.camel.NoSuchOptionException; +import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.NoSuchOptionException; +import org.apache.camel.component.extension.verifier.OptionsGroup; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.RestError; import org.apache.camel.component.salesforce.internal.SalesforceSession; import org.apache.camel.component.salesforce.internal.client.DefaultRestClient; -import org.apache.camel.impl.verifier.DefaultComponentVerifier; -import org.apache.camel.impl.verifier.OptionsGroup; -import org.apache.camel.impl.verifier.ResultBuilder; -import org.apache.camel.impl.verifier.ResultErrorBuilder; -import org.apache.camel.impl.verifier.ResultErrorHelper; import org.apache.camel.util.jsse.SSLContextParameters; import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Origin; @@ -39,9 +39,10 @@ import org.eclipse.jetty.client.util.DigestAuthentication; import org.eclipse.jetty.util.ssl.SslContextFactory; -public class SalesforceComponentVerifier extends DefaultComponentVerifier { - SalesforceComponentVerifier(SalesforceComponent component) { - super("salesforce", component.getCamelContext()); +public class SalesforceComponentVerifierExtension extends DefaultComponentVerifierExtension { + + SalesforceComponentVerifierExtension() { + super("salesforce"); } // ********************************* diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..bf7ed2a4e3380 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierExtensionTest.java @@ -0,0 +1,183 @@ +/** + * 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.salesforce; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.Component; +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.salesforce.api.SalesforceException; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.camel.util.ObjectHelper; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +public class SalesforceComponentVerifierExtensionTest extends CamelTestSupport { + private static final String CLIENT_ID = getSystemPropertyOrEnvVar("salesforce.clientid"); + private static final String CLIENT_SECRET = getSystemPropertyOrEnvVar("salesforce.clientsecret"); + private static final String USERNAME = getSystemPropertyOrEnvVar("salesforce.userName"); + private static final String PASSWORD = getSystemPropertyOrEnvVar("salesforce.password"); + + @Override + protected void doPreSetup() throws Exception { + Assume.assumeNotNull(CLIENT_ID); + Assume.assumeNotNull(CLIENT_SECRET); + Assume.assumeNotNull(USERNAME); + Assume.assumeNotNull(PASSWORD); + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + // ********************************* + // Helpers + // ********************************* + + protected Map getParameters() { + HashMap parameters = new HashMap<>(); + parameters.put("clientId", CLIENT_ID); + parameters.put("clientSecret", CLIENT_SECRET); + parameters.put("userName", USERNAME); + parameters.put("password", PASSWORD); + + + return parameters; + } + + public static String getSystemPropertyOrEnvVar(String systemProperty) { + String answer = System.getProperty(systemProperty); + if (ObjectHelper.isEmpty(answer)) { + String envProperty = systemProperty.toUpperCase().replaceAll("[.-]", "_"); + answer = System.getenv(envProperty); + } + + return answer; + } + + protected ComponentVerifierExtension getExtension() { + Component component = context().getComponent("salesforce"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + return verifier; + } + + // ********************************* + // Parameters validation + // ********************************* + + @Test + public void testUsernamePasswordParameters() { + HashMap parameters = new HashMap<>(); + parameters.put("clientId", "clientId"); + parameters.put("clientSecret", "clientSecret"); + parameters.put("userName", "userName"); + parameters.put("password", "password"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testRefreshTokenParameters() { + Map parameters = getParameters(); + parameters.put("clientId", "clientId"); + parameters.put("clientSecret", "clientSecret"); + parameters.put("refreshToken", "refreshToken"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testWrongParameters() { + HashMap parameters = new HashMap<>(); + parameters.put("clientId", "clientId"); + parameters.put("clientSecret", "clientSecret"); + parameters.put("password", "password"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(3, result.getErrors().size()); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode()); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Test + public void testConnectivity() { + Map parameters = getParameters(); + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongUserName() { + Map parameters = getParameters(); + parameters.put("userName", "not-a-salesforce-user"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(2, result.getErrors().size()); + + // Exception + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE)); + + // Salesforce Error + Assert.assertEquals("invalid_grant", result.getErrors().get(1).getDetail("salesforce_code")); + } + + @Test + public void testConnectivityWithWrongSecrets() { + Map parameters = getParameters(); + parameters.put("clientId", "wrong-client-id"); + parameters.put("clientSecret", "wrong-client-secret"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(2, result.getErrors().size()); + + // Exception + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); + + // Salesforce Error + Assert.assertEquals("invalid_client_id", result.getErrors().get(1).getDetail("salesforce_code")); + } +} diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java index dc02d55eb25ea..8b27265a8d5fc 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java @@ -20,7 +20,6 @@ import java.util.Map; import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.camel.util.ObjectHelper; @@ -72,11 +71,9 @@ public static String getSystemPropertyOrEnvVar(String systemProperty) { return answer; } - protected SalesforceComponentVerifier getVerifier() { + protected ComponentVerifier getVerifier() { SalesforceComponent component = context().getComponent("salesforce", SalesforceComponent.class); - SalesforceComponentVerifier verifier = (SalesforceComponentVerifier)component.getVerifier(); - - return verifier; + return component.getVerifier(); } // ********************************* @@ -120,9 +117,9 @@ public void testWrongParameters() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(3, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode()); - Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode()); - Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode()); } // ********************************* @@ -148,10 +145,10 @@ public void testConnectivityWithWrongUserName() { Assert.assertEquals(2, result.getErrors().size()); // Exception - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); - Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); // Salesforce Error Assert.assertEquals("invalid_grant", result.getErrors().get(1).getDetail("salesforce_code")); @@ -171,9 +168,9 @@ public void testConnectivityWithWrongSecrets() { Assert.assertEquals(2, result.getErrors().size()); // Exception - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException); Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); // Salesforce Error diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java index 8a5ab9ea48b4c..ff414c845ed43 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java @@ -16,14 +16,19 @@ */ package org.apache.camel.component.servicenow; +import java.util.Collection; +import java.util.Collections; import java.util.Map; +import java.util.Optional; import org.apache.camel.CamelContext; import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; import org.apache.camel.SSLContextParametersAware; import org.apache.camel.VerifiableComponent; -import org.apache.camel.impl.UriEndpointComponent; +import org.apache.camel.component.extension.ComponentExtension; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.impl.DefaultComponent; import org.apache.camel.spi.Metadata; import org.apache.camel.util.EndpointHelper; import org.apache.camel.util.IntrospectionSupport; @@ -32,7 +37,7 @@ * Represents the component that manages {@link ServiceNowEndpoint}. */ @Metadata(label = "verifiers", enums = "parameters,connectivity") -public class ServiceNowComponent extends UriEndpointComponent implements VerifiableComponent, SSLContextParametersAware { +public class ServiceNowComponent extends DefaultComponent implements VerifiableComponent, SSLContextParametersAware { @Metadata(label = "advanced") private ServiceNowConfiguration configuration; @@ -40,7 +45,11 @@ public class ServiceNowComponent extends UriEndpointComponent implements Verifia private boolean useGlobalSslContextParameters; public ServiceNowComponent() { - super(ServiceNowEndpoint.class); + this.configuration = new ServiceNowConfiguration(); + } + + public ServiceNowComponent(CamelContext camelContext) { + super(camelContext); this.configuration = new ServiceNowConfiguration(); } @@ -183,10 +192,24 @@ public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParamete this.useGlobalSslContextParameters = useGlobalSslContextParameters; } - /** - * TODO: document - */ + @Override public ComponentVerifier getVerifier() { - return new ServiceNowComponentVerifier(this); + return new ServiceNowComponentVerifierExtension(this); + } + + @Override + public Collection> getExtensionTypes() { + return Collections.singletonList(ComponentVerifierExtension.class); + } + + @Override + public Optional getExtension(Class extensionType) { + if (ComponentVerifierExtension.class.isAssignableFrom(extensionType)) { + return Optional.of( + extensionType.cast(new ServiceNowComponentVerifierExtension(this)) + ); + } + + return Optional.empty(); } } diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java similarity index 89% rename from components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java rename to components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java index 8d4cf9db77024..96313d208d5da 100644 --- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtension.java @@ -20,16 +20,15 @@ import javax.ws.rs.HttpMethod; import javax.ws.rs.core.MediaType; -import org.apache.camel.ComponentVerifier; -import org.apache.camel.NoSuchOptionException; -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.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.NoSuchOptionException; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; -public class ServiceNowComponentVerifier extends DefaultComponentVerifier { +public class ServiceNowComponentVerifierExtension extends DefaultComponentVerifierExtension { private final ServiceNowComponent component; - ServiceNowComponentVerifier(ServiceNowComponent component) { + ServiceNowComponentVerifierExtension(ServiceNowComponent component) { super("servicenow", component.getCamelContext()); this.component = component; diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..a06d50330e23f --- /dev/null +++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierExtensionTest.java @@ -0,0 +1,151 @@ +/** + * 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.servicenow; + +import java.util.Map; +import javax.ws.rs.ProcessingException; + +import org.apache.camel.Component; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.junit.Assert; +import org.junit.Test; + +public class ServiceNowComponentVerifierExtensionTest extends ServiceNowTestSupport { + public ServiceNowComponentVerifierExtensionTest() { + super(false); + } + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + protected ComponentVerifierExtension getExtension() { + Component component = context().getComponent("servicenow"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + return verifier; + } + + // ********************************* + // Parameters validation + // ********************************* + + @Test + public void testParameter() { + Map parameters = getParameters(); + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testMissingMandatoryParameter() { + Map parameters = getParameters(); + parameters.remove("instanceName"); + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next()); + } + + @Test + public void testMissingMandatoryAuthenticationParameter() { + Map parameters = getParameters(); + parameters.remove("userName"); + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next()); + } + + // ********************************* + // Connectivity validation + // ********************************* + + @Test + public void testConnectivity() { + Map parameters = getParameters(); + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityOnCustomTable() { + Map parameters = getParameters(); + parameters.put("table", "ticket"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityWithWrongInstance() { + Map parameters = getParameters(); + parameters.put("instanceName", "unknown-instance"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException); + } + + @Test + public void testConnectivityWithWrongTable() { + Map parameters = getParameters(); + parameters.put("table", "unknown"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); + } + + @Test + public void testConnectivityWithWrongAuthentication() { + Map parameters = getParameters(); + parameters.put("userName", "unknown-user"); + parameters.remove("oauthClientId"); + parameters.remove("oauthClientSecret"); + + ComponentVerifierExtension.Result result = getExtension().verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName")); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password")); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId")); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret")); + } +} diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java index 1fcd5bc620f91..ddb3109f4078f 100644 --- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java +++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java @@ -17,11 +17,9 @@ package org.apache.camel.component.servicenow; import java.util.Map; - import javax.ws.rs.ProcessingException; import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; import org.junit.Assert; import org.junit.Test; @@ -35,9 +33,9 @@ public boolean isUseRouteBuilder() { return false; } - protected ServiceNowComponentVerifier getVerifier() { + protected ServiceNowComponentVerifierExtension getVerifier() { ServiceNowComponent component = context().getComponent("servicenow", ServiceNowComponent.class); - ServiceNowComponentVerifier verifier = (ServiceNowComponentVerifier)component.getVerifier(); + ServiceNowComponentVerifierExtension verifier = (ServiceNowComponentVerifierExtension)component.getVerifier(); return verifier; } @@ -62,7 +60,7 @@ public void testMissingMandatoryParameter() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next()); } @@ -74,7 +72,7 @@ public void testMissingMandatoryAuthenticationParameter() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next()); } @@ -109,9 +107,9 @@ public void testConnectivityWithWrongInstance() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException); } @Test @@ -123,10 +121,10 @@ public void testConnectivityWithWrongTable() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); } @Test @@ -140,10 +138,10 @@ public void testConnectivityWithWrongAuthentication() { Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException); Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName")); Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password")); Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId")); diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java index d86f60331f32b..552b5488bed2b 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/AbstractTwitterComponent.java @@ -22,6 +22,7 @@ import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.spi.Metadata; @@ -29,7 +30,6 @@ * Base Twitter component */ public abstract class AbstractTwitterComponent extends DefaultComponent implements VerifiableComponent { - @Metadata(label = "security", secret = true) private String consumerKey; @Metadata(label = "security", secret = true) @@ -47,13 +47,17 @@ public abstract class AbstractTwitterComponent extends DefaultComponent implemen @Metadata(label = "proxy") private Integer httpProxyPort; - public AbstractTwitterComponent() { + protected AbstractTwitterComponent(String componentVerifierScheme) { + this(null, componentVerifierScheme); } - public AbstractTwitterComponent(CamelContext context) { + protected AbstractTwitterComponent(CamelContext context, String componentVerifierScheme) { super(context); + + registerExtension(() -> new TwitterComponentVerifierExtension(componentVerifierScheme)); } + @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { TwitterConfiguration properties = new TwitterConfiguration(); properties.setConsumerKey(consumerKey); @@ -162,4 +166,11 @@ public Integer getHttpProxyPort() { return httpProxyPort; } + /** + * Get a verifier for the component. + */ + @Override + public ComponentVerifier getVerifier() { + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); + } } diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java index a1b7e5ddc5fff..92ea50588dd93 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponent.java @@ -19,12 +19,7 @@ import java.util.Map; import org.apache.camel.CamelContext; -import org.apache.camel.ComponentVerifier; import org.apache.camel.Endpoint; -import org.apache.camel.VerifiableComponent; -import org.apache.camel.component.twitter.data.ConsumerType; -import org.apache.camel.component.twitter.data.EndpointType; -import org.apache.camel.impl.DefaultComponent; import org.apache.camel.spi.Metadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +30,7 @@ * @deprecated Use * {@link org.apache.camel.component.twitter.directmessage.TwitterDirectMessageComponent}, * {@link org.apache.camel.component.twitter.search.TwitterSearchComponent}, - * {@link org.apache.camel.component.twitter.streaming..TwitterStreamingComponent} or + * {@link org.apache.camel.component.twitter.streaming.TwitterStreamingComponent} or * {@link org.apache.camel.component.twitter.timeline.TwitterTimelineComponent} * instead. */ @@ -46,12 +41,14 @@ public class TwitterComponent extends AbstractTwitterComponent { private static final Logger LOG = LoggerFactory.getLogger(TwitterComponent.class); public TwitterComponent() { + super("twitter"); } public TwitterComponent(CamelContext context) { - super(context); + super(context, "twitter"); } + @Override protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { String[] tokens = remaining.split("/"); LOG.warn("The scheme syntax 'twitter:{}' has been deprecated. Use 'twitter-{}' instead.", tokens[0], tokens[0]); @@ -73,11 +70,4 @@ protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, endpoint.setKeywords(getAndRemoveParameter(parameters, "keywords", String.class)); return endpoint; } - - /** - * Get a verifier for the twitter component. - */ - public ComponentVerifier getVerifier() { - return new DefaultTwitterComponentVerifier(this); - } } diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java similarity index 80% rename from components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java rename to components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java index cdc1d6e3e5ad6..f92fa847cff88 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/DefaultTwitterComponentVerifier.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtension.java @@ -18,22 +18,21 @@ import java.util.Map; -import org.apache.camel.ComponentVerifier; -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.camel.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorHelper; import twitter4j.Twitter; import twitter4j.TwitterException; -public class DefaultTwitterComponentVerifier extends DefaultComponentVerifier { +public final class TwitterComponentVerifierExtension extends DefaultComponentVerifierExtension { - public DefaultTwitterComponentVerifier(AbstractTwitterComponent component) { - super("twitter", component.getCamelContext()); + public TwitterComponentVerifierExtension() { + this("twitter"); } - public DefaultTwitterComponentVerifier(AbstractTwitterComponent component, String scheme) { - super(scheme, component.getCamelContext()); + public TwitterComponentVerifierExtension(String scheme) { + super(scheme); } // ********************************* @@ -80,8 +79,8 @@ private void verifyCredentials(ResultBuilder builder, Map parame .detail("twitter_exception_code", e.getExceptionCode()) .detail("twitter_exception_message", e.getMessage()) .detail("twitter_exception_caused-by-network-issue", e.isCausedByNetworkIssue()) - .detail(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName()) - .detail(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e); + .detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName()) + .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e); // For a complete list of error codes see: // https://dev.twitter.com/overview/api/response-codes diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java index 516bb3139fb77..7ad0636176a04 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/directmessage/TwitterDirectMessageComponent.java @@ -18,10 +18,9 @@ import java.util.Map; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.component.twitter.AbstractTwitterComponent; -import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier; import org.apache.camel.component.twitter.TwitterConfiguration; import org.apache.camel.spi.Metadata; @@ -31,14 +30,16 @@ @Metadata(label = "verifiers", enums = "parameters,connectivity") public class TwitterDirectMessageComponent extends AbstractTwitterComponent { - protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { - return new TwitterDirectMessageEndpoint(uri, remaining, this, properties); + public TwitterDirectMessageComponent() { + super("twitter-directmessage"); + } + + public TwitterDirectMessageComponent(CamelContext context) { + super(context, "twitter-directmessage"); } - /** - * Get a verifier for the twitter directmessage component. - */ - public ComponentVerifier getVerifier() { - return new DefaultTwitterComponentVerifier(this, "twitter-directmessage"); + @Override + protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { + return new TwitterDirectMessageEndpoint(uri, remaining, this, properties); } } diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java index 84578871683e2..5123ab202019c 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/search/TwitterSearchComponent.java @@ -18,11 +18,9 @@ import java.util.Map; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; -import org.apache.camel.VerifiableComponent; import org.apache.camel.component.twitter.AbstractTwitterComponent; -import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier; import org.apache.camel.component.twitter.TwitterConfiguration; import org.apache.camel.spi.Metadata; @@ -32,14 +30,16 @@ @Metadata(label = "verifiers", enums = "parameters,connectivity") public class TwitterSearchComponent extends AbstractTwitterComponent { - protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { - return new TwitterSearchEndpoint(uri, remaining, this, properties); + public TwitterSearchComponent() { + super("twitter-search"); + } + + public TwitterSearchComponent(CamelContext context) { + super(context, "twitter-search"); } - /** - * Get a verifier for the twitter search component. - */ - public ComponentVerifier getVerifier() { - return new DefaultTwitterComponentVerifier(this, "twitter-search"); + @Override + protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { + return new TwitterSearchEndpoint(uri, remaining, this, properties); } } diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java index 1ccf16088a832..5de57a09cc19b 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponent.java @@ -18,10 +18,9 @@ import java.util.Map; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.component.twitter.AbstractTwitterComponent; -import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier; import org.apache.camel.component.twitter.TwitterConfiguration; import org.apache.camel.spi.Metadata; @@ -31,15 +30,17 @@ @Metadata(label = "verifiers", enums = "parameters,connectivity") public class TwitterStreamingComponent extends AbstractTwitterComponent { + public TwitterStreamingComponent() { + super("twitter-streaming"); + } + + public TwitterStreamingComponent(CamelContext context) { + super(context, "twitter-streaming"); + } + + @Override protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { String keywords = getAndRemoveParameter(parameters, "keywords", String.class); return new TwitterStreamingEndpoint(uri, remaining, keywords, this, properties); } - - /** - * Get a verifier for the twitter streaming component. - */ - public ComponentVerifier getVerifier() { - return new DefaultTwitterComponentVerifier(this, "twitter-streaming"); - } } diff --git a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java index 0c9c885c6e193..ece0d0fd60e95 100644 --- a/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java +++ b/components/camel-twitter/src/main/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponent.java @@ -18,10 +18,9 @@ import java.util.Map; -import org.apache.camel.ComponentVerifier; +import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.component.twitter.AbstractTwitterComponent; -import org.apache.camel.component.twitter.DefaultTwitterComponentVerifier; import org.apache.camel.component.twitter.TwitterConfiguration; import org.apache.camel.spi.Metadata; @@ -31,16 +30,17 @@ @Metadata(label = "verifiers", enums = "parameters,connectivity") public class TwitterTimelineComponent extends AbstractTwitterComponent { + public TwitterTimelineComponent() { + super("twitter-timeline"); + } + + public TwitterTimelineComponent(CamelContext context) { + super(context, "twitter-timeline"); + } + @Override protected Endpoint doCreateEndpoint(TwitterConfiguration properties, String uri, String remaining, Map parameters) throws Exception { String user = getAndRemoveParameter(parameters, "user", String.class); return new TwitterTimelineEndpoint(uri, remaining, user, this, properties); } - - /** - * Get a verifier for the twitter timeline component. - */ - public ComponentVerifier getVerifier() { - return new DefaultTwitterComponentVerifier(this, "twitter-timeline"); - } } diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..21331da3a3abd --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierExtensionTest.java @@ -0,0 +1,82 @@ +/** + * 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.twitter; + +import java.util.Map; + +import org.apache.camel.Component; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.junit.Assert; +import org.junit.Test; + + +public abstract class AbstractComponentVerifierExtensionTest extends CamelTwitterTestSupport { + + protected abstract String getComponentScheme(); + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testConnectivity() { + Component component = context().getComponent(getComponentScheme()); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = getParameters(); + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testInvalidKeyConfiguration() { + Component component = context().getComponent(getComponentScheme()); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = getParameters(); + parameters.put("consumerKey", "invalid"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_status_code"))); + Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_error_code"))); + } + + @Test + public void testInvalidTokenConfiguration() { + Component component = context().getComponent(getComponentScheme()); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = getParameters(); + parameters.put("accessToken", "invalid"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_status_code"))); + Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.asAttribute("twitter_error_code"))); + Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size()); + Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next()); + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java new file mode 100644 index 0000000000000..703f7cf4cc261 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/AbstractComponentVerifierTest.java @@ -0,0 +1,81 @@ +/** + * 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.twitter; + +import java.util.Map; + +import org.apache.camel.ComponentVerifier; +import org.junit.Assert; +import org.junit.Test; + + +public abstract class AbstractComponentVerifierTest extends CamelTwitterTestSupport { + + protected abstract String getComponentScheme(); + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testConnectivity() { + AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class); + ComponentVerifier verifier = component.getVerifier(); + + Map parameters = getParameters(); + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); + } + + @Test + public void testInvalidKeyConfiguration() { + AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class); + ComponentVerifier verifier = component.getVerifier(); + + Map parameters = getParameters(); + parameters.put("consumerKey", "invalid"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_status_code"))); + Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_error_code"))); + } + + @Test + public void testInvalidTokenConfiguration() { + AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class); + ComponentVerifier verifier = component.getVerifier(); + + Map parameters = getParameters(); + parameters.put("accessToken", "invalid"); + + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); + Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_status_code"))); + Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.asAttribute("twitter_error_code"))); + Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size()); + Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next()); + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java deleted file mode 100644 index 28c29920a6a8e..0000000000000 --- a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/CamelComponentVerifierTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.component.twitter; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.camel.ComponentVerifier; -import org.apache.camel.ComponentVerifier.VerificationError; -import org.apache.camel.component.twitter.search.TwitterSearchComponent; -import org.junit.Assert; -import org.junit.Test; - -import static org.apache.camel.ComponentVerifier.VerificationError.asAttribute; - -public class CamelComponentVerifierTest extends CamelTwitterTestSupport { - - @Override - public boolean isUseRouteBuilder() { - return false; - } - - @Test - public void testConnectivity() { - TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class); - DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier(); - - Map parameters = getParameters(); - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); - - Assert.assertEquals(ComponentVerifier.Result.Status.OK, result.getStatus()); - } - - @Test - public void testInvalidKeyConfiguration() { - TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class); - DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier(); - - Map parameters = getParameters(); - parameters.put("consumerKey", "invalid"); - - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); - - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); - Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); - Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(asAttribute("twitter_status_code"))); - Assert.assertEquals(32, result.getErrors().get(0).getDetails().get(asAttribute("twitter_error_code"))); - } - - @Test - public void testInvalidTokenConfiguration() { - TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class); - DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier(); - - Map parameters = getParameters(); - parameters.put("accessToken", "invalid"); - - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); - - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); - Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, result.getErrors().get(0).getCode()); - Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(asAttribute("twitter_status_code"))); - Assert.assertEquals(89, result.getErrors().get(0).getDetails().get(asAttribute("twitter_error_code"))); - Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size()); - Assert.assertEquals("accessToken", result.getErrors().get(0).getParameterKeys().iterator().next()); - } - - @Test - public void testEmptyConfiguration() { - TwitterSearchComponent component = context().getComponent("twitter-search", TwitterSearchComponent.class); - DefaultTwitterComponentVerifier verifier = (DefaultTwitterComponentVerifier)component.getVerifier(); - - { - // Parameters validation - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, Collections.emptyMap()); - - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); - Assert.assertEquals(5, result.getErrors().size()); - - List expected = new LinkedList<>(); - expected.add("keywords"); - expected.add("consumerKey"); - expected.add("consumerSecret"); - expected.add("accessToken"); - expected.add("accessTokenSecret"); - - for (VerificationError error : result.getErrors()) { - expected.removeAll(error.getParameterKeys()); - } - - Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty()); - } - - { - // Connectivity validation - ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, Collections.emptyMap()); - - Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); - Assert.assertEquals(1, result.getErrors().size()); - Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); - Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); - Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException); - } - } -} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..d3fc2da27dcd5 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierExtensionTest.java @@ -0,0 +1,24 @@ +/** + * 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.twitter; + +public class TwitterComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest { + @Override + protected String getComponentScheme() { + return "twitter"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java new file mode 100644 index 0000000000000..5d24a04466bf1 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/TwitterComponentVerifierTest.java @@ -0,0 +1,24 @@ +/** + * 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.twitter; + +public class TwitterComponentVerifierTest extends AbstractComponentVerifierTest { + @Override + protected String getComponentScheme() { + return "twitter"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..a5de409488929 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierExtensionTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.directmessage; + +import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest; + +public class TwitterDirectmessageComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest { + @Override + protected String getComponentScheme() { + return "twitter-directmessage"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java new file mode 100644 index 0000000000000..829271289da96 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/directmessage/TwitterDirectmessageComponentVerifierTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.directmessage; + +import org.apache.camel.component.twitter.AbstractComponentVerifierTest; + +public class TwitterDirectmessageComponentVerifierTest extends AbstractComponentVerifierTest { + @Override + protected String getComponentScheme() { + return "twitter-directmessage"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..ae8428f2006b5 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierExtensionTest.java @@ -0,0 +1,72 @@ +/** + * 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.twitter.search; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.apache.camel.Component; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest; +import org.junit.Assert; +import org.junit.Test; + +public class TwitterSearchComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest { + @Override + protected String getComponentScheme() { + return "twitter-search"; + } + + @Test + public void testEmptyConfiguration() { + Component component = context().getComponent(getComponentScheme()); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + { + // Parameters validation + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(5, result.getErrors().size()); + + List expected = new LinkedList<>(); + expected.add("keywords"); + expected.add("consumerKey"); + expected.add("consumerSecret"); + expected.add("accessToken"); + expected.add("accessTokenSecret"); + + for (ComponentVerifierExtension.VerificationError error : result.getErrors()) { + expected.removeAll(error.getParameterKeys()); + } + + Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty()); + } + + { + // Connectivity validation + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException); + } + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java new file mode 100644 index 0000000000000..6bf6275880461 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/search/TwitterSearchComponentVerifierTest.java @@ -0,0 +1,72 @@ +/** + * 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.twitter.search; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.apache.camel.ComponentVerifier; +import org.apache.camel.component.twitter.AbstractComponentVerifierTest; +import org.apache.camel.component.twitter.AbstractTwitterComponent; +import org.junit.Assert; +import org.junit.Test; + +public class TwitterSearchComponentVerifierTest extends AbstractComponentVerifierTest { + @Override + protected String getComponentScheme() { + return "twitter-search"; + } + + @Test + public void testEmptyConfiguration() { + AbstractTwitterComponent component = context().getComponent(getComponentScheme(), AbstractTwitterComponent.class); + ComponentVerifier verifier = component.getVerifier(); + + { + // Parameters validation + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(5, result.getErrors().size()); + + List expected = new LinkedList<>(); + expected.add("keywords"); + expected.add("consumerKey"); + expected.add("consumerSecret"); + expected.add("accessToken"); + expected.add("accessTokenSecret"); + + for (ComponentVerifier.VerificationError error : result.getErrors()) { + expected.removeAll(error.getParameterKeys()); + } + + Assert.assertTrue("Missing expected params: " + expected.toString(), expected.isEmpty()); + } + + { + // Connectivity validation + ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, Collections.emptyMap()); + + Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifier.VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode()); + Assert.assertNotNull(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE)); + Assert.assertTrue(result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof IllegalArgumentException); + } + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..9dcdb78c5769b --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierExtensionTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.streaming; + +import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest; + +public class TwitterStreamingComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest { + @Override + protected String getComponentScheme() { + return "twitter-streaming"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java new file mode 100644 index 0000000000000..8d6da45a36d20 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/streaming/TwitterStreamingComponentVerifierTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.streaming; + +import org.apache.camel.component.twitter.AbstractComponentVerifierTest; + +public class TwitterStreamingComponentVerifierTest extends AbstractComponentVerifierTest { + @Override + protected String getComponentScheme() { + return "twitter-streaming"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..1ea478ce8c75a --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierExtensionTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.timeline; + +import org.apache.camel.component.twitter.AbstractComponentVerifierExtensionTest; + +public class TwitterTimelineComponentVerifierExtensionTest extends AbstractComponentVerifierExtensionTest { + @Override + protected String getComponentScheme() { + return "twitter-timeline"; + } +} diff --git a/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java new file mode 100644 index 0000000000000..2081db5c9de56 --- /dev/null +++ b/components/camel-twitter/src/test/java/org/apache/camel/component/twitter/timeline/TwitterTimelineComponentVerifierTest.java @@ -0,0 +1,26 @@ +/** + * 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.twitter.timeline; + +import org.apache.camel.component.twitter.AbstractComponentVerifierTest; + +public class TwitterTimelineComponentVerifierTest extends AbstractComponentVerifierTest { + @Override + protected String getComponentScheme() { + return "twitter-timeline"; + } +} diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java index ff522f706113b..b3623d453e103 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java @@ -31,6 +31,7 @@ import org.apache.camel.Producer; import org.apache.camel.SSLContextParametersAware; import org.apache.camel.VerifiableComponent; +import org.apache.camel.component.extension.ComponentVerifierExtension; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.RestApiConsumerFactory; @@ -67,10 +68,13 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF private UndertowHostOptions hostOptions; public UndertowComponent() { + this(null); } public UndertowComponent(CamelContext context) { super(context); + + registerExtension(UndertowComponentVerifierExtension::new); } @Override @@ -361,11 +365,9 @@ public void setHostOptions(UndertowHostOptions hostOptions) { this.hostOptions = hostOptions; } - /** - * - */ + @Override public ComponentVerifier getVerifier() { - return new UndertowComponentVerifier(this); + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } } diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java similarity index 95% rename from components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java rename to components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java index 03a73f54e3181..7be54be45f11f 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifier.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java @@ -34,9 +34,9 @@ import io.undertow.util.Headers; import io.undertow.util.HttpString; import io.undertow.util.Methods; -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.component.extension.verifier.DefaultComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; import org.apache.camel.util.FileUtil; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; @@ -47,13 +47,10 @@ import org.xnio.Xnio; import org.xnio.XnioWorker; -public final class UndertowComponentVerifier extends DefaultComponentVerifier { - private final UndertowComponent component; +public final class UndertowComponentVerifierExtension extends DefaultComponentVerifierExtension { - public UndertowComponentVerifier(UndertowComponent component) { - super("undertow", component.getCamelContext()); - - this.component = component; + UndertowComponentVerifierExtension() { + super("undertow"); } // ********************************* diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java new file mode 100644 index 0000000000000..dc6cd6e3876a3 --- /dev/null +++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtensionTest.java @@ -0,0 +1,104 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.undertow; + +import java.nio.channels.UnresolvedAddressException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.Component; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.junit.Assert; +import org.junit.Test; + +public class UndertowComponentVerifierExtensionTest extends BaseUndertowTest { + @Test + public void testParameters() throws Exception { + Component component = context().getComponent("undertow"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpURI", "http://localhost:" + getPort()); + parameters.put("tcpNoDelay", "true"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testMissingParameters() throws Exception { + Component component = context().getComponent("undertow"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("tcpNoDelay", "true"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode()); + Assert.assertEquals(1, result.getErrors().get(0).getParameterKeys().size()); + Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("httpURI")); + } + + @Test + public void testConnectivity() throws Exception { + Component component = context().getComponent("undertow"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpURI", "http://localhost:" + getPort()); + parameters.put("tcpNoDelay", "true"); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus()); + } + + @Test + public void testConnectivityError() throws Exception { + Component component = context().getComponent("undertow"); + ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new); + + Map parameters = new HashMap<>(); + parameters.put("httpURI", "http://no-host:" + getPort()); + + ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters); + + Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus()); + Assert.assertEquals(1, result.getErrors().size()); + + ComponentVerifierExtension.VerificationError error = result.getErrors().get(0); + + Assert.assertEquals(ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION, error.getCode()); + Assert.assertTrue(error.getDetail(ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof UnresolvedAddressException); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("undertow:http://localhost:{{port}}") + .process(e -> e.getOut().setBody("ok")); + } + }; + } +} diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java index c8ca4592b0e74..23a2396802354 100644 --- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java +++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java @@ -211,7 +211,7 @@ private void createConnectorConfigurationSource(String packageName, ComponentMod prefix += connectorScheme.toLowerCase(Locale.US); for (OptionModel option : model.getComponentOptions()) { - boolean isComponentOption= componentOptions != null && componentOptions.stream().anyMatch(o -> o.equals(option.getName())); + boolean isComponentOption = componentOptions != null && componentOptions.stream().anyMatch(o -> o.equals(option.getName())); boolean isEndpointOption = endpointOptions != null && endpointOptions.stream().anyMatch(o -> o.equals(option.getName())); // only include the options that has been explicit configured in the diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java index 50d1407197589..d9f24eb0be1e6 100644 --- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java +++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java @@ -26,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.camel.CamelContext; import org.apache.camel.Component; @@ -36,9 +37,10 @@ import org.apache.camel.VerifiableComponent; import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.component.extension.ComponentVerifierExtension; +import org.apache.camel.component.extension.verifier.ResultBuilder; +import org.apache.camel.component.extension.verifier.ResultErrorBuilder; import org.apache.camel.impl.DefaultComponent; -import org.apache.camel.impl.verifier.ResultBuilder; -import org.apache.camel.impl.verifier.ResultErrorBuilder; import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; @@ -83,6 +85,8 @@ protected DefaultConnectorComponent(String componentName, String className) { if (!catalog.findComponentNames().contains(componentScheme)) { this.catalog.addComponent(componentScheme, this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme)); } + + registerExtension(this::getComponentVerifierExtension); } @Override @@ -172,16 +176,20 @@ public void setOptions(Map baseComponentOptions) { this.options = Collections.unmodifiableMap(new HashMap<>(baseComponentOptions)); } - @SuppressWarnings("unchecked") @Override public ComponentVerifier getVerifier() { + return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); + } + + private ComponentVerifierExtension getComponentVerifierExtension() { try { // Create the component but no need to add it to the camel context // nor to start it. final Component component = createNewBaseComponent(); + final Optional extension = component.getExtension(ComponentVerifierExtension.class); - if (component instanceof VerifiableComponent) { - return (scope, map) -> { + if (extension.isPresent()) { + return (ComponentVerifierExtension.Scope scope, Map map) -> { Map options; try { @@ -192,18 +200,18 @@ public ComponentVerifier getVerifier() { } catch (URISyntaxException | NoTypeConversionAvailableException e) { // If a failure is detected while reading the catalog, wrap it // and stop the validation step. - return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope) + return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.OK, scope) .error(ResultErrorBuilder.withException(e).build()) .build(); } - return ((VerifiableComponent) component).getVerifier().verify(scope, options); + return extension.get().verify(scope, options); }; } else { return (scope, map) -> { - return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope) + return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.UNSUPPORTED, scope) .error( - ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED) + ResultErrorBuilder.withCode(ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED) .detail("camel_connector_name", getConnectorName()) .detail("camel_component_name", getComponentName()) .build()) @@ -212,7 +220,7 @@ public ComponentVerifier getVerifier() { } } catch (Exception e) { return (scope, map) -> { - return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope) + return ResultBuilder.withStatusAndScope(ComponentVerifierExtension.Result.Status.OK, scope) .error(ResultErrorBuilder.withException(e).build()) .build(); };