activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jstrac...@apache.org
Subject svn commit: r521369 - in /activemq/camel/trunk: camel-core/src/main/java/org/apache/camel/util/ camel-spring/ camel-spring/src/main/java/org/apache/camel/spring/ camel-spring/src/test/java/org/apache/camel/spring/ camel-spring/src/test/java/org/apache/...
Date Thu, 22 Mar 2007 17:45:30 GMT
Author: jstrachan
Date: Thu Mar 22 10:45:29 2007
New Revision: 521369

URL: http://svn.apache.org/viewvc?view=rev&rev=521369
Log:
added a Spring FactoryBean for creating and configuring a CamelContext along with auto-starting
it and also being able to search the classpath for routes to be installed

Added:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
  (with props)
    activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
  (with props)
    activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
  (with props)
    activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
  (with props)
    activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/
    activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/
    activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
  (with props)
    activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
  (with props)
Modified:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
    activemq/camel/trunk/camel-spring/pom.xml

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java?view=diff&rev=521369&r1=521368&r2=521369
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
(original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
Thu Mar 22 10:45:29 2007
@@ -136,4 +136,10 @@
         }
         return value != null;
     }
+
+
+
+    public static boolean isNotNullOrBlank(String text) {
+        return text != null && text.trim().length() > 0;
+    }
 }

Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
(added)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,328 @@
+/**
+ *
+ * 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.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileInputStream;
+
+/**
+ * <p>ResolverUtil is used to locate classes that are available in the/a class path
and meet
+ * arbitrary conditions. The two most common conditions are that a class implements/extends
+ * another class, or that is it annotated with a specific annotation. However, through the
use
+ * of the {@link Test} class it is possible to search using arbitrary conditions.</p>
+ *
+ * <p>A ClassLoader is used to locate all locations (directories and jar files) in
the class
+ * path that contain classes within certain packages, and then to load those classes and
+ * check them. By default the ClassLoader returned by
+ *  {@code Thread.currentThread().getContextClassLoader()} is used, but this can be overridden
+ * by calling {@link #setClassLoader(ClassLoader)} prior to invoking any of the {@code find()}
+ * methods.</p>
+ *
+ * <p>General searches are initiated by calling the
+ * {@link #find(ResolverUtil.Test, String)} ()} method and supplying
+ * a package name and a Test instance. This will cause the named package <b>and all
sub-packages</b>
+ * to be scanned for classes that meet the test. There are also utility methods for the common
+ * use cases of scanning multiple packages for extensions of particular classes, or classes
+ * annotated with a specific annotation.</p>
+ *
+ * <p>The standard usage pattern for the ResolverUtil class is as follows:</p>
+ *
+ *<pre>
+ *ResolverUtil&lt;ActionBean&gt; resolver = new ResolverUtil&lt;ActionBean&gt;();
+ *resolver.findImplementation(ActionBean.class, pkg1, pkg2);
+ *resolver.find(new CustomTest(), pkg1);
+ *resolver.find(new CustomTest(), pkg2);
+ *Collection&lt;ActionBean&gt; beans = resolver.getClasses();
+ *</pre>
+ *
+ * @author Tim Fennell
+ */
+public class ResolverUtil<T> {
+    private static final transient Log log = LogFactory.getLog(ResolverUtil.class);
+
+    /**
+     * A simple interface that specifies how to test classes to determine if they
+     * are to be included in the results produced by the ResolverUtil.
+     */
+    public static interface Test {
+        /**
+         * Will be called repeatedly with candidate classes. Must return True if a class
+         * is to be included in the results, false otherwise.
+         */
+        boolean matches(Class type);
+    }
+
+    /**
+     * A Test that checks to see if each class is assignable to the provided class. Note
+     * that this test will match the parent type itself if it is presented for matching.
+     */
+    public static class IsA implements Test {
+        private Class parent;
+
+        /** Constructs an IsA test using the supplied Class as the parent class/interface.
*/
+        public IsA(Class parentType) { this.parent = parentType; }
+
+        /** Returns true if type is assignable to the parent type supplied in the constructor.
*/
+        public boolean matches(Class type) {
+            return type != null && parent.isAssignableFrom(type);
+        }
+
+        @Override public String toString() {
+            return "is assignable to " + parent.getSimpleName();
+        }
+    }
+
+    /**
+     * A Test that checks to see if each class is annotated with a specific annotation. If
it
+     * is, then the test returns true, otherwise false.
+     */
+    public static class AnnotatedWith implements Test {
+        private Class<? extends Annotation> annotation;
+
+        /** Construts an AnnotatedWith test for the specified annotation type. */
+        public AnnotatedWith(Class<? extends Annotation> annotation) { this.annotation
= annotation; }
+
+        /** Returns true if the type is annotated with the class provided to the constructor.
*/
+        public boolean matches(Class type) {
+            return type != null && type.isAnnotationPresent(annotation);
+        }
+
+        @Override public String toString() {
+            return "annotated with @" + annotation.getSimpleName();
+        }
+    }
+
+    /** The set of matches being accumulated. */
+    private Set<Class<? extends T>> matches = new HashSet<Class<?extends
T>>();
+
+    /**
+     * The ClassLoader to use when looking for classes. If null then the ClassLoader returned
+     * by Thread.currentThread().getContextClassLoader() will be used.
+     */
+    private ClassLoader classloader;
+
+    /**
+     * Provides access to the classes discovered so far. If no calls have been made to
+     * any of the {@code find()} methods, this set will be empty.
+     *
+     * @return the set of classes that have been discovered.
+     */
+    public Set<Class<? extends T>> getClasses() {
+        return matches;
+    }
+
+    /**
+     * Returns the classloader that will be used for scanning for classes. If no explicit
+     * ClassLoader has been set by the calling, the context class loader will be used.
+     *
+     * @return the ClassLoader that will be used to scan for classes
+     */
+    public ClassLoader getClassLoader() {
+        return classloader == null ? Thread.currentThread().getContextClassLoader() : classloader;
+    }
+
+    /**
+     * Sets an explicit ClassLoader that should be used when scanning for classes. If none
+     * is set then the context classloader will be used.
+     *
+     * @param classloader a ClassLoader to use when scanning for classes
+     */
+    public void setClassLoader(ClassLoader classloader) { this.classloader = classloader;
}
+
+    /**
+     * Attempts to discover classes that are assignable to the type provided. In the case
+     * that an interface is provided this method will collect implementations. In the case
+     * of a non-interface class, subclasses will be collected.  Accumulated classes can be
+     * accessed by calling {@link #getClasses()}.
+     *
+     * @param parent the class of interface to find subclasses or implementations of
+     * @param packageNames one or more package names to scan (including subpackages) for
classes
+     */
+    public void findImplementations(Class parent, String... packageNames) {
+        if (packageNames == null) return;
+
+        Test test = new IsA(parent);
+        for (String pkg : packageNames) {
+            find(test, pkg);
+        }
+    }
+
+    /**
+     * Attempts to discover classes that are annotated with to the annotation. Accumulated
+     * classes can be accessed by calling {@link #getClasses()}.
+     *
+     * @param annotation the annotation that should be present on matching classes
+     * @param packageNames one or more package names to scan (including subpackages) for
classes
+     */
+    public void findAnnotated(Class<? extends Annotation> annotation, String... packageNames)
{
+        if (packageNames == null) return;
+
+        Test test = new AnnotatedWith(annotation);
+        for (String pkg : packageNames) {
+            find(test, pkg);
+        }
+    }
+
+    /**
+     * Scans for classes starting at the package provided and descending into subpackages.
+     * Each class is offered up to the Test as it is discovered, and if the Test returns
+     * true the class is retained.  Accumulated classes can be fetched by calling
+     * {@link #getClasses()}.
+     *
+     * @param test an instance of {@link Test} that will be used to filter classes
+     * @param packageName the name of the package from which to start scanning for
+     *        classes, e.g. {@code net.sourceforge.stripes}
+     */
+    public void find(Test test, String packageName) {
+        packageName = packageName.replace('.', '/');
+        ClassLoader loader = getClassLoader();
+        Enumeration<URL> urls;
+
+        try {
+            urls = loader.getResources(packageName);
+        }
+        catch (IOException ioe) {
+            ResolverUtil.log.warn("Could not read package: " + packageName, ioe);
+            return;
+        }
+
+        while (urls.hasMoreElements()) {
+            try {
+                String urlPath = urls.nextElement().getFile();
+                urlPath = URLDecoder.decode(urlPath, "UTF-8");
+
+                // If it's a file in a directory, trim the stupid file: spec
+                if ( urlPath.startsWith("file:") ) {
+                    urlPath = urlPath.substring(5);
+                }
+
+                // Else it's in a JAR, grab the path to the jar
+                if (urlPath.indexOf('!') > 0) {
+                    urlPath = urlPath.substring(0, urlPath.indexOf('!'));
+                }
+
+                ResolverUtil.log.info("Scanning for classes in [" + urlPath + "] matching
criteria: " + test);
+                File file = new File(urlPath);
+                if ( file.isDirectory() ) {
+                    loadImplementationsInDirectory(test, packageName, file);
+                }
+                else {
+                    loadImplementationsInJar(test, packageName, file);
+                }
+            }
+            catch (IOException ioe) {
+                ResolverUtil.log.warn("could not read entries", ioe);
+            }
+        }
+    }
+
+
+    /**
+     * Finds matches in a physical directory on a filesystem.  Examines all
+     * files within a directory - if the File object is not a directory, and ends with <i>.class</i>
+     * the file is loaded and tested to see if it is acceptable according to the Test.  Operates
+     * recursively to find classes within a folder structure matching the package structure.
+     *
+     * @param test a Test used to filter the classes that are discovered
+     * @param parent the package name up to this directory in the package hierarchy.  E.g.
if
+     *        /classes is in the classpath and we wish to examine files in /classes/org/apache
then
+     *        the values of <i>parent</i> would be <i>org/apache</i>
+     * @param location a File object representing a directory
+     */
+    private void loadImplementationsInDirectory(Test test, String parent, File location)
{
+        File[] files = location.listFiles();
+        StringBuilder builder = null;
+
+        for (File file : files) {
+            builder = new StringBuilder(100);
+            builder.append(parent).append("/").append(file.getName());
+            String packageOrClass = ( parent == null ? file.getName() : builder.toString()
);
+
+            if (file.isDirectory()) {
+                loadImplementationsInDirectory(test, packageOrClass, file);
+            }
+            else if (file.getName().endsWith(".class")) {
+                addIfMatching(test, packageOrClass);
+            }
+        }
+    }
+
+    /**
+     * Finds matching classes within a jar files that contains a folder structure
+     * matching the package structure.  If the File is not a JarFile or does not exist a
warning
+     * will be logged, but no error will be raised.
+     *
+     * @param test a Test used to filter the classes that are discovered
+     * @param parent the parent package under which classes must be in order to be considered
+     * @param jarfile the jar file to be examined for classes
+     */
+    private void loadImplementationsInJar(Test test, String parent, File jarfile) {
+
+        try {
+            JarEntry entry;
+            JarInputStream jarStream = new JarInputStream(new FileInputStream(jarfile));
+
+            while ( (entry = jarStream.getNextJarEntry() ) != null) {
+                String name = entry.getName();
+                if (!entry.isDirectory() && name.startsWith(parent) && name.endsWith(".class"))
{
+                    addIfMatching(test, name);
+                }
+            }
+        }
+        catch (IOException ioe) {
+            ResolverUtil.log.error("Could not search jar file '" + jarfile + "' for classes
matching criteria: " +
+                      test + "due to an IOException: " + ioe.getMessage());
+        }
+    }
+
+    /**
+     * Add the class designated by the fully qualified class name provided to the set of
+     * resolved classes if and only if it is approved by the Test supplied.
+     *
+     * @param test the test used to determine if the class matches
+     * @param fqn the fully qualified name of a class
+     */
+    protected void addIfMatching(Test test, String fqn) {
+        try {
+            String externalName = fqn.substring(0, fqn.indexOf('.')).replace('/', '.');
+            ClassLoader loader = getClassLoader();
+            ResolverUtil.log.trace("Checking to see if class " + externalName + " matches
criteria [" + test+ "]");
+
+            Class type = loader.loadClass(externalName);
+            if (test.matches(type) ) {
+                matches.add( (Class<T>) type);
+            }
+        }
+        catch (Throwable t) {
+            ResolverUtil.log.warn("Could not examine class '"+ fqn + "' due to a " +
+                     t.getClass().getName()+ " with message: " + t.getMessage());
+        }
+    }
+}

Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ResolverUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: activemq/camel/trunk/camel-spring/pom.xml
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/pom.xml?view=diff&rev=521369&r1=521368&r2=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/pom.xml (original)
+++ activemq/camel/trunk/camel-spring/pom.xml Thu Mar 22 10:45:29 2007
@@ -49,11 +49,13 @@
       <scope>test</scope>
     </dependency>
 
+    <!--
     <dependency>
       <groupId>org.apache.xbean</groupId>
       <artifactId>xbean-spring</artifactId>
       <version>2.8</version>
     </dependency>
+    -->
     
     <dependency>
       <groupId>org.springframework</groupId>

Added: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
(added)
+++ activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,137 @@
+/**
+ *
+ * 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.spring;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A Spring {@link FactoryBean} to create and initialize a Camel {@CamelContext}
+ * and install routes either explicitly configured in Spring or found by searching the classpath.
+ *
+ * @version $Revision$
+ */
+public class CamelContextFactoryBean implements FactoryBean, InitializingBean, DisposableBean,
ApplicationContextAware {
+    private CamelContext context;
+    private boolean singleton = true;
+    private List<RouteBuilder> routeBuilders = new ArrayList<RouteBuilder>();
+    private String[] packages = {};
+    private ApplicationContext applicationContext;
+
+    public Object getObject() throws Exception {
+        return getContext();
+    }
+
+    public Class getObjectType() {
+        return CamelContext.class;
+    }
+
+    public boolean isSingleton() {
+        return singleton;
+    }
+
+    public void afterPropertiesSet() throws Exception {
+
+        // lets force any lazy creation
+        getContext();
+
+        findRouteBuiders();
+        installRoutes();
+
+        // now lets activate the routes
+        getContext().activateEndpoints();
+    }
+
+    public void destroy() throws Exception {
+        getContext().deactivateEndpoints();
+    }
+
+    // Properties
+    //-------------------------------------------------------------------------
+    public CamelContext getContext() {
+        if (context == null) {
+            context = new DefaultCamelContext();
+        }
+        return context;
+    }
+
+    public void setContext(CamelContext context) {
+        this.context = context;
+    }
+
+    public List<RouteBuilder> getRouteBuilders() {
+        return routeBuilders;
+    }
+
+    /**
+     * Sets the {@link RouteBuilder} instances to be installed in this context
+     *
+     * @param routeBuilders the route builders to activate on startup
+     */
+    public void setRouteBuilders(List<RouteBuilder> routeBuilders) {
+        this.routeBuilders = routeBuilders;
+    }
+
+    public ApplicationContext getApplicationContext() {
+        return applicationContext;
+    }
+
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    public String[] getPackages() {
+        return packages;
+    }
+
+    public void setPackages(String[] packages) {
+        this.packages = packages;
+    }
+
+
+    // Implementation methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * Strategy to install all available routes into the context
+     */
+    protected void installRoutes() {
+        for (RouteBuilder routeBuilder : routeBuilders) {
+            getContext().setRoutes(routeBuilder);
+        }
+    }
+
+    /**
+     * Strategy method to try find {@link RouteBuilder} instances on the classpath
+     */
+    protected void findRouteBuiders() throws IllegalAccessException, InstantiationException
{
+        if (packages != null && packages.length > 0) {
+            RouteBuilderFinder finder = new RouteBuilderFinder(this);
+            finder.appendBuilders(getRouteBuilders());
+        }
+    }
+}

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
(added)
+++ activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,120 @@
+/**
+ *
+ * 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.spring;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.util.ResolverUtil;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A helper class which will find all {@link RouteBuilder} instances on the classpath
+ *
+ * @version $Revision$
+ */
+public class RouteBuilderFinder implements ApplicationContextAware {
+    private String[] packages = {};
+    private ApplicationContext applicationContext;
+    private ResolverUtil resolver = new ResolverUtil();
+
+    public RouteBuilderFinder(ApplicationContext applicationContext, String[] packages) {
+        this.applicationContext = applicationContext;
+        this.packages = packages;
+    }
+
+    public RouteBuilderFinder(CamelContextFactoryBean factoryBean) {
+        this.applicationContext = factoryBean.getApplicationContext();
+        this.packages = factoryBean.getPackages();
+    }
+
+    public String[] getPackages() {
+        return packages;
+    }
+
+    public void setPackages(String[] packages) {
+        this.packages = packages;
+    }
+
+    public ApplicationContext getApplicationContext() {
+        return applicationContext;
+    }
+
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
+        this.applicationContext = applicationContext;
+    }
+
+    /**
+     * Appends all the {@link RouteBuilder} instances that can be found on the classpath
+     */
+    public void appendBuilders(List<RouteBuilder> list) throws IllegalAccessException,
InstantiationException {
+        resolver.findImplementations(RouteBuilder.class, packages);
+        //resolver.findAnnotated(Endpoint.class, packages);
+        Set<Class> classes = resolver.getClasses();
+        for (Class aClass : classes) {
+            if (shouldIgnoreBean(aClass)) {
+                continue;
+            }
+            if (isValidClass(aClass)) {
+                list.add(instantiateBuilder(aClass));
+            }
+        }
+    }
+
+    public void destroy() throws Exception {
+    }
+
+    /**
+     * Lets ignore beans that are not explicitly configured in the spring.xml
+     */
+    protected boolean shouldIgnoreBean(Class type) {
+        Map beans = applicationContext.getBeansOfType(type, true, true);
+        if (beans == null || beans.isEmpty()) {
+            return false;
+        }
+        // TODO apply some filter?
+        return true;
+    }
+
+    /**
+     * Returns true if the object is non-abstract and supports a zero argument constructor
+     */
+    protected boolean isValidClass(Class type) {
+        if (!Modifier.isAbstract(type.getModifiers()) && !type.isInterface()) {
+            Constructor[] constructors = type.getDeclaredConstructors();
+            for (Constructor constructor : constructors) {
+                Class[] classes = constructor.getParameterTypes();
+                if (classes.length == 0) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    protected RouteBuilder instantiateBuilder(Class type) throws IllegalAccessException,
InstantiationException {
+        // TODO we could support spring-injection for these types
+        return (RouteBuilder) type.newInstance();
+    }
+}
\ No newline at end of file

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-spring/src/main/java/org/apache/camel/spring/RouteBuilderFinder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
(added)
+++ activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,58 @@
+/**
+ *
+ * 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.spring;
+
+import junit.framework.TestCase;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.ApplicationContext;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.TestSupport;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @version $Revision$
+ */
+public class SpringClassPathRouteLoaderTest extends TestSupport {
+    private static final transient Log log = LogFactory.getLog(SpringClassPathRouteLoaderTest.class);
+    
+    public void testLoadingRouteBuildresOnTheClassPathViaSpringXml() throws Exception {
+        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("org/apache/camel/spring/findRouteBuildersOnClassPath.xml");
+
+        CamelContext context = (CamelContext) applicationContext.getBean("camel");
+        assertNotNull("No context found!", context);
+
+        Map<Endpoint,Processor> map = context.getRoutes();
+        log.debug("Found routes: " + map);
+
+        Set<Map.Entry<Endpoint,Processor>> entries = map.entrySet();
+        assertEquals("One Route should be found", 1, entries.size());
+
+        for (Map.Entry<Endpoint, Processor> entry : entries) {
+            Endpoint key = entry.getKey();
+            Processor processor = entry.getValue();
+
+            assertEndpointUri(key, "queue:test.a");
+        }
+    }
+}

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/SpringClassPathRouteLoaderTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
(added)
+++ activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,29 @@
+/**
+ *
+ * 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.spring.example.test1;
+
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * @version $Revision$
+ */
+public class MyRouteBuilder extends RouteBuilder {
+    public void configure() {
+        from("queue:test.a").to("queue:test.b");
+    }
+}

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-spring/src/test/java/org/apache/camel/spring/example/test1/MyRouteBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml?view=auto&rev=521369
==============================================================================
--- activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
(added)
+++ activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
Thu Mar 22 10:45:29 2007
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+  <bean id="camel" class="org.apache.camel.spring.CamelContextFactoryBean">
+    <property name="packages" value="org.apache.camel.spring.example"/>
+  </bean>
+</beans>
+<!-- END SNIPPET: example -->

Propchange: activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: activemq/camel/trunk/camel-spring/src/test/resources/org/apache/camel/spring/findRouteBuildersOnClassPath.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml



Mime
View raw message