org.apache.camel.impl.DefaultComponent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-core Show documentation
Show all versions of camel-core Show documentation
The Core Camel Java DSL based router
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.impl;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.camel.CamelContext;
import org.apache.camel.Component;
import org.apache.camel.ComponentConfiguration;
import org.apache.camel.Endpoint;
import org.apache.camel.EndpointConfiguration;
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.support.ServiceSupport;
import org.apache.camel.util.CamelContextHelper;
import org.apache.camel.util.EndpointHelper;
import org.apache.camel.util.IntrospectionSupport;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.URISupport;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default component to use for base for components implementations.
*/
public abstract class DefaultComponent extends ServiceSupport implements Component {
private static final Logger LOG = LoggerFactory.getLogger(DefaultComponent.class);
private CamelContext camelContext;
public DefaultComponent() {
}
public DefaultComponent(CamelContext context) {
this.camelContext = context;
}
@Deprecated
protected String preProcessUri(String uri) {
// Give components a chance to preprocess URIs and migrate to URI syntax that discourages invalid URIs
// (see CAMEL-4425)
// check URI string to the unsafe URI characters
String encodedUri = UnsafeUriCharactersEncoder.encode(uri);
if (!encodedUri.equals(uri)) {
// uri supplied is not really valid
// we just don't want to log the password setting here
LOG.warn("Supplied URI '{}' contains unsafe characters, please check encoding", URISupport.sanitizeUri(uri));
}
return encodedUri;
}
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 = URISupport.extractRemainderPath(u, useRawUri());
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=[{}]", new Object[]{URISupport.sanitizeUri(uri), URISupport.sanitizePath(path)});
}
Endpoint endpoint = createEndpoint(uri, path, parameters);
if (endpoint == null) {
return null;
}
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 ComponentConfiguration createComponentConfiguration() {
return new DefaultComponentConfiguration(this);
}
public EndpointConfiguration createConfiguration(String uri) throws Exception {
MappedEndpointConfiguration config = new MappedEndpointConfiguration(getCamelContext());
config.setURI(new URI(uri));
return config;
}
public boolean useRawUri() {
// should use encoded uri by default
return false;
}
/**
* 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 = IntrospectionSupport.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("&&")) {
Pattern pattern = Pattern.compile("RAW(.*&&.*)");
Matcher m = 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.");
}
}
public CamelContext getCamelContext() {
return camelContext;
}
public void setCamelContext(CamelContext context) {
this.camelContext = context;
}
protected void doStart() throws Exception {
ObjectHelper.notNull(getCamelContext(), "camelContext");
}
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 {
// set reference properties first as they use # syntax that fools the regular properties setter
EndpointHelper.setReferenceProperties(camelContext, bean, parameters);
EndpointHelper.setProperties(camelContext, bean, parameters);
}
/**
* Derived classes may wish to overload this to prevent the default introspection of URI parameters
* on the created 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) {
value = defaultValue;
}
if (value == null) {
return null;
}
return CamelContextHelper.convertTo(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;
}
}