You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2009/06/17 08:04:53 UTC

svn commit: r785479 [1/2] - in /camel/trunk: camel-core/src/main/java/org/apache/camel/impl/ camel-core/src/main/java/org/apache/camel/impl/scan/ camel-core/src/main/java/org/apache/camel/model/ camel-core/src/main/java/org/apache/camel/spi/ camel-core...

Author: davsclaus
Date: Wed Jun 17 06:04:52 2009
New Revision: 785479

URL: http://svn.apache.org/viewvc?rev=785479&view=rev
Log:
CAMEL-1708: New packageScan configuration for Spring DSL to use ANT path style filters for scanning RouteBuilder classes. Replaces the old package tag, that is @deprecated. Thanks to Stephen Gargan for this great patch.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java   (contents, props changed)
      - copied, changed from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithAnyPackageScanFilter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java   (contents, props changed)
      - copied, changed from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithPackageScanFilter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java   (contents, props changed)
      - copied, changed from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AssignableToPackageScanFilter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java   (with props)
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java   (with props)
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java   (with props)
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java   (with props)
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java   (with props)
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanWithDeprecatedPackagesTest.java   (with props)
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/route/MyExcludedRouteBuilder.java   (with props)
    camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/config/scan/componentScanWithPackages.xml   (with props)
    camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/config/scan/explicitlyDefinedRouteExclusion.xml   (with props)
Removed:
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithAnyPackageScanFilter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithPackageScanFilter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AssignableToPackageScanFilter.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/PackageScanClassResolver.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/CollectionHelper.java
    camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
    camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/SpringTestSupport.java
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanTest.java
    camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/config/scan/componentScan.xml

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java Wed Jun 17 06:04:52 2009
@@ -33,6 +33,10 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 
+import org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter;
+import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter;
+import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
+import org.apache.camel.impl.scan.CompositePackageScanFilter;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.util.ObjectHelper;
@@ -46,11 +50,19 @@
 
     protected static final transient Log LOG = LogFactory.getLog(DefaultPackageScanClassResolver.class);
     private Set<ClassLoader> classLoaders;
+    private Set<PackageScanFilter> scanFilters;
 
     public void addClassLoader(ClassLoader classLoader) {
         getClassLoaders().add(classLoader);
     }
 
