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.spring.javaconfig;
018    
019    import java.util.List;
020    
021    import org.apache.camel.CamelContext;
022    import org.apache.camel.RoutesBuilder;
023    import org.apache.camel.builder.RouteBuilder;
024    import org.apache.camel.spring.CamelBeanPostProcessor;
025    import org.apache.camel.spring.SpringCamelContext;
026    import org.springframework.beans.factory.BeanFactory;
027    import org.springframework.beans.factory.BeanFactoryAware;
028    import org.springframework.beans.factory.FactoryBean;
029    import org.springframework.beans.factory.ListableBeanFactory;
030    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
031    import org.springframework.context.ApplicationContext;
032    import org.springframework.context.ApplicationContextAware;
033    import org.springframework.context.ApplicationEventPublisherAware;
034    import org.springframework.context.MessageSourceAware;
035    import org.springframework.context.ResourceLoaderAware;
036    import org.springframework.context.annotation.Bean;
037    import org.springframework.context.annotation.Configuration;
038    
039    
040    
041    /**
042     * A useful base class for writing
043     * <a href="http://www.springsource.org/javaconfig">Spring JavaConfig</a>
044     * configurations for working with Camel
045     *
046     * @version $Revision: 893852 $
047     */
048    @Configuration
049    public abstract class CamelConfiguration implements BeanFactoryAware, ApplicationContextAware {
050        
051        private BeanFactory beanFactory;
052    
053        private AutowireCapableBeanFactory autowireCapableBeanFactory;
054    
055        private ApplicationContext applicationContext;
056    
057        public void setBeanFactory(BeanFactory beanFactory) {
058            this.beanFactory = beanFactory;
059            if (beanFactory instanceof AutowireCapableBeanFactory) {
060                autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory;
061            }
062        }
063    
064        protected BeanFactory getBeanFactory() {
065            return this.beanFactory;
066        }
067    
068        public void setApplicationContext(ApplicationContext ac) {
069            this.applicationContext = ac;
070        }
071    
072        protected ApplicationContext getApplicationContext() {
073            return this.applicationContext;
074        }
075    
076        public Object getBean(String beanName) {
077            return beanFactory.getBean(beanName);
078        }
079    
080        public <T> T getBean(Class<T> type) {
081            return beanFactory.getBean(type);
082        }
083    
084        public <T> T getBean(String beanName, Class<T> type) {
085            return beanFactory.getBean(beanName, type);
086        }
087       
088    
089        /**
090         * Invoke callbacks on the object, as though it were configured in the factory. If appropriate,
091         * the object may be wrapped before being returned. For this reason, it is recommended to always
092         * respect the return value when using this method.
093         *
094         * @param   object  object to configure
095         *
096         * @return  either the original object or a wrapped one after callbacks called on it.
097         */
098        protected <T> T getConfigured(T object) {
099            if (this.autowireCapableBeanFactory == null) {
100                throw new UnsupportedOperationException(
101                    "Cannot configure object - not running in an AutowireCapableBeanFactory");
102            }
103    
104            @SuppressWarnings("unchecked") // See SPR-4955
105            T configuredObject = (T) autowireCapableBeanFactory.initializeBean(object, null);
106    
107            // this block copied from ApplicationContextAwareProcessor.  See SJC-149.
108            if (this.applicationContext != null) {
109                if (configuredObject instanceof ResourceLoaderAware) {
110                    ((ResourceLoaderAware) configuredObject).setResourceLoader(this.applicationContext);
111                }
112    
113                if (configuredObject instanceof ApplicationEventPublisherAware) {
114                    ((ApplicationEventPublisherAware) configuredObject).setApplicationEventPublisher(this.applicationContext);
115                }
116    
117                if (configuredObject instanceof MessageSourceAware) {
118                    ((MessageSourceAware) configuredObject).setMessageSource(this.applicationContext);
119                }
120    
121                if (configuredObject instanceof ApplicationContextAware) {
122                    ((ApplicationContextAware) configuredObject).setApplicationContext(this.applicationContext);
123                }
124            }
125    
126            return configuredObject;
127        }
128    
129        @Bean
130        public CamelBeanPostProcessor camelBeanPostProcessor() throws Exception {
131            CamelBeanPostProcessor answer = new CamelBeanPostProcessor();
132    
133            CamelContext camelContext = getBean(CamelContext.class);
134            // lets lookup a bean
135            answer.setCamelContext(camelContext);        
136            return answer;
137        }
138    
139        /**
140         * Returns the CamelContext
141         */
142        @Bean
143        public CamelContext camelContext() throws Exception {
144            CamelContext camelContext = createCamelContext();
145            setupCamelContext(camelContext);
146            List<RouteBuilder> routes = routes();
147            for (RoutesBuilder route : routes) {
148                camelContext.addRoutes(route);
149            }        
150            return camelContext;
151        }
152        
153        // Can register the camel component, language here
154        protected void setupCamelContext(CamelContext camelContext) throws Exception {
155            
156        }
157        
158        protected CamelContext createCamelContext() throws Exception {
159            return new SpringCamelContext(getApplicationContext());
160        }
161    
162        /**
163         * Returns the list of routes to use in this configuration
164         */
165        public abstract List<RouteBuilder> routes();
166    
167    }