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;
018    
019    import java.lang.reflect.Modifier;
020    import java.util.List;
021    import java.util.Map;
022    import java.util.Set;
023    
024    import org.apache.camel.builder.RouteBuilder;
025    import org.apache.camel.util.ResolverUtil;
026    import org.apache.commons.logging.Log;
027    import org.apache.commons.logging.LogFactory;
028    import org.springframework.context.ApplicationContext;
029    
030    /**
031     * A helper class which will find all {@link RouteBuilder} instances on the classpath
032     *
033     * @version $Revision: 35332 $
034     */
035    public class RouteBuilderFinder {
036        private static final transient Log LOG = LogFactory.getLog(RouteBuilderFinder.class);
037        private final SpringCamelContext camelContext;
038        private final String[] packages;
039        private ApplicationContext applicationContext;
040        private ResolverUtil resolver = new ResolverUtil();
041    
042        public RouteBuilderFinder(SpringCamelContext camelContext, String[] packages, ClassLoader classLoader) {
043            this.camelContext = camelContext;
044            this.applicationContext = camelContext.getApplicationContext();
045            this.packages = packages;
046    
047            // lets add all the available class loaders just in case of wierdness
048            // we could make this more strict once we've worked out all the gremlins
049            // in servicemix-camel
050            Set set = resolver.getClassLoaders();
051            set.clear();
052            set.add(classLoader);
053    /*
054            set.add(classLoader);
055            set.add(applicationContext.getClassLoader());
056            set.add(getClass().getClassLoader());
057    */
058        }
059    
060        public String[] getPackages() {
061            return packages;
062        }
063    
064        public ApplicationContext getApplicationContext() {
065            return applicationContext;
066        }
067    
068    
069        /**
070         * Appends all the {@link RouteBuilder} instances that can be found on the classpath
071         */
072        public void appendBuilders(List<RouteBuilder> list) throws IllegalAccessException, InstantiationException {
073            resolver.findImplementations(RouteBuilder.class, packages);
074            Set<Class> classes = resolver.getClasses();
075            for (Class aClass : classes) {
076                if (shouldIgnoreBean(aClass)) {
077                    continue;
078                }
079                if (isValidClass(aClass)) {
080                    RouteBuilder builder = instantiateBuilder(aClass);
081                    list.add(builder);
082                }
083            }
084        }
085    
086        public void destroy() throws Exception {
087        }
088    
089        /**
090         * Lets ignore beans that are not explicitly configured in the spring.xml
091         */
092        protected boolean shouldIgnoreBean(Class type) {
093            Map beans = applicationContext.getBeansOfType(type, true, true);
094            if (beans == null || beans.isEmpty()) {
095                return false;
096            }
097            // TODO apply some filter?
098            return true;
099        }
100    
101        /**
102         * Returns true if the object is non-abstract and supports a zero argument constructor
103         */
104        protected boolean isValidClass(Class type) {
105            if (!Modifier.isAbstract(type.getModifiers()) && !type.isInterface()) {
106                return true;
107            }
108            return false;
109        }
110    
111        protected RouteBuilder instantiateBuilder(Class type) throws IllegalAccessException, InstantiationException {
112            return (RouteBuilder) camelContext.getInjector().newInstance(type);
113        }
114    }