+    public void addFilter(PackageScanFilter filter) {
+        if (scanFilters == null) {
+            scanFilters = new LinkedHashSet<PackageScanFilter>();
+        }
+        scanFilters.add(filter);
+    }
+
     public Set<ClassLoader> getClassLoaders() {
         if (classLoaders == null) {
             classLoaders = new HashSet<ClassLoader>();
@@ -80,7 +92,7 @@
             LOG.debug("Searching for annotations of " + annotation.getName() + " in packages: " + Arrays.asList(packageNames));
         }
 
-        PackageScanFilter test = new AnnotatedWithPackageScanFilter(annotation, true);
+        PackageScanFilter test = getCompositeFilter(new AnnotatedWithPackageScanFilter(annotation, true));
         Set<Class> classes = new LinkedHashSet<Class>();
         for (String pkg : packageNames) {
             find(test, pkg, classes);
@@ -103,7 +115,7 @@
             LOG.debug("Searching for annotations of " + annotations + " in packages: " + Arrays.asList(packageNames));
         }
 
-        PackageScanFilter test = new AnnotatedWithAnyPackageScanFilter(annotations, true);
+        PackageScanFilter test = getCompositeFilter(new AnnotatedWithAnyPackageScanFilter(annotations, true));
         Set<Class> classes = new LinkedHashSet<Class>();
         for (String pkg : packageNames) {
             find(test, pkg, classes);
@@ -126,7 +138,7 @@
             LOG.debug("Searching for implementations of " + parent.getName() + " in packages: " + Arrays.asList(packageNames));
         }
 
-        PackageScanFilter test = new AssignableToPackageScanFilter(parent);
+        PackageScanFilter test = getCompositeFilter(new AssignableToPackageScanFilter(parent));
         Set<Class> classes = new LinkedHashSet<Class>();
         for (String pkg : packageNames) {
             find(test, pkg, classes);
@@ -157,13 +169,12 @@
         return classes;
     }
 
-
     protected void find(PackageScanFilter test, String packageName, Set<Class> classes) {
         packageName = packageName.replace('.', '/');
 
         Set<ClassLoader> set = getClassLoaders();
 
-        for (ClassLoader classLoader : set) {            
+        for (ClassLoader classLoader : set) {
             find(test, packageName, classLoader, classes);
         }
     }
@@ -268,8 +279,14 @@
         return loader.getResources(packageName);
     }
 
-
-
+    private PackageScanFilter getCompositeFilter(PackageScanFilter filter) {
+        if (scanFilters != null) {
+            CompositePackageScanFilter composite = new CompositePackageScanFilter(scanFilters);
+            composite.addFilter(filter);
+            return composite;
+        }
+        return filter;
+    }
 
     /**
      * Finds matches in a physical directory on a filesystem. Examines all files

Copied: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java (from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithAnyPackageScanFilter.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithAnyPackageScanFilter.java&r1=785473&r2=785479&rev=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithAnyPackageScanFilter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl;
+package org.apache.camel.impl.scan;
 
 import java.lang.annotation.Annotation;
 import java.util.Set;

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Copied: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java (from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithPackageScanFilter.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithPackageScanFilter.java&r1=785473&r2=785479&rev=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AnnotatedWithPackageScanFilter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl;
+package org.apache.camel.impl.scan;
 
 import java.lang.annotation.Annotation;
 

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Copied: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java (from r785473, camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AssignableToPackageScanFilter.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AssignableToPackageScanFilter.java&r1=785473&r2=785479&rev=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/AssignableToPackageScanFilter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -14,7 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl;
+package org.apache.camel.impl.scan;
+
+import java.util.HashSet;
+import java.util.Set;
 
 import org.apache.camel.spi.PackageScanFilter;
 
@@ -22,18 +25,42 @@
  * Package scan filter for testing if a given class is assignable to another class.
  */
 public class AssignableToPackageScanFilter implements PackageScanFilter {
-    private final Class parent;
+    private final Set<Class> parents = new HashSet<Class>();
+
+    public AssignableToPackageScanFilter() {
+    }
 
     public AssignableToPackageScanFilter(Class parentType) {
-        this.parent = parentType;
+        parents.add(parentType);
+    }
+
+    public AssignableToPackageScanFilter(Set<Class> parents) {
+        this.parents.addAll(parents);
+    }
+
+    public void addParentType(Class parentType) {
+        parents.add(parentType);
     }
 
     public boolean matches(Class type) {
-        return type != null && parent.isAssignableFrom(type);
+        if (parents != null && parents.size() > 0) {
+            for (Class parent : parents) {
+                if (parent.isAssignableFrom(type)) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     @Override
     public String toString() {
-        return "is assignable to " + parent.getSimpleName();
+        StringBuilder sb = new StringBuilder();
+        for (Class parent : parents) {
+            sb.append(parent.getSimpleName()).append(", ");
+        }
+        sb.setLength(sb.length() > 0 ? sb.length() - 2 : 0);
+        return "is assignable to any of " + sb;
     }
+
 }

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,54 @@
+/**
+ * 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.impl.scan;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.camel.spi.PackageScanFilter;
+
+/**
+ * <code>CompositePackageScanFilter</code> allows multiple
+ * {@link PackageScanFilter}s to be composed into a single filter. For a
+ * {@link Class} to match a {@link CompositePackageScanFilter} it must match
+ * each of the filters the composite contains
+ */
+public class CompositePackageScanFilter implements PackageScanFilter {
+    private Set<PackageScanFilter> filters;
+
+    public CompositePackageScanFilter() {
+        filters = new LinkedHashSet<PackageScanFilter>();
+    }
+
+    public CompositePackageScanFilter(Set<PackageScanFilter> filters) {
+        this.filters = new LinkedHashSet<PackageScanFilter>(filters);
+    }
+
+    public void addFilter(PackageScanFilter filter) {
+        filters.add(filter);
+    }
+
+    public boolean matches(Class type) {
+        for (PackageScanFilter filter : filters) {
+            if (!filter.matches(type)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,44 @@
+/**
+ * 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.impl.scan;
+
+import org.apache.camel.spi.PackageScanFilter;
+
+/**
+ * Package scan filter for inverting the match result of a subfilter. If the
+ * subfilter would match and return <tt>true</tt> this filter will invert that
+ * match and return <tt>false</tt>.
+ */
+@SuppressWarnings("unchecked")
+public class InvertingPackageScanFilter implements PackageScanFilter {
+
+    private PackageScanFilter filter;
+
+    public InvertingPackageScanFilter(PackageScanFilter filter) {
+        this.filter = filter;
+    }
+
+    public boolean matches(Class type) {
+        return !filter.matches(type);
+    }
+
+    @Override
+    public String toString() {
+        return "![" + filter.toString() + "]";
+    }
+
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,127 @@
+/**
+ * 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.impl.scan;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.camel.spi.PackageScanFilter;
+import org.springframework.util.AntPathMatcher;
+
+/**
+ * <code>PatternBasedPackageScanFilter</code> uses an underlying
+ * {@link AntPathMatcher} to filter scanned files according to include and
+ * exclude patterns.
+ * 
+ * @see AntPathMatcher
+ */
+public class PatternBasedPackageScanFilter implements PackageScanFilter {
+    private AntPathMatcher matcher = new AntPathMatcher();
+
+    private List<String> excludePatterns;
+    private List<String> includePatterns;
+
+    /**
+     * add and exclude pattern to the filter. Classes matching this pattern will
+     * not match the filter 
+     * 
+     * @param excludePattern
+     */
+    public void addExcludePattern(String excludePattern) {
+        if (excludePatterns == null) {
+            excludePatterns = new ArrayList<String>();
+        }
+        excludePatterns.add(excludePattern);
+    }
+
+    /**
+     * add and include pattern to the filter. Classes must match one of supplied
+     * include patterns to match the filter 
+     * 
+     * @param includePattern
+     */
+    public void addIncludePattern(String includePattern) {
+        if (includePatterns == null) {
+            includePatterns = new ArrayList<String>();
+        }
+        includePatterns.add(includePattern);
+    }
+    
+    public void addIncludePatterns(Collection<String> includes) {
+        if (includePatterns == null) {
+            includePatterns = new ArrayList<String>();
+        }
+        includePatterns.addAll(includes);
+    }
+    
+    public void addExcludePatterns(Collection<String> excludes) {
+        if (excludePatterns == null) {
+            excludePatterns = new ArrayList<String>();
+        }
+        excludePatterns.addAll(excludes);
+    }
+
+    /**
+     * Tests if a given class matches the patterns in this filter. Patterns are
+     * specified by {@link AntPathMatcher}
+     * <p>
+     * if no include or exclude patterns are set then all classes match.
+     * <p>
+     * If the filter contains only include filters, then the candidate class
+     * must match one of the include patterns to match the filter and return
+     * true.
+     * <p>
+     * If the filter contains only exclude filters, then the filter will return
+     * true unless the candidate class matches an exclude pattern.
+     * <p>
+     * if this contains both include and exclude filters, then the above rules
+     * apply with excludes taking precedence over includes i.e. an include
+     * pattern of java.util.* and an exclude pattern of java.util.jar.* will
+     * include a file only if it is in the util pkg and not in the util.jar
+     * package.
+     * 
+     * @return true if candidate class matches according to the above rules
+     */
+    public boolean matches(Class candidateClass) {
+        String candidate = candidateClass.getName();
+        if (includePatterns != null || excludePatterns != null) {
+
+            if (excludePatterns != null && excludePatterns.size() > 0) {
+                if (matchesAny(excludePatterns, candidate)) {
+                    return false;
+                }
+            }
+
+            if (includePatterns != null && includePatterns.size() > 0) {
+                return matchesAny(includePatterns, candidate);
+            }
+
+        }
+        return true;
+    }
+
+    private boolean matchesAny(List<String> patterns, String candidate) {
+        for (String pattern : patterns) {
+            if (matcher.match(pattern, candidate)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,60 @@
+/**
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * <code>PackageScanDefinition</code> represents a &lt;package-scan/&gt element.
+ */
+@XmlRootElement(name = "packageScan")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PackageScanDefinition {
+
+    @XmlElement(name = "packages", required = true)
+    private List<String> packages = new ArrayList<String>();
+
+    @XmlElement(name = "excludes", required = false)
+    private List<String> excludes = new ArrayList<String>();
+
+    @XmlElement(name = "includes", required = false)
+    private List<String> includes = new ArrayList<String>();
+
+    public List<String> getExcludes() {
+        return excludes;
+    }
+
+    public List<String> getIncludes() {
+        return includes;
+    }
+
+    public List<String> getPackages() {
+        return packages;
+    }
+
+    protected void clear() {
+        packages.clear();
+        excludes.clear();
+        includes.clear();
+    }
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/model/PackageScanDefinition.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/PackageScanClassResolver.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/PackageScanClassResolver.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/PackageScanClassResolver.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/PackageScanClassResolver.java Wed Jun 17 06:04:52 2009
@@ -84,5 +84,12 @@
      * @return the classes found, returns an empty set if none found
      */
     Set<Class> findByFilter(PackageScanFilter fiter, String... packageNames);
+    
+    /**
+     * Add a filter that will be applied to all scan operations
+     * 
+     * @param filter filter to filter desired classes in all scan operations
+     */
+    void addFilter(PackageScanFilter filter);
 
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/CollectionHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/CollectionHelper.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/CollectionHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/CollectionHelper.java Wed Jun 17 06:04:52 2009
@@ -20,9 +20,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.w3c.dom.NodeList;
 
@@ -112,6 +114,12 @@
         return answer;
     }
 
+    public static <T> Set<T> createSetContaining(T... contents) {
+        Set<T> contentsAsSet = new HashSet<T>();
+        contentsAsSet.addAll(Arrays.asList(contents));
+        return contentsAsSet;
+    }
+
     public static String collectionAsCommaDelimitedString(String[] col) {
         if (col == null || col.length == 0) {
             return "";

Modified: camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index (original)
+++ camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index Wed Jun 17 06:04:52 2009
@@ -42,6 +42,7 @@
 OnExceptionDefinition
 OptionalIdentifiedType
 OtherwiseDefinition
+PackageScanDefinition
 PipelineDefinition
 PolicyDefinition
 ProcessDefinition

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,124 @@
+/**
+ * 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.impl.scan;
+
+import java.lang.annotation.Annotation;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.camel.impl.DefaultPackageScanClassResolver;
+import org.apache.camel.impl.scan.test.ScannableOne;
+import org.apache.camel.impl.scan.test.ScannableTwo;
+import org.apache.camel.impl.scan.test.a.ScanTargetOne;
+import org.apache.camel.impl.scan.test.b.ScanTargetTwo;
+import org.apache.camel.impl.scan.test.c.ScanTargetThree;
+
+public class DefaultPackageScanClassResolverTest extends ScanTestSupport {
+
+    private DefaultPackageScanClassResolver resolver;
+    private Set<Class<? extends Annotation>> annotations = new HashSet<Class<? extends Annotation>>();
+    private String scanPackage = "org.apache.camel.impl.scan.test";
+
+    public void setUp() throws Exception {
+        super.setUp();
+        resolver = new DefaultPackageScanClassResolver();
+        annotations.add(ScannableOne.class);
+        annotations.add(ScannableTwo.class);
+    }
+
+    public void testFindByAnnotationWithoutExtraFilters() {
+        Set<Class> scanned = resolver.findAnnotated(ScannableOne.class, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetOne.class, ScanTargetTwo.class);
+
+        scanned = resolver.findAnnotated(ScannableTwo.class, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetThree.class);
+    }
+
+    public void testFindByAnnotationsWithoutExtraFilters() {
+        Set<Class> scanned = resolver.findAnnotated(annotations, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetOne.class, ScanTargetTwo.class, ScanTargetThree.class);
+    }
+
+    public void testFindImplementationsWithoutExtraFilters() {
+        Set<Class> scanned = resolver.findImplementations(ScanTargetOne.class, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetOne.class, ScanTargetTwo.class);
+    }
+    
+    public void testFindByAnnotationWithIncludePackageFilter() {
+        filter.addIncludePattern(scanPackage + ".b.*");
+        resolver.addFilter(filter);
+
+        Set<Class> scanned = resolver.findAnnotated(ScannableOne.class, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetTwo.class);
+
+        scanned = resolver.findAnnotated(ScannableTwo.class, scanPackage);
+        validateMatchingSetContains(scanned);
+    }
+
+    public void testFindByAnnotationsWithIncludePackageFilter() {
+        filter.addIncludePattern(scanPackage + ".b.*");
+        filter.addIncludePattern(scanPackage + ".c.*");
+        resolver.addFilter(filter);
+
+        Set<Class> scanned = resolver.findAnnotated(annotations, "org.apache.camel.impl.scan");
+        validateMatchingSetContains(scanned, ScanTargetTwo.class, ScanTargetThree.class);
+    }
+
+    public void testFindByAnnotationWithExcludePackageFilter() {
+        filter.addExcludePattern(scanPackage + ".b.*");
+        filter.addExcludePattern(scanPackage + ".c.*");
+        resolver.addFilter(filter);
+
+        Set<Class> scanned = resolver.findAnnotated(ScannableOne.class, scanPackage);
+        validateMatchingSetContains(scanned, ScanTargetOne.class);
+
+        scanned = resolver.findAnnotated(ScannableTwo.class, scanPackage);
+        validateMatchingSetContains(scanned);
+    }
+
+    public void testFindByAnnotationsWithExcludePackageFilter() {
+        filter.addExcludePattern(scanPackage + ".a.*");
+
+        Set<Class> scanned = resolver.findAnnotated(annotations, "org.apache.camel.impl.scan");
+        validateMatchingSetContains(scanned, ScanTargetTwo.class, ScanTargetThree.class);
+    }
+
+    public void testFindByFilterWithIncludePackageFilter() {
+        filter.addIncludePattern(scanPackage + ".**.ScanTarget*");
+        resolver.addFilter(filter);
+
+        Set<Class> scanned = resolver.findByFilter(filter, "org.apache.camel.impl.scan");
+        validateMatchingSetContains(scanned, ScanTargetOne.class, ScanTargetTwo.class, ScanTargetThree.class);
+    }
+    
+    public void testFindImplementationsWithIncludePackageFilter() {
+        filter.addIncludePattern(scanPackage + ".b.*");
+        resolver.addFilter(filter);
+        
+        Set<Class> scanned = resolver.findImplementations(ScanTargetOne.class, scanPackage);
+        validateMatchingSetContains(scanned,  ScanTargetTwo.class);
+    }
+    
+    public void testFindImplementationsWithExcludePackageFilter() {
+        filter.addExcludePattern(scanPackage + ".a.*");
+        resolver.addFilter(filter);
+        
+        Set<Class> scanned = resolver.findImplementations(ScanTargetOne.class, scanPackage);
+        validateMatchingSetContains(scanned,  ScanTargetTwo.class);
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/DefaultPackageScanClassResolverTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,106 @@
+/**
+ * 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.impl.scan;
+
+import java.lang.annotation.Annotation;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.camel.impl.scan.test.ScannableOne;
+import org.apache.camel.impl.scan.test.ScannableTwo;
+import org.apache.camel.impl.scan.test.a.ScanTargetOne;
+import org.apache.camel.impl.scan.test.b.ScanTargetTwo;
+import org.apache.camel.impl.scan.test.c.ScanTargetThree;
+import org.apache.camel.spi.PackageScanFilter;
+import org.apache.camel.util.CollectionHelper;
+
+public class PackageScanFiltersTest extends TestCase {
+
+    public void testAssignableToPackageScanFilter() {
+        AssignableToPackageScanFilter filter = new AssignableToPackageScanFilter();
+        assertFalse(filter.matches(ScanTargetOne.class));
+
+        filter = new AssignableToPackageScanFilter(ScanTargetOne.class);
+        validateFilter(filter, ScanTargetOne.class);
+
+        filter = new AssignableToPackageScanFilter(ScanTargetOne.class);
+        validateFilter(filter, ScanTargetTwo.class);
+
+        Set<Class> classes = new LinkedHashSet<Class>();
+        classes.add(ScanTargetOne.class);
+        classes.add(ScanTargetThree.class);
+        filter = new AssignableToPackageScanFilter(classes);
+        validateFilter(filter, ScanTargetOne.class);
+        validateFilter(filter, ScanTargetTwo.class);
+        validateFilter(filter, ScanTargetThree.class);
+
+        assertEquals("is assignable to any of ScanTargetOne, ScanTargetThree", filter.toString());
+    }
+
+    public void testAnnotatedWithAnyPackageScanFilter() {
+        Set<Class<? extends Annotation>> annotations = new LinkedHashSet<Class<? extends Annotation>>();
+        annotations.add(ScannableOne.class);
+        annotations.add(ScannableTwo.class);
+
+        AnnotatedWithAnyPackageScanFilter filter = new AnnotatedWithAnyPackageScanFilter(annotations);
+        Class<ScanTargetOne> type = ScanTargetOne.class;
+        validateFilter(filter, type);
+        validateFilter(filter, ScanTargetThree.class);
+
+        assertEquals("annotated with any @[[interface org.apache.camel.impl.scan.test.ScannableOne, interface org.apache.camel.impl.scan.test.ScannableTwo]]", filter.toString());
+    }
+
+    public void testAnnotatedWithPackageScanFilter() {
+        AnnotatedWithPackageScanFilter filter = new AnnotatedWithPackageScanFilter(ScannableOne.class);
+        validateFilter(filter, ScanTargetOne.class);
+        validateFilter(filter, ScanTargetTwo.class);
+
+        filter = new AnnotatedWithPackageScanFilter(ScannableTwo.class);
+        validateFilter(filter, ScanTargetThree.class);
+        assertEquals("annotated with @ScannableTwo", filter.toString());
+    }
+
+    public void testCompositePackageScanFilter() {
+        PackageScanFilter one = new AnnotatedWithPackageScanFilter(ScannableOne.class);
+        PackageScanFilter two = new AssignableToPackageScanFilter(ScanTargetOne.class);
+        Set<PackageScanFilter> filters = CollectionHelper.createSetContaining(one, two);
+
+        CompositePackageScanFilter filter = new CompositePackageScanFilter(filters);
+        validateFilter(filter, ScanTargetOne.class);
+        validateFilter(filter, ScanTargetTwo.class);
+
+        filter = new CompositePackageScanFilter();
+        filter.addFilter(one);
+        filter.addFilter(two);
+        validateFilter(filter, ScanTargetOne.class);
+        validateFilter(filter, ScanTargetTwo.class);
+    }
+
+    public void testInvertingFilter() {
+        InvertingPackageScanFilter filter = new InvertingPackageScanFilter(new AnnotatedWithPackageScanFilter(ScannableOne.class));
+        validateFilter(filter, ScanTargetThree.class);
+        assertEquals("![annotated with @ScannableOne]", filter.toString());
+    }
+
+    private void validateFilter(PackageScanFilter filter, Class type) {
+        assertTrue(filter.matches(type));
+        assertFalse(new InvertingPackageScanFilter(filter).matches(type));
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PackageScanFiltersTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,181 @@
+/**
+ * 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.impl.scan;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarFile;
+
+import org.apache.camel.util.CollectionHelper;
+
+@SuppressWarnings("unchecked")
+public class PatternBasedPackageScanFilterTest extends ScanTestSupport {
+
+    private Set<Class> allClasses;
+
+    public void setUp() throws Exception {
+        // use classes that are pretty much constants
+        allClasses = new HashSet<Class>();
+        allClasses.add(List.class);
+        allClasses.add(ArrayList.class);
+        allClasses.add(LinkedList.class);
+        allClasses.add(File.class);
+        allClasses.add(FileInputStream.class);
+        allClasses.add(RandomAccessFile.class);
+        // contains file pattern but in util pkg not io
+        allClasses.add(JarFile.class);
+        super.setUp();
+    }
+
+    public void testNoPattersIncludeAllClasses() {
+        validateMatchingSetContains(allClasses);
+    }
+
+    public void testIncludePatterns() {
+        addIncludePatterns("*");
+        validateMatchingSetContains(allClasses);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java*");
+        validateMatchingSetContains(allClasses);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.io.*");
+        validateMatchingSetContains(File.class, FileInputStream.class, RandomAccessFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.util.**");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class, JarFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.io.*", "java.util.*");
+        validateMatchingSetContains(allClasses);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.io.File");
+        validateMatchingSetContains(File.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.io.File*");
+        validateMatchingSetContains(File.class, FileInputStream.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.io.*File*");
+        validateMatchingSetContains(File.class, FileInputStream.class, RandomAccessFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.**.*File*");
+        validateMatchingSetContains(File.class, FileInputStream.class, RandomAccessFile.class, JarFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.util.*List");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.lang", "java.lang.*");
+        validateMatchingSetContains();
+
+        filter = new PatternBasedPackageScanFilter();
+        addIncludePatterns("java.lang", "java.lang.*");
+        validateMatchingSetContains();
+    }
+
+    public void testExcludePatterns() {
+        addExcludePatterns("*");
+        validateMatchingSetContains();
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java*");
+        validateMatchingSetContains();
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.io.*");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class, JarFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.util.**");
+        validateMatchingSetContains(File.class, FileInputStream.class, RandomAccessFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.io.*", "java.util.*");
+        validateMatchingSetContains();
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.io.File");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class, JarFile.class, FileInputStream.class, RandomAccessFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.io.File*");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class, JarFile.class, RandomAccessFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.io.*File*");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class, JarFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.**.*File*");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.util.*List");
+        validateMatchingSetContains(File.class, FileInputStream.class, RandomAccessFile.class, JarFile.class);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.lang", "java.lang.*");
+        validateMatchingSetContains(allClasses);
+
+        filter = new PatternBasedPackageScanFilter();
+        addExcludePatterns("java.lang", "java.lang.*");
+        validateMatchingSetContains(allClasses);
+    }
+
+    public void testExcludeHasPrecedenceOverInclude() {
+        // include any classes from the util pkg but exclude those in jar
+        addIncludePatterns("java.util.*");
+        addExcludePatterns("java.util.jar.*");
+        validateMatchingSetContains(List.class, ArrayList.class, LinkedList.class);
+    }
+    
+    public void testBulkIncludeAdd() {
+        // include any classes from the util pkg but exclude those in jar
+        Set<String> includes = CollectionHelper.createSetContaining("java.io.*", "java.util.*");
+        filter.addIncludePatterns(includes);
+        validateMatchingSetContains(allClasses);
+    }
+    
+    public void testBulkExcludeAdd() {
+        // include any classes from the util pkg but exclude those in jar
+        Set<String> excludes = CollectionHelper.createSetContaining("java.io.*", "java.util.*");
+        filter.addExcludePatterns(excludes);
+        validateMatchingSetContains();
+    }
+
+    protected void validateMatchingSetContains(Class... matchingClasses) {
+        super.validateMatchingSetContains(allClasses, matchingClasses);
+    }
+
+    protected void validateMatchingSetContains(Set<Class> matchingClasses) {
+        super.validateMatchingSetContains(allClasses, matchingClasses);
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/PatternBasedPackageScanFilterTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,74 @@
+/**
+ * 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.impl.scan;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("unchecked")
+public abstract class ScanTestSupport extends TestCase {
+
+    protected PatternBasedPackageScanFilter filter;
+
+    public void setUp() throws Exception {
+        filter = new PatternBasedPackageScanFilter();
+    }
+
+    protected void validateMatchingSetContains(Set<Class> scannedClasses, Class... matchingClasses) {
+        HashSet<Class> expectedSet = new HashSet<Class>();
+        for (Class expected : matchingClasses) {
+            expectedSet.add(expected);
+        }
+        validateMatchingSetContains(scannedClasses, expectedSet);
+    }
+
+    protected void validateMatchingSetContains(Set<Class> scannedClasses, Set<Class> matchingClasses) {
+        Set<Class> matching = getMatchingClasses(scannedClasses, filter);
+        assertEquals("Incorrect number of classes matched", matchingClasses.size(), matching.size());
+
+        for (Class expected : matchingClasses) {
+            assertTrue("Expected matching class '" + expected + "' is not present", matching.contains(expected));
+        }
+    }
+
+    protected void addIncludePatterns(String... patterns) {
+        for (String pattern : patterns) {
+            filter.addIncludePattern(pattern);
+        }
+    }
+
+    protected void addExcludePatterns(String... patterns) {
+        for (String pattern : patterns) {
+            filter.addExcludePattern(pattern);
+        }
+    }
+
+    public Set<Class> getMatchingClasses(Set<Class> scannedClasses, PatternBasedPackageScanFilter filter) {
+        Set<Class> matching = new HashSet<Class>();
+
+        for (Class candidate : scannedClasses) {
+            if (filter.matches(candidate)) {
+                matching.add(candidate);
+            }
+        }
+
+        return matching;
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/ScanTestSupport.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,25 @@
+/**
+ * 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.impl.scan.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ScannableOne {
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableOne.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,25 @@
+/**
+ * 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.impl.scan.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ScannableTwo {
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/ScannableTwo.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,27 @@
+/**
+ * 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.impl.scan.test.a;
+
+import org.apache.camel.impl.scan.test.ScannableOne;
+
+@ScannableOne
+public class ScanTargetOne {
+
+    public void someMethod() {
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/a/ScanTargetOne.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java Wed Jun 17 06:04:52 2009
@@ -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.impl.scan.test.b;
+
+import org.apache.camel.impl.scan.test.ScannableOne;
+import org.apache.camel.impl.scan.test.a.ScanTargetOne;
+
+@ScannableOne
+@SuppressWarnings("all")
+public class ScanTargetTwo extends ScanTargetOne {
+
+    public void someMethod() {
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/b/ScanTargetTwo.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,24 @@
+/**
+ * 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.impl.scan.test.c;
+
+public class NotAScanTarget {
+
+    public void someMethod() {
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/NotAScanTarget.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,27 @@
+/**
+ * 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.impl.scan.test.c;
+
+import org.apache.camel.impl.scan.test.ScannableTwo;
+
+@ScannableTwo()
+public class ScanTargetThree {
+
+    public void someMethod() {
+    }
+
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/scan/test/c/ScanTargetThree.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java Wed Jun 17 06:04:52 2009
@@ -32,6 +32,7 @@
 import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.impl.DefaultLifecycleStrategy;
+import org.apache.camel.impl.scan.PatternBasedPackageScanFilter;
 import org.apache.camel.management.DefaultInstrumentationAgent;
 import org.apache.camel.management.InstrumentationLifecycleStrategy;
 import org.apache.camel.model.FromDefinition;
@@ -41,6 +42,7 @@
 import org.apache.camel.model.InterceptSendToEndpointDefinition;
 import org.apache.camel.model.OnCompletionDefinition;
 import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.PackageScanDefinition;
 import org.apache.camel.model.PolicyDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteBuilderDefinition;
@@ -104,6 +106,8 @@
     private PropertiesDefinition properties;
     @XmlElement(name = "package", required = false)
     private String[] packages = {};
+    @XmlElement(name = "packageScan", type = PackageScanDefinition.class, required = false)
+    private PackageScanDefinition packageScan;
     @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class, required = false)
     private CamelJMXAgentDefinition camelJMXAgent;    
     @XmlElements({
@@ -563,6 +567,10 @@
         this.properties = properties;
     }
 
+    /**
+     * @deprecated replaced by {@link #getPackageScan()}
+     */
+    @Deprecated
     public String[] getPackages() {
         return packages;
     }
@@ -572,13 +580,30 @@
      * extend {@link RouteBuilder} to be auto-wired up to the
      * {@link SpringCamelContext} as a route. Note that classes are excluded if
      * they are specifically configured in the spring.xml
-     *
+     * 
+     * @deprecated replaced by {@link #setPackageScan(org.apache.camel.model.PackageScanDefinition)}
      * @param packages the package names which are recursively searched
      */
+    @Deprecated
     public void setPackages(String[] packages) {
         this.packages = packages;
     }
 
+    public PackageScanDefinition getPackageScan() {
+        return packageScan;
+    }
+
+    /**
+     * Sets the package scanning information. Package scanning allows for the
+     * automatic discovery of certain camel classes at runtime for inclusion
+     * e.g. {@link RouteBuilder} implementations
+     * 
+     * @param packageScan the package scan
+     */
+    public void setPackageScan(PackageScanDefinition packageScan) {
+        this.packageScan = packageScan;
+    }
+
     public void setBeanPostProcessor(BeanPostProcessor postProcessor) {
         this.beanPostProcessor = postProcessor;
     }
@@ -766,26 +791,55 @@
      * Strategy method to try find {@link RouteBuilder} instances on the classpath
      */
     protected void findRouteBuilders() throws Exception {
-        List<String> packages = new ArrayList<String>();
+
+        PackageScanClassResolver resolver = getContext().getPackageScanClassResolver();
+        addPackageElementContentsToScanDefinition();
+
+        PackageScanDefinition packageScanDef = getPackageScan();
+
+        if (packageScanDef != null && packageScanDef.getPackages().size() > 0) {
+
+            PatternBasedPackageScanFilter filter = new PatternBasedPackageScanFilter();
+            filter.addIncludePatterns(packageScanDef.getIncludes());
+            filter.addExcludePatterns(packageScanDef.getExcludes());
+            resolver.addFilter(filter);
+
+            String[] normalized = normalizePackages(packageScanDef.getPackages());
+            RouteBuilderFinder finder = new RouteBuilderFinder(getContext(), normalized, getContextClassLoaderOnStart(), getBeanPostProcessor(), getContext()
+                .getPackageScanClassResolver());
+            finder.appendBuilders(getAdditionalBuilders());
+        }
+
+    }
+
+    private void addPackageElementContentsToScanDefinition() {
+        PackageScanDefinition packageScanDef = getPackageScan();
 
         if (getPackages() != null && getPackages().length > 0) {
+            LOG.warn("Using a packages element to specify packages to search has been deprecated. Please use a package-scan element instead.");
+            if (packageScanDef == null) {
+                packageScanDef = new PackageScanDefinition();
+                setPackageScan(packageScanDef);
+            }
 
-            // normalize packages as end user can have inserted spaces or \n or the likes
-            for (String name : getPackages()) {
-                name = ObjectHelper.normalizeClassName(name);
-                if (ObjectHelper.isNotEmpty(name)) {
-                    if (LOG.isTraceEnabled()) {
-                        LOG.trace("Using package: " + name + " to scan for RouteBuilder classes");
-                    }
-                    packages.add(name);
-                }
+            for (String pkg : getPackages()) {
+                packageScanDef.getPackages().add(pkg);
             }
-            String[] normalized = packages.toArray(new String[packages.size()]);
+        }
+    }
 
-            RouteBuilderFinder finder = new RouteBuilderFinder(getContext(), normalized, getContextClassLoaderOnStart(),
-                    getBeanPostProcessor(), getContext().getPackageScanClassResolver());
-            finder.appendBuilders(getAdditionalBuilders());
+    private String[] normalizePackages(List<String> unnormalized) {
+        List<String> packages = new ArrayList<String>();
+        for (String name : unnormalized) {
+            name = ObjectHelper.normalizeClassName(name);
+            if (ObjectHelper.isNotEmpty(name)) {
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Using package: " + name + " to scan for RouteBuilder classes");
+                }
+                packages.add(name);
+            }
         }
+        return packages.toArray(new String[packages.size()]);
     }
-    
+
 }

Modified: camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java (original)
+++ camel/trunk/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java Wed Jun 17 06:04:52 2009
@@ -31,15 +31,6 @@
 import org.apache.camel.builder.xml.Namespaces;
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.SendDefinition;
-import org.apache.camel.model.dataformat.ArtixDSDataFormat;
-import org.apache.camel.model.dataformat.JaxbDataFormat;
-import org.apache.camel.model.dataformat.SerializationDataFormat;
-import org.apache.camel.model.dataformat.XMLBeansDataFormat;
-import org.apache.camel.model.loadbalancer.FailoverLoadBalancerDefinition;
-import org.apache.camel.model.loadbalancer.RandomLoadBalancerDefinition;
-import org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition;
-import org.apache.camel.model.loadbalancer.StickyLoadBalancerDefinition;
-import org.apache.camel.model.loadbalancer.TopicLoadBalancerDefinition;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spring.CamelBeanPostProcessor;
 import org.apache.camel.spring.CamelConsumerTemplateFactoryBean;
@@ -160,7 +151,7 @@
         classes.add(org.apache.camel.spring.CamelContextFactoryBean.class);
         classes.add(org.apache.camel.ExchangePattern.class);
         classes.add(org.apache.camel.model.RouteDefinition.class);
-        classes.add(org.apache.camel.model.config.StreamResequencerConfig.class);     
+        classes.add(org.apache.camel.model.config.StreamResequencerConfig.class);
         classes.add(org.apache.camel.model.dataformat.DataFormatsDefinition.class);
         classes.add(org.apache.camel.model.language.ExpressionDefinition.class);
         classes.add(org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition.class);
@@ -200,6 +191,7 @@
                 builder.addPropertyValue("onExceptions", factoryBean.getOnExceptions());
                 builder.addPropertyValue("builderRefs", factoryBean.getBuilderRefs());
                 builder.addPropertyValue("properties", factoryBean.getProperties());
+                builder.addPropertyValue("packageScan", factoryBean.getPackageScan());
                 if (factoryBean.getPackages().length > 0) {
                     builder.addPropertyValue("packages", factoryBean.getPackages());
                 }

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/SpringTestSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/SpringTestSupport.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/SpringTestSupport.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/SpringTestSupport.java Wed Jun 17 06:04:52 2009
@@ -16,27 +16,35 @@
  */
 package org.apache.camel.spring;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Route;
+import org.apache.camel.impl.DefaultPackageScanClassResolver;
+import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
+import org.apache.camel.impl.scan.InvertingPackageScanFilter;
 import org.apache.camel.util.ObjectHelper;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
 
 /**
  * @version $Revision$
  */
 public abstract class SpringTestSupport extends ContextTestSupport {
     protected AbstractXmlApplicationContext applicationContext;
-
     protected abstract AbstractXmlApplicationContext createApplicationContext();
 
     @Override
     protected void setUp() throws Exception {
         applicationContext = createApplicationContext();
         assertNotNull("Should have created a valid spring context", applicationContext);
-
         super.setUp();
     }
 
@@ -48,6 +56,67 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    private static class ExcludingPackageScanClassResolver extends DefaultPackageScanClassResolver {
+
+        public void setExcludedClasses(Set<Class> excludedClasses) {
+            excludedClasses = excludedClasses == null ? Collections.EMPTY_SET : excludedClasses;
+            addFilter(new InvertingPackageScanFilter(new AssignableToPackageScanFilter(excludedClasses)));
+        }
+
+    }
+
+    /**
+     * Create a parent context that initializes a
+     * {@link org.apache.camel.spi.PackageScanClassResolver} to exclude a set of given classes from
+     * being resolved. Typically this is used at test time to exclude certain routes,
+     * which might otherwise be just noisy, from being discovered and initialized.
+     * <p/>
+     * To use this filtering mechanism it is necessary to provide the
+     * {@link ApplicationContext} returned from here as the parent context to
+     * your test context e.g.
+     *
+     * <pre>
+     * protected AbstractXmlApplicationContext createApplicationContext() {
+     *     return new ClassPathXmlApplicationContext(new String[] {&quot;test-context.xml&quot;}, getRouteExcludingApplicationContext());
+     * }
+     * </pre>
+     *
+     * This will, in turn, call the template methods <code>excludedRoutes</code>
+     * and <code>excludedRoute</code> to determine the classes to be excluded from scanning.
+     *
+     * @see org.apache.camel.spring.config.scan.SpringComponentScanTest for an example.
+     * @return ApplicationContext a parent {@link ApplicationContext} configured
+     *         to exclude certain classes from package scanning
+     */
+    protected ApplicationContext getRouteExcludingApplicationContext() {
+        GenericApplicationContext routeExcludingContext = new GenericApplicationContext();
+        routeExcludingContext.registerBeanDefinition("excludingResolver", new RootBeanDefinition(ExcludingPackageScanClassResolver.class));
+        routeExcludingContext.refresh();
+
+        ExcludingPackageScanClassResolver excludingResolver = (ExcludingPackageScanClassResolver)routeExcludingContext.getBean("excludingResolver");
+        excludingResolver.setExcludedClasses(new HashSet<Class>(Arrays.asList(excludeRoutes())));
+
+        return routeExcludingContext;
+    }
+
+    /**
+     * Template method used to exclude {@link org.apache.camel.Routes} from the test time context
+     * route scanning
+     *
+     * @return Class[] the classes to be excluded from test time context route scanning
+     */
+    protected Class[] excludeRoutes() {
+        Class excludedRoute = excludeRoute();
+        return excludedRoute != null ? new Class[] {excludedRoute} : new Class[0];
+    }
+
+    /**
+     * Template method used to exclude a {@link org.apache.camel.Routes} from the test camel context
+     */
+    protected Class excludeRoute() {
+        return null;
+    }
 
     /**
      * Looks up the mandatory spring bean of the given name and type, failing if
@@ -85,4 +154,5 @@
     protected CamelContext createCamelContext() throws Exception {
         return SpringCamelContext.springCamelContext(applicationContext);
     }
+
 }

Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java?rev=785479&view=auto
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java (added)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java Wed Jun 17 06:04:52 2009
@@ -0,0 +1,57 @@
+/**
+ * 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.config.scan;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.SpringTestSupport;
+import org.apache.camel.spring.config.scan.route.MyExcludedRouteBuilder;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class RouteExclusionFromWithinSpringTestSupportTest extends SpringTestSupport {
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext(new String[] {"org/apache/camel/spring/config/scan/componentScan.xml"}, getRouteExcludingApplicationContext());
+    }
+
+    public void testRouteExcluded() throws InterruptedException {
+        assertEquals(1, context.getRoutes().size());
+        MockEndpoint mock = getMockEndpoint("mock:definitelyShouldNeverReceiveExchange");
+        mock.expectedMessageCount(0);
+
+        sendBody("direct:shouldNeverRecieveExchange", "dropped like a hot rock");
+        mock.await(500, TimeUnit.MILLISECONDS);
+        mock.assertIsSatisfied();
+    }
+
+    public void testRoutesNotExcludedWorkNormally() throws InterruptedException {
+        template.sendBody("direct:start", "request");
+        MockEndpoint mock = getMockEndpoint("mock:end");
+        mock.expectedMessageCount(1);
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected Class excludeRoute() {
+
+        return MyExcludedRouteBuilder.class;
+    }
+
+}

Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/RouteExclusionFromWithinSpringTestSupportTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanTest.java?rev=785479&r1=785478&r2=785479&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/config/scan/SpringComponentScanTest.java Wed Jun 17 06:04:52 2009
@@ -17,6 +17,8 @@
 
 package org.apache.camel.spring.config.scan;
 
+import java.util.concurrent.TimeUnit;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.component.mock.MockEndpoint;
@@ -33,6 +35,16 @@
         template = context.createProducerTemplate();
 
     }
+    
+    public void testExcludedRoute() throws InterruptedException {
+        assertEquals(1, context.getRoutes().size());
+        MockEndpoint mock = getMockEndpoint("mock:definitelyShouldNeverReceiveExchange");
+        mock.expectedMessageCount(0);
+
+        sendBody("direct:shouldNeverRecieveExchange", "dropped like a hot rock");
+        mock.await(500, TimeUnit.MILLISECONDS);
+        mock.assertIsSatisfied();
+    }
 
     public void testSpringComponentScanFeature() throws InterruptedException {
         template.sendBody("direct:start", "request");