001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.impl;
018    
019    import java.lang.reflect.ParameterizedType;
020    import java.lang.reflect.Type;
021    import java.util.Map;
022    import java.util.concurrent.ExecutorService;
023    import java.util.concurrent.ScheduledExecutorService;
024    
025    import org.apache.camel.CamelContext;
026    import org.apache.camel.CamelContextAware;
027    import org.apache.camel.Component;
028    import org.apache.camel.Endpoint;
029    import org.apache.camel.Exchange;
030    import org.apache.camel.ExchangePattern;
031    import org.apache.camel.PollingConsumer;
032    import org.apache.camel.util.ObjectHelper;
033    import org.apache.camel.util.concurrent.ExecutorServiceHelper;
034    
035    /**
036     * A default endpoint useful for implementation inheritance
037     *
038     * @version $Revision: 835240 $
039     */
040    public abstract class DefaultEndpoint implements Endpoint, CamelContextAware {
041        private static final int DEFAULT_THREADPOOL_SIZE = 10;
042    
043        private String endpointUri;
044        private CamelContext camelContext;
045        private Component component;
046        private ExecutorService executorService;
047        private ExchangePattern exchangePattern = ExchangePattern.InOnly;
048    
049        protected DefaultEndpoint(String endpointUri, Component component) {
050            this(endpointUri, component.getCamelContext());
051            this.component = component;
052        }
053    
054        protected DefaultEndpoint(String endpointUri, CamelContext camelContext) {
055            this(endpointUri);
056            this.camelContext = camelContext;
057        }
058    
059        protected DefaultEndpoint(String endpointUri) {
060            this.setEndpointUri(endpointUri);
061        }
062    
063        protected DefaultEndpoint() {
064            super();
065        }
066    
067        public int hashCode() {
068            return getEndpointUri().hashCode() * 37 + 1;
069        }
070    
071        @Override
072        public boolean equals(Object object) {
073            if (object instanceof DefaultEndpoint) {
074                DefaultEndpoint that = (DefaultEndpoint) object;
075                return ObjectHelper.equal(this.getEndpointUri(), that.getEndpointUri());
076            }
077            return false;
078        }
079    
080        @Override
081        public String toString() {
082            return "Endpoint[" + getEndpointUri() + "]";
083        }
084    
085        public String getEndpointUri() {
086            if (endpointUri == null) {
087                endpointUri = createEndpointUri();
088                if (endpointUri == null) {
089                    throw new IllegalArgumentException("endpointUri is not specified and " + getClass().getName()
090                            + " does not implement createEndpointUri() to create a default value");
091                }
092            }
093            return endpointUri;
094        }
095    
096        public String getEndpointKey() {
097            if (isLenientProperties()) {
098                // only use the endpoint uri without parameters as the properties is lenient
099                String uri = getEndpointUri();
100                if (uri.indexOf('?') != -1) {
101                    return ObjectHelper.before(uri, "?");
102                } else {
103                    return uri;
104                }
105            } else {
106                // use the full endpoint uri
107                return getEndpointUri();
108            }
109        }
110    
111        public CamelContext getCamelContext() {
112            return camelContext;
113        }
114    
115        public Component getComponent() {
116            return component;
117        }
118    
119        public void setCamelContext(CamelContext camelContext) {
120            this.camelContext = camelContext;
121        }
122    
123        public synchronized ExecutorService getExecutorService() {
124            if (executorService == null) {
125                Component c = getComponent();
126                if (c instanceof DefaultComponent) {
127                    DefaultComponent dc = (DefaultComponent) c;
128                    executorService = dc.getExecutorService();
129                }
130                if (executorService == null) {
131                    executorService = createScheduledExecutorService();
132                }
133            }
134            return executorService;
135        }
136        
137        public synchronized ScheduledExecutorService getScheduledExecutorService() {
138            ExecutorService executor = getExecutorService();
139            if (executor instanceof ScheduledExecutorService) {
140                return (ScheduledExecutorService) executor;
141            } else {
142                return createScheduledExecutorService();
143            }
144        }
145    
146        public synchronized void setExecutorService(ExecutorService executorService) {
147            this.executorService = executorService;
148        }
149    
150        public PollingConsumer createPollingConsumer() throws Exception {
151            return new EventDrivenPollingConsumer(this);
152        }
153    
154        public Exchange createExchange(Exchange exchange) {
155            Class<Exchange> exchangeType = getExchangeType();
156            if (exchangeType != null) {
157                if (exchangeType.isInstance(exchange)) {
158                    return exchangeType.cast(exchange);
159                }
160            }
161            return exchange.copy();
162        }
163    
164        /**
165         * Returns the type of the exchange which is generated by this component
166         */
167        @SuppressWarnings("unchecked")
168        public Class<Exchange> getExchangeType() {
169            Type type = getClass().getGenericSuperclass();
170            if (type instanceof ParameterizedType) {
171                ParameterizedType parameterizedType = (ParameterizedType) type;
172                Type[] arguments = parameterizedType.getActualTypeArguments();
173                if (arguments.length > 0) {
174                    Type argumentType = arguments[0];
175                    if (argumentType instanceof Class) {
176                        return (Class<Exchange>) argumentType;
177                    }
178                }
179            }
180            return null;
181        }
182    
183        public Exchange createExchange() {
184            return createExchange(getExchangePattern());
185        }
186    
187        public Exchange createExchange(ExchangePattern pattern) {
188            return new DefaultExchange(this, pattern);
189        }
190    
191        public ExchangePattern getExchangePattern() {
192            return exchangePattern;
193        }
194    
195        public void setExchangePattern(ExchangePattern exchangePattern) {
196            this.exchangePattern = exchangePattern;
197        }
198    
199        protected ScheduledExecutorService createScheduledExecutorService() {
200            return ExecutorServiceHelper.newScheduledThreadPool(DEFAULT_THREADPOOL_SIZE, getEndpointUri(), true);
201        }
202    
203        public void configureProperties(Map<String, Object> options) {
204            // do nothing by default
205        }
206    
207        /**
208         * A factory method to lazily create the endpointUri if none is specified 
209         */
210        protected String createEndpointUri() {
211            return null;
212        }
213    
214        /**
215         * Sets the endpointUri if it has not been specified yet via some kind of dependency injection mechanism.
216         * This allows dependency injection frameworks such as Spring or Guice to set the default endpoint URI in cases
217         * where it has not been explicitly configured using the name/context in which an Endpoint is created.
218         */
219        public void setEndpointUriIfNotSpecified(String value) {
220            if (endpointUri == null) {
221                setEndpointUri(value);
222            }
223        }
224        protected void setEndpointUri(String endpointUri) {
225            this.endpointUri = endpointUri;
226        }
227    
228        public boolean isLenientProperties() {
229            // default should be false for most components
230            return false;
231        }
232    
233    }