Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.support;
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.CamelContextAware;
import org.apache.camel.Component;
import org.apache.camel.Endpoint;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.NoFactoryAvailableException;
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.component.extension.ComponentExtension;
import org.apache.camel.spi.GeneratedPropertyConfigurer;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.PropertyConfigurer;
import org.apache.camel.spi.PropertyConfigurerAware;
import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.PropertiesHelper;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.URISupport;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
import org.apache.camel.util.function.Suppliers;
/**
* Default component to use for base for components implementations.
*/
public abstract class DefaultComponent extends ServiceSupport implements Component {
/**
* Simple RAW() pattern used only for validating URI in this class
*/
private static final Pattern RAW_PATTERN = Pattern.compile("RAW[({].*&&.*[)}]");
private static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/configurer/";
private volatile GeneratedPropertyConfigurer componentPropertyConfigurer;
private volatile GeneratedPropertyConfigurer endpointPropertyConfigurer;
private final List> extensions = new ArrayList<>();
private CamelContext camelContext;
@Metadata(label = "advanced",
description = "Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities")
private boolean basicPropertyBinding;
public DefaultComponent() {
}
public DefaultComponent(CamelContext context) {
this.camelContext = context;
}
@Deprecated
protected String preProcessUri(String uri) {
return UnsafeUriCharactersEncoder.encode(uri);
}
@Override
public Endpoint createEndpoint(String uri, Map properties) throws Exception {
ObjectHelper.notNull(getCamelContext(), "camelContext");
// check URI string to the unsafe URI characters
String encodedUri = preProcessUri(uri);
URI u = new URI(encodedUri);
String path;
if (u.getScheme() != null) {
// if there is a scheme then there is also a path
path = URISupport.extractRemainderPath(u, useRawUri());
} else {
// this uri has no context-path as the leading text is the component name (scheme)
path = null;
}
// use encoded or raw uri?
Map parameters;
if (useRawUri()) {
// when using raw uri then the query is taking from the uri as is
String query;
int idx = uri.indexOf('?');
if (idx > -1) {
query = uri.substring(idx + 1);
} else {
query = u.getRawQuery();
}
// and use method parseQuery
parameters = URISupport.parseQuery(query, true);
} else {
// however when using the encoded (default mode) uri then the query,
// is taken from the URI (ensures values is URI encoded)
// and use method parseParameters
parameters = URISupport.parseParameters(u);
}
if (properties != null) {
parameters.putAll(properties);
}
// This special property is only to identify endpoints in a unique manner
parameters.remove("hash");
validateURI(uri, path, parameters);
if (log.isTraceEnabled()) {
// at trace level its okay to have parameters logged, that may contain passwords
log.trace("Creating endpoint uri=[{}], path=[{}], parameters=[{}]", URISupport.sanitizeUri(uri), URISupport.sanitizePath(path), parameters);
} else if (log.isDebugEnabled()) {
// but at debug level only output sanitized uris
log.debug("Creating endpoint uri=[{}], path=[{}]", URISupport.sanitizeUri(uri), URISupport.sanitizePath(path));
}
Endpoint endpoint = createEndpoint(uri, path, parameters);
if (endpoint == null) {
return null;
}
// setup whether to use basic property binding or not which must be done before we set properties
boolean basic = getAndRemoveParameter(parameters, "basicPropertyBinding", boolean.class, basicPropertyBinding);
if (endpoint instanceof DefaultEndpoint) {
((DefaultEndpoint) endpoint).setBasicPropertyBinding(basic);
}
endpoint.configureProperties(parameters);
if (useIntrospectionOnEndpoint()) {
setProperties(endpoint, parameters);
}
// if endpoint is strict (not lenient) and we have unknown parameters configured then
// fail if there are parameters that could not be set, then they are probably misspell or not supported at all
if (!endpoint.isLenientProperties()) {
validateParameters(uri, parameters, null);
}
afterConfiguration(uri, path, endpoint, parameters);
return endpoint;
}
@Override
public Endpoint createEndpoint(String uri) throws Exception {
ObjectHelper.notNull(getCamelContext(), "camelContext");
// check URI string to the unsafe URI characters
String encodedUri = preProcessUri(uri);
URI u = new URI(encodedUri);
String path;
if (u.getScheme() != null) {
// if there is a scheme then there is also a path
path = URISupport.extractRemainderPath(u, useRawUri());
} else {
// this uri has no context-path as the leading text is the component name (scheme)
path = null;
}
Map parameters;
if (useRawUri()) {
// when using raw uri then the query is taking from the uri as is
String query;
int idx = uri.indexOf('?');
if (idx > -1) {
query = uri.substring(idx + 1);
} else {
query = u.getRawQuery();
}
// and use method parseQuery
parameters = URISupport.parseQuery(query, true);
} else {
// however when using the encoded (default mode) uri then the query,
// is taken from the URI (ensures values is URI encoded)
// and use method parseParameters
parameters = URISupport.parseParameters(u);
}
// parameters using raw syntax: RAW(value)
// should have the token removed, so its only the value we have in parameters, as we are about to create
// an endpoint and want to have the parameter values without the RAW tokens
URISupport.resolveRawParameterValues(parameters);
// use encoded or raw uri?
uri = useRawUri() ? uri : encodedUri;
validateURI(uri, path, parameters);
if (log.isTraceEnabled()) {
// at trace level its okay to have parameters logged, that may contain passwords
log.trace("Creating endpoint uri=[{}], path=[{}], parameters=[{}]", URISupport.sanitizeUri(uri), URISupport.sanitizePath(path), parameters);
} else if (log.isDebugEnabled()) {
// but at debug level only output sanitized uris
log.debug("Creating endpoint uri=[{}], path=[{}]", URISupport.sanitizeUri(uri), URISupport.sanitizePath(path));
}
Endpoint endpoint = createEndpoint(uri, path, parameters);
if (endpoint == null) {
return null;
}
// inject camel context
endpoint.setCamelContext(getCamelContext());
// setup whether to use basic property binding or not which must be done before we set properties
boolean basic = getAndRemoveParameter(parameters, "basicPropertyBinding", boolean.class, basicPropertyBinding);
if (endpoint instanceof DefaultEndpoint) {
((DefaultEndpoint) endpoint).setBasicPropertyBinding(basic);
}
endpoint.configureProperties(parameters);
if (useIntrospectionOnEndpoint()) {
setProperties(endpoint, parameters);
}
// if endpoint is strict (not lenient) and we have unknown parameters configured then
// fail if there are parameters that could not be set, then they are probably misspell or not supported at all
if (!endpoint.isLenientProperties()) {
validateParameters(uri, parameters, null);
}
afterConfiguration(uri, path, endpoint, parameters);
return endpoint;
}
@Override
public boolean useRawUri() {
// should use encoded uri by default
return false;
}
/**
* Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
*/
public boolean isBasicPropertyBinding() {
return basicPropertyBinding;
}
/**
* Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
*/
public void setBasicPropertyBinding(boolean basicPropertyBinding) {
this.basicPropertyBinding = basicPropertyBinding;
}
/**
* Strategy to do post configuration logic.
*
* Can be used to construct an URI based on the remaining parameters. For example the parameters that configures
* the endpoint have been removed from the parameters which leaves only the additional parameters left.
*
* @param uri the uri
* @param remaining the remaining part of the URI without the query parameters or component prefix
* @param endpoint the created endpoint
* @param parameters the remaining parameters after the endpoint has been created and parsed the parameters
* @throws Exception can be thrown to indicate error creating the endpoint
*/
protected void afterConfiguration(String uri, String remaining, Endpoint endpoint, Map parameters) throws Exception {
// noop
}
/**
* Strategy for validation of parameters, that was not able to be resolved to any endpoint options.
*
* @param uri the uri
* @param parameters the parameters, an empty map if no parameters given
* @param optionPrefix optional prefix to filter the parameters for validation. Use null for validate all.
* @throws ResolveEndpointFailedException should be thrown if the URI validation failed
*/
protected void validateParameters(String uri, Map parameters, String optionPrefix) {
if (parameters == null || parameters.isEmpty()) {
return;
}
Map param = parameters;
if (optionPrefix != null) {
param = PropertiesHelper.extractProperties(parameters, optionPrefix);
}
if (param.size() > 0) {
throw new ResolveEndpointFailedException(uri, "There are " + param.size()
+ " parameters that couldn't be set on the endpoint."
+ " Check the uri if the parameters are spelt correctly and that they are properties of the endpoint."
+ " Unknown parameters=[" + param + "]");
}
}
/**
* Strategy for validation of the uri when creating the endpoint.
*
* @param uri the uri
* @param path the path - part after the scheme
* @param parameters the parameters, an empty map if no parameters given
* @throws ResolveEndpointFailedException should be thrown if the URI validation failed
*/
protected void validateURI(String uri, String path, Map parameters) {
// check for uri containing double && markers without include by RAW
if (uri.contains("&&")) {
Matcher m = RAW_PATTERN.matcher(uri);
// we should skip the RAW part
if (!m.find()) {
throw new ResolveEndpointFailedException(uri, "Invalid uri syntax: Double && marker found. "
+ "Check the uri and remove the duplicate & marker.");
}
}
// if we have a trailing & then that is invalid as well
if (uri.endsWith("&")) {
throw new ResolveEndpointFailedException(uri, "Invalid uri syntax: Trailing & marker found. "
+ "Check the uri and remove the trailing & marker.");
}
}
@Override
public CamelContext getCamelContext() {
return camelContext;
}
@Override
public void setCamelContext(CamelContext context) {
this.camelContext = context;
}
@Override
protected void doInit() throws Exception {
org.apache.camel.spi.annotations.Component ann = ObjectHelper.getAnnotation(this, org.apache.camel.spi.annotations.Component.class);
if (ann != null) {
String name = ann.value();
// just grab first scheme name if the component has scheme alias (eg http,https)
if (name.contains(",")) {
name = StringHelper.before(name, ",");
}
try {
log.trace("Discovering optional component property configurer class for component: {}", name);
Optional> clazz = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH)
.findOptionalClass(name + "-component", null);
clazz.ifPresent(c -> componentPropertyConfigurer = org.apache.camel.support.ObjectHelper.newInstance(c, GeneratedPropertyConfigurer.class));
if (log.isDebugEnabled() && componentPropertyConfigurer != null) {
log.debug("Discovered component property configurer: {} -> {}", name, componentPropertyConfigurer);
}
log.trace("Discovering optional endpoint property configurer class for component: {}", name);
clazz = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH)
.findOptionalClass(name + "-endpoint", null);
clazz.ifPresent(c -> endpointPropertyConfigurer = org.apache.camel.support.ObjectHelper.newInstance(c, GeneratedPropertyConfigurer.class));
if (log.isDebugEnabled() && endpointPropertyConfigurer != null) {
log.debug("Discovered endpoint property configurer: {} -> {}", name, endpointPropertyConfigurer);
}
} catch (NoFactoryAvailableException e) {
// ignore
}
}
}
@Override
protected void doStart() throws Exception {
ObjectHelper.notNull(getCamelContext(), "camelContext");
}
@Override
protected void doStop() throws Exception {
// noop
}
/**
* A factory method allowing derived components to create a new endpoint
* from the given URI, remaining path and optional parameters
*
* @param uri the full URI of the endpoint
* @param remaining the remaining part of the URI without the query
* parameters or component prefix
* @param parameters the optional parameters passed in
* @return a newly created endpoint or null if the endpoint cannot be
* created based on the inputs
* @throws Exception is thrown if error creating the endpoint
*/
protected abstract Endpoint createEndpoint(String uri, String remaining, Map parameters)
throws Exception;
/**
* Sets the bean properties on the given bean
*
* @param bean the bean
* @param parameters properties to set
*/
protected void setProperties(Object bean, Map parameters) throws Exception {
setProperties(getCamelContext(), bean, parameters);
}
/**
* Sets the bean properties on the given bean using the given {@link CamelContext}.
*
* @param camelContext the {@link CamelContext} to use
* @param bean the bean
* @param parameters properties to set
*/
protected void setProperties(CamelContext camelContext, Object bean, Map parameters) throws Exception {
if (parameters == null || parameters.isEmpty()) {
return;
}
boolean basic = basicPropertyBinding || "true".equals(parameters.getOrDefault("basicPropertyBinding", "false"));
if (basic) {
// use basic binding
PropertyBindingSupport.build()
.withPlaceholder(false).withNesting(false).withDeepNesting(false).withReference(false)
.bind(camelContext, bean, parameters);
} else {
PropertyConfigurer configurer = null;
if (bean instanceof Component) {
configurer = getComponentPropertyConfigurer();
} else if (bean instanceof Endpoint) {
configurer = getEndpointPropertyConfigurer();
} else if (bean instanceof PropertyConfigurerAware) {
configurer = ((PropertyConfigurerAware) bean).getPropertyConfigurer(bean);
}
// use advanced binding
PropertyBindingSupport.build().withConfigurer(configurer).bind(camelContext, bean, parameters);
}
}
@Override
public PropertyConfigurer getComponentPropertyConfigurer() {
return componentPropertyConfigurer;
}
@Override
public PropertyConfigurer getEndpointPropertyConfigurer() {
return endpointPropertyConfigurer;
}
/**
* Derived classes may wish to overload this to prevent the default introspection of URI parameters
* on the created {@link Endpoint} instance.
*/
protected boolean useIntrospectionOnEndpoint() {
return true;
}
/**
* Gets the parameter and remove it from the parameter map. This method doesn't resolve
* reference parameters in the registry.
*
* @param parameters the parameters
* @param key the key
* @param type the requested type to convert the value from the parameter
* @return the converted value parameter, null if parameter does not exists.
* @see #resolveAndRemoveReferenceParameter(Map, String, Class)
*/
public T getAndRemoveParameter(Map parameters, String key, Class type) {
return getAndRemoveParameter(parameters, key, type, null);
}
/**
* Gets the parameter and remove it from the parameter map. This method doesn't resolve
* reference parameters in the registry.
*
* @param parameters the parameters
* @param key the key
* @param type the requested type to convert the value from the parameter
* @param defaultValue use this default value if the parameter does not contain the key
* @return the converted value parameter
* @see #resolveAndRemoveReferenceParameter(Map, String, Class, Object)
*/
public T getAndRemoveParameter(Map parameters, String key, Class type, T defaultValue) {
Object value = parameters.remove(key);
if (value != null) {
// if we have a value then convert it
return CamelContextHelper.mandatoryConvertTo(getCamelContext(), type, value);
} else {
value = defaultValue;
}
if (value == null) {
return null;
}
return CamelContextHelper.mandatoryConvertTo(getCamelContext(), type, value);
}
/**
* Gets the parameter and remove it from the parameter map. This method resolves
* reference parameters in the registry as well.
*
* @param parameters the parameters
* @param key the key
* @param type the requested type to convert the value from the parameter
* @return the converted value parameter
*/
public T getAndRemoveOrResolveReferenceParameter(Map parameters, String key, Class type) {
return getAndRemoveOrResolveReferenceParameter(parameters, key, type, null);
}
/**
* Gets the parameter and remove it from the parameter map. This method resolves
* reference parameters in the registry as well.
*
* @param parameters the parameters
* @param key the key
* @param type the requested type to convert the value from the parameter
* @param defaultValue use this default value if the parameter does not contain the key
* @return the converted value parameter
*/
public T getAndRemoveOrResolveReferenceParameter(Map parameters, String key, Class type, T defaultValue) {
String value = getAndRemoveParameter(parameters, key, String.class);
if (value == null) {
return defaultValue;
} else if (EndpointHelper.isReferenceParameter(value)) {
return EndpointHelper.resolveReferenceParameter(getCamelContext(), value, type);
} else {
return getCamelContext().getTypeConverter().convertTo(type, value);
}
}
/**
* Resolves a reference parameter in the registry and removes it from the map.
*
* @param type of object to lookup in the registry.
* @param parameters parameter map.
* @param key parameter map key.
* @param type type of object to lookup in the registry.
* @return the referenced object or null if the parameter map
* doesn't contain the key.
* @throws IllegalArgumentException if a non-null reference was not found in
* registry.
*/
public T resolveAndRemoveReferenceParameter(Map parameters, String key, Class type) {
return resolveAndRemoveReferenceParameter(parameters, key, type, null);
}
/**
* Resolves a reference parameter in the registry and removes it from the map.
*
* @param type of object to lookup in the registry.
* @param parameters parameter map.
* @param key parameter map key.
* @param type type of object to lookup in the registry.
* @param defaultValue default value to use if the parameter map doesn't
* contain the key.
* @return the referenced object or the default value.
* @throws IllegalArgumentException if referenced object was not found in
* registry.
*/
public T resolveAndRemoveReferenceParameter(Map parameters, String key, Class type, T defaultValue) {
String value = getAndRemoveParameter(parameters, key, String.class);
if (value == null) {
return defaultValue;
} else {
return EndpointHelper.resolveReferenceParameter(getCamelContext(), value, type);
}
}
/**
* Resolves a reference list parameter in the registry and removes it from
* the map.
*
* @param parameters parameter map.
* @param key parameter map key.
* @param elementType result list element type.
* @return the list of referenced objects or an empty list if the parameter
* map doesn't contain the key.
* @throws IllegalArgumentException if any of the referenced objects was
* not found in registry.
* @see EndpointHelper#resolveReferenceListParameter(CamelContext, String, Class)
*/
public List resolveAndRemoveReferenceListParameter(Map parameters, String key, Class elementType) {
return resolveAndRemoveReferenceListParameter(parameters, key, elementType, new ArrayList<>(0));
}
/**
* Resolves a reference list parameter in the registry and removes it from
* the map.
*
* @param parameters parameter map.
* @param key parameter map key.
* @param elementType result list element type.
* @param defaultValue default value to use if the parameter map doesn't
* contain the key.
* @return the list of referenced objects or the default value.
* @throws IllegalArgumentException if any of the referenced objects was
* not found in registry.
* @see EndpointHelper#resolveReferenceListParameter(CamelContext, String, Class)
*/
public List resolveAndRemoveReferenceListParameter(Map parameters, String key, Class elementType, List defaultValue) {
String value = getAndRemoveParameter(parameters, key, String.class);
if (value == null) {
return defaultValue;
} else {
return EndpointHelper.resolveReferenceListParameter(getCamelContext(), value, elementType);
}
}
/**
* Returns the reminder of the text if it starts with the prefix.
*
* Is useable for string parameters that contains commands.
*
* @param prefix the prefix
* @param text the text
* @return the reminder, or null if no reminder
*/
protected String ifStartsWithReturnRemainder(String prefix, String text) {
if (text.startsWith(prefix)) {
String remainder = text.substring(prefix.length());
if (remainder.length() > 0) {
return remainder;
}
}
return null;
}
protected void registerExtension(ComponentExtension extension) {
extensions.add(() -> extension);
}
protected 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 -> Component.trySetComponent(e, this))
.map(e -> CamelContextAware.trySetCamelContext(e, getCamelContext()));
}
}