| /** |
| * 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.util.HashMap; |
| import java.util.Map; |
| |
| import org.apache.camel.CamelContext; |
| import org.apache.camel.CamelContextAware; |
| import org.apache.camel.Component; |
| import org.apache.camel.Consumer; |
| import org.apache.camel.Endpoint; |
| import org.apache.camel.EndpointConfiguration; |
| import org.apache.camel.Exchange; |
| import org.apache.camel.ExchangePattern; |
| import org.apache.camel.PollingConsumer; |
| import org.apache.camel.ResolveEndpointFailedException; |
| import org.apache.camel.spi.HasId; |
| import org.apache.camel.support.ServiceSupport; |
| import org.apache.camel.util.EndpointHelper; |
| import org.apache.camel.util.IntrospectionSupport; |
| import org.apache.camel.util.ObjectHelper; |
| import org.apache.camel.util.URISupport; |
| |
| /** |
| * A default endpoint useful for implementation inheritance. |
| * <p/> |
| * Components which leverages <a |
| * href="http://camel.apache.org/asynchronous-routing-engine.html">asynchronous |
| * processing model</a> should check the {@link #isSynchronous()} to determine |
| * if asynchronous processing is allowed. The <tt>synchronous</tt> option on the |
| * endpoint allows Camel end users to dictate whether they want the asynchronous |
| * model or not. The option is default <tt>false</tt> which means asynchronous |
| * processing is allowed. |
| * |
| * @version |
| */ |
| public abstract class DefaultEndpoint extends ServiceSupport implements Endpoint, HasId, CamelContextAware { |
| |
| private String endpointUri; |
| private EndpointConfiguration endpointConfiguration; |
| private CamelContext camelContext; |
| private Component component; |
| private ExchangePattern exchangePattern = ExchangePattern.InOnly; |
| // option to allow end user to dictate whether async processing should be |
| // used or not (if possible) |
| private boolean synchronous; |
| private final String id = EndpointHelper.createEndpointId(); |
| private Map<String, Object> consumerProperties; |
| |
| /** |
| * Constructs a fully-initialized DefaultEndpoint instance. This is the |
| * preferred method of constructing an object from Java code (as opposed to |
| * Spring beans, etc.). |
| * |
| * @param endpointUri the full URI used to create this endpoint |
| * @param component the component that created this endpoint |
| */ |
| protected DefaultEndpoint(String endpointUri, Component component) { |
| this.camelContext = component == null ? null : component.getCamelContext(); |
| this.component = component; |
| this.setEndpointUri(endpointUri); |
| } |
| |
| /** |
| * Constructs a DefaultEndpoint instance which has <b>not</b> been created |
| * using a {@link Component}. |
| * <p/> |
| * <b>Note:</b> It is preferred to create endpoints using the associated |
| * component. |
| * |
| * @param endpointUri the full URI used to create this endpoint |
| * @param camelContext the Camel Context in which this endpoint is operating |
| */ |
| @Deprecated |
| protected DefaultEndpoint(String endpointUri, CamelContext camelContext) { |
| this(endpointUri); |
| this.camelContext = camelContext; |
| } |
| |
| /** |
| * Constructs a partially-initialized DefaultEndpoint instance. |
| * <p/> |
| * <b>Note:</b> It is preferred to create endpoints using the associated |
| * component. |
| * |
| * @param endpointUri the full URI used to create this endpoint |
| */ |
| @Deprecated |
| protected DefaultEndpoint(String endpointUri) { |
| this.setEndpointUri(endpointUri); |
| } |
| |
| /** |
| * Constructs a partially-initialized DefaultEndpoint instance. Useful when |
| * creating endpoints manually (e.g., as beans in Spring). |
| * <p/> |
| * Please note that the endpoint URI must be set through properties (or |
| * overriding {@link #createEndpointUri()} if one uses this constructor. |
| * <p/> |
| * <b>Note:</b> It is preferred to create endpoints using the associated |
| * component. |
| */ |
| protected DefaultEndpoint() { |
| } |
| |
| public int hashCode() { |
| return getEndpointUri().hashCode() * 37 + 1; |
| } |
| |
| @Override |
| public boolean equals(Object object) { |
| if (object instanceof DefaultEndpoint) { |
| DefaultEndpoint that = (DefaultEndpoint)object; |
| return ObjectHelper.equal(this.getEndpointUri(), that.getEndpointUri()); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("Endpoint[%s]", URISupport.sanitizeUri(getEndpointUri())); |
| } |
| |
| /** |
| * Returns a unique String ID which can be used for aliasing without having |
| * to use the whole URI which is not unique |
| */ |
| public String getId() { |
| return id; |
| } |
| |
| public String getEndpointUri() { |
| if (endpointUri == null) { |
| endpointUri = createEndpointUri(); |
| if (endpointUri == null) { |
| throw new IllegalArgumentException("endpointUri is not specified and " + getClass().getName() |
| + " does not implement createEndpointUri() to create a default value"); |
| } |
| } |
| return endpointUri; |
| } |
| |
| public EndpointConfiguration getEndpointConfiguration() { |
| if (endpointConfiguration == null) { |
| endpointConfiguration = createEndpointConfiguration(getEndpointUri()); |
| } |
| return endpointConfiguration; |
| } |
| |
| /** |
| * Sets a custom {@link EndpointConfiguration} |
| * |
| * @param endpointConfiguration a custom endpoint configuration to be used. |
| */ |
| public void setEndpointConfiguration(EndpointConfiguration endpointConfiguration) { |
| this.endpointConfiguration = endpointConfiguration; |
| } |
| |
| public String getEndpointKey() { |
| if (isLenientProperties()) { |
| // only use the endpoint uri without parameters as the properties is |
| // lenient |
| String uri = getEndpointUri(); |
| if (uri.indexOf('?') != -1) { |
| return ObjectHelper.before(uri, "?"); |
| } else { |
| return uri; |
| } |
| } else { |
| // use the full endpoint uri |
| return getEndpointUri(); |
| } |
| } |
| |
| public CamelContext getCamelContext() { |
| return camelContext; |
| } |
| |
| /** |
| * Returns the component that created this endpoint. |
| * |
| * @return the component that created this endpoint, or <tt>null</tt> if |
| * none set |
| */ |
| public Component getComponent() { |
| return component; |
| } |
| |
| public void setCamelContext(CamelContext camelContext) { |
| this.camelContext = camelContext; |
| } |
| |
| public PollingConsumer createPollingConsumer() throws Exception { |
| return new EventDrivenPollingConsumer(this); |
| } |
| |
| public Exchange createExchange(Exchange exchange) { |
| return exchange.copy(); |
| } |
| |
| public Exchange createExchange() { |
| return createExchange(getExchangePattern()); |
| } |
| |
| public Exchange createExchange(ExchangePattern pattern) { |
| return new DefaultExchange(this, pattern); |
| } |
| |
| /** |
| * Returns the default exchange pattern to use for createExchange(). |
| * |
| * @see #setExchangePattern(ExchangePattern exchangePattern) |
| */ |
| public ExchangePattern getExchangePattern() { |
| return exchangePattern; |
| } |
| |
| /** |
| * Sets the default exchange pattern to use for {@link #createExchange()}. |
| * The default value is {@link ExchangePattern#InOnly} |
| */ |
| public void setExchangePattern(ExchangePattern exchangePattern) { |
| this.exchangePattern = exchangePattern; |
| } |
| |
| /** |
| * Returns whether synchronous processing should be strictly used. |
| * |
| * @see #setSynchronous(boolean synchronous) |
| */ |
| public boolean isSynchronous() { |
| return synchronous; |
| } |
| |
| /** |
| * Sets whether synchronous processing should be strictly used, or Camel is |
| * allowed to use asynchronous processing (if supported). |
| * |
| * @param synchronous <tt>true</tt> to enforce synchronous processing |
| */ |
| public void setSynchronous(boolean synchronous) { |
| this.synchronous = synchronous; |
| } |
| |
| public void configureProperties(Map<String, Object> options) { |
| Map<String, Object> consumerProperties = IntrospectionSupport.extractProperties(options, "consumer."); |
| if (consumerProperties != null) { |
| setConsumerProperties(consumerProperties); |
| } |
| } |
| |
| /** |
| * A factory method to lazily create the endpointUri if none is specified |
| */ |
| protected String createEndpointUri() { |
| return null; |
| } |
| |
| /** |
| * A factory method to lazily create the endpoint configuration if none is specified |
| */ |
| protected EndpointConfiguration createEndpointConfiguration(String uri) { |
| // using this factory method to be backwards compatible with the old code |
| if (getComponent() != null) { |
| // prefer to use component endpoint configuration |
| try { |
| return getComponent().createConfiguration(uri); |
| } catch (Exception e) { |
| throw ObjectHelper.wrapRuntimeCamelException(e); |
| } |
| } else if (getCamelContext() != null) { |
| // fallback and use a mapped endpoint configuration |
| return new MappedEndpointConfiguration(getCamelContext(), uri); |
| } |
| // not configuration possible |
| return null; |
| } |
| |
| /** |
| * Sets the endpointUri if it has not been specified yet via some kind of |
| * dependency injection mechanism. This allows dependency injection |
| * frameworks such as Spring or Guice to set the default endpoint URI in |
| * cases where it has not been explicitly configured using the name/context |
| * in which an Endpoint is created. |
| */ |
| public void setEndpointUriIfNotSpecified(String value) { |
| if (endpointUri == null) { |
| setEndpointUri(value); |
| } |
| } |
| |
| /** |
| * Sets the URI that created this endpoint. |
| */ |
| protected void setEndpointUri(String endpointUri) { |
| this.endpointUri = endpointUri; |
| } |
| |
| public boolean isLenientProperties() { |
| // default should be false for most components |
| return false; |
| } |
| |
| public Map<String, Object> getConsumerProperties() { |
| return consumerProperties; |
| } |
| |
| public void setConsumerProperties(Map<String, Object> consumerProperties) { |
| this.consumerProperties = consumerProperties; |
| } |
| |
| protected void configureConsumer(Consumer consumer) throws Exception { |
| if (consumerProperties != null) { |
| // use a defensive copy of the consumer properties as the methods below will remove the used properties |
| // and in case we restart routes, we need access to the original consumer properties again |
| Map<String, Object> copy = new HashMap<String, Object>(consumerProperties); |
| |
| // set reference properties first as they use # syntax that fools the regular properties setter |
| EndpointHelper.setReferenceProperties(getCamelContext(), consumer, copy); |
| EndpointHelper.setProperties(getCamelContext(), consumer, copy); |
| |
| // special consumer.bridgeErrorHandler option |
| Object bridge = copy.remove("bridgeErrorHandler"); |
| if (bridge != null && "true".equals(bridge)) { |
| if (consumer instanceof DefaultConsumer) { |
| DefaultConsumer defaultConsumer = (DefaultConsumer) consumer; |
| defaultConsumer.setExceptionHandler(new BridgeExceptionHandlerToErrorHandler(defaultConsumer)); |
| } else { |
| throw new IllegalArgumentException("Option consumer.bridgeErrorHandler is only supported by endpoints," |
| + " having their consumer extend DefaultConsumer. The consumer is a " + consumer.getClass().getName() + " class."); |
| } |
| } |
| |
| if (!this.isLenientProperties() && copy.size() > 0) { |
| throw new ResolveEndpointFailedException(this.getEndpointUri(), "There are " + copy.size() |
| + " parameters that couldn't be set on the endpoint consumer." |
| + " Check the uri if the parameters are spelt correctly and that they are properties of the endpoint." |
| + " Unknown consumer parameters=[" + copy + "]"); |
| } |
| } |
| } |
| |
| @Override |
| protected void doStart() throws Exception { |
| // noop |
| } |
| |
| @Override |
| protected void doStop() throws Exception { |
| // noop |
| } |
| } |