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.Method;
020    
021    import javax.xml.bind.annotation.XmlTransient;
022    
023    import org.apache.camel.CamelContext;
024    import org.apache.camel.CamelContextAware;
025    import org.apache.camel.Consume;
026    import org.apache.camel.Consumer;
027    import org.apache.camel.ConsumerTemplate;
028    import org.apache.camel.Endpoint;
029    import org.apache.camel.PollingConsumer;
030    import org.apache.camel.Processor;
031    import org.apache.camel.Producer;
032    import org.apache.camel.ProducerTemplate;
033    import org.apache.camel.Service;
034    import org.apache.camel.component.bean.BeanProcessor;
035    import org.apache.camel.component.bean.ProxyHelper;
036    import org.apache.camel.util.CamelContextHelper;
037    import org.apache.camel.util.ObjectHelper;
038    import org.apache.commons.logging.Log;
039    import org.apache.commons.logging.LogFactory;
040    
041    /**
042     * A helper class for Camel based injector or post processing hooks which can be reused by
043     * both the <a href="http://camel.apache.org/spring.html">Spring</a>
044     * and <a href="http://camel.apache.org/guice.html">Guice</a> support.
045     *
046     * @version $Revision: 835732 $
047     */
048    public class CamelPostProcessorHelper implements CamelContextAware {
049        private static final transient Log LOG = LogFactory.getLog(CamelPostProcessorHelper.class);
050    
051        @XmlTransient
052        private CamelContext camelContext;
053    
054        public CamelPostProcessorHelper() {
055        }
056    
057        public CamelPostProcessorHelper(CamelContext camelContext) {
058            this.setCamelContext(camelContext);
059        }
060    
061        public CamelContext getCamelContext() {
062            return camelContext;
063        }
064    
065        public void setCamelContext(CamelContext camelContext) {
066            this.camelContext = camelContext;
067        }
068    
069        /**
070         * Does the given context match this camel context
071         */
072        public boolean matchContext(String context) {
073            if (ObjectHelper.isNotEmpty(context)) {
074                if (!camelContext.getName().equals(context)) {
075                    return false;
076                }
077            }
078            return true;
079        }
080    
081        public void consumerInjection(Method method, Object bean) {
082            Consume consume = method.getAnnotation(Consume.class);
083            if (consume != null && matchContext(consume.context())) {
084                LOG.info("Creating a consumer for: " + consume);
085                subscribeMethod(method, bean, consume.uri(), consume.ref());
086            }
087        }
088    
089        public void subscribeMethod(Method method, Object bean, String endpointUri, String endpointName) {
090            // lets bind this method to a listener
091            String injectionPointName = method.getName();
092            Endpoint endpoint = getEndpointInjection(endpointUri, endpointName, injectionPointName, true);
093            if (endpoint != null) {
094                try {
095                    Processor processor = createConsumerProcessor(bean, method, endpoint);
096                    Consumer consumer = endpoint.createConsumer(processor);
097                    if (LOG.isDebugEnabled()) {
098                        LOG.debug("Created processor: " + processor + " for consumer: " + consumer);
099                    }
100                    startService(consumer);
101                } catch (Exception e) {
102                    throw ObjectHelper.wrapRuntimeCamelException(e);
103                }
104            }
105        }
106    
107        /**
108         * Stats the given service
109         */
110        protected void startService(Service service) throws Exception {
111            getCamelContext().addService(service);
112        }
113    
114        /**
115         * Create a processor which invokes the given method when an incoming
116         * message exchange is received
117         */
118        protected Processor createConsumerProcessor(final Object pojo, final Method method, final Endpoint endpoint) {
119            BeanProcessor answer = new BeanProcessor(pojo, getCamelContext());
120            answer.setMethodObject(method);
121            return answer;
122        }
123    
124        protected Endpoint getEndpointInjection(String uri, String name, String injectionPointName, boolean mandatory) {
125            return CamelContextHelper.getEndpointInjection(getCamelContext(), uri, name, injectionPointName, mandatory);
126        }
127    
128        /**
129         * Creates the object to be injected for an {@link org.apache.camel.EndpointInject} or {@link org.apache.camel.Produce} injection point
130         */
131        @SuppressWarnings("unchecked")
132        public Object getInjectionValue(Class<?> type, String endpointUri, String endpointRef, String injectionPointName) {
133            if (type.isAssignableFrom(ProducerTemplate.class)) {
134                return createInjectionProducerTemplate(endpointUri, endpointRef, injectionPointName);
135            } else if (type.isAssignableFrom(ConsumerTemplate.class)) {
136                return createInjectionConsumerTemplate(endpointUri, endpointRef, injectionPointName);
137            } else {
138                Endpoint endpoint = getEndpointInjection(endpointUri, endpointRef, injectionPointName, true);
139                if (endpoint != null) {
140                    if (type.isInstance(endpoint)) {
141                        return endpoint;
142                    } else if (type.isAssignableFrom(Producer.class)) {
143                        return createInjectionProducer(endpoint);
144                    } else if (type.isAssignableFrom(PollingConsumer.class)) {
145                        return createInjectionPollingConsumer(endpoint);
146                    } else if (type.isInterface()) {
147                        // lets create a proxy
148                        try {
149                            return ProxyHelper.createProxy(endpoint, type);
150                        } catch (Exception e) {
151                            throw createProxyInstantiationRuntimeException(type, endpoint, e);
152                        }
153                    } else {
154                        throw new IllegalArgumentException("Invalid type: " + type.getName()
155                                + " which cannot be injected via @EndpointInject/@Produce for: " + endpoint);
156                    }
157                }
158                return null;
159            }
160        }
161    
162        /**
163         * Factory method to create a {@link org.apache.camel.ProducerTemplate} to be injected into a POJO
164         */
165        protected ProducerTemplate createInjectionProducerTemplate(String endpointUri, String endpointRef, String injectionPointName) {
166            // endpoint is optional for this injection point
167            Endpoint endpoint = getEndpointInjection(endpointUri, endpointRef, injectionPointName, false);
168            return new DefaultProducerTemplate(getCamelContext(), endpoint);
169        }
170    
171        /**
172         * Factory method to create a {@link org.apache.camel.ConsumerTemplate} to be injected into a POJO
173         */
174        protected ConsumerTemplate createInjectionConsumerTemplate(String endpointUri, String endpointRef, String injectionPointName) {
175            return new DefaultConsumerTemplate(getCamelContext());
176        }
177    
178        /**
179         * Factory method to create a started {@link org.apache.camel.PollingConsumer} to be injected into a POJO
180         */
181        protected PollingConsumer createInjectionPollingConsumer(Endpoint endpoint) {
182            try {
183                PollingConsumer pollingConsumer = endpoint.createPollingConsumer();
184                startService(pollingConsumer);
185                return pollingConsumer;
186            } catch (Exception e) {
187                throw ObjectHelper.wrapRuntimeCamelException(e);
188            }
189        }
190    
191        /**
192         * A Factory method to create a started {@link org.apache.camel.Producer} to be injected into a POJO
193         */
194        protected Producer createInjectionProducer(Endpoint endpoint) {
195            try {
196                Producer producer = endpoint.createProducer();
197                startService(producer);
198                return producer;
199            } catch (Exception e) {
200                throw ObjectHelper.wrapRuntimeCamelException(e);
201            }
202        }
203    
204        protected RuntimeException createProxyInstantiationRuntimeException(Class<?> type, Endpoint endpoint, Exception e) {
205            return new ProxyInstantiationException(type, endpoint, e);
206        }
207    }