001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.impl.scan;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import org.apache.camel.spi.PackageScanFilter;
024    import org.springframework.util.AntPathMatcher;
025    
026    /**
027     * <code>PatternBasedPackageScanFilter</code> uses an underlying
028     * {@link AntPathMatcher} to filter scanned files according to include and
029     * exclude patterns.
030     * 
031     * @see AntPathMatcher
032     */
033    public class PatternBasedPackageScanFilter implements PackageScanFilter {
034        private AntPathMatcher matcher = new AntPathMatcher();
035    
036        private List<String> excludePatterns;
037        private List<String> includePatterns;
038    
039        /**
040         * add and exclude pattern to the filter. Classes matching this pattern will
041         * not match the filter 
042         * 
043         * @param excludePattern
044         */
045        public void addExcludePattern(String excludePattern) {
046            if (excludePatterns == null) {
047                excludePatterns = new ArrayList<String>();
048            }
049            excludePatterns.add(excludePattern);
050        }
051    
052        /**
053         * add and include pattern to the filter. Classes must match one of supplied
054         * include patterns to match the filter 
055         * 
056         * @param includePattern
057         */
058        public void addIncludePattern(String includePattern) {
059            if (includePatterns == null) {
060                includePatterns = new ArrayList<String>();
061            }
062            includePatterns.add(includePattern);
063        }
064        
065        public void addIncludePatterns(Collection<String> includes) {
066            if (includePatterns == null) {
067                includePatterns = new ArrayList<String>();
068            }
069            includePatterns.addAll(includes);
070        }
071        
072        public void addExcludePatterns(Collection<String> excludes) {
073            if (excludePatterns == null) {
074                excludePatterns = new ArrayList<String>();
075            }
076            excludePatterns.addAll(excludes);
077        }
078    
079        /**
080         * Tests if a given class matches the patterns in this filter. Patterns are
081         * specified by {@link AntPathMatcher}
082         * <p>
083         * if no include or exclude patterns are set then all classes match.
084         * <p>
085         * If the filter contains only include filters, then the candidate class
086         * must match one of the include patterns to match the filter and return
087         * true.
088         * <p>
089         * If the filter contains only exclude filters, then the filter will return
090         * true unless the candidate class matches an exclude pattern.
091         * <p>
092         * if this contains both include and exclude filters, then the above rules
093         * apply with excludes taking precedence over includes i.e. an include
094         * pattern of java.util.* and an exclude pattern of java.util.jar.* will
095         * include a file only if it is in the util pkg and not in the util.jar
096         * package.
097         * 
098         * @return true if candidate class matches according to the above rules
099         */
100        public boolean matches(Class candidateClass) {
101            String candidate = candidateClass.getName();
102            if (includePatterns != null || excludePatterns != null) {
103    
104                if (excludePatterns != null && excludePatterns.size() > 0) {
105                    if (matchesAny(excludePatterns, candidate)) {
106                        return false;
107                    }
108                }
109    
110                if (includePatterns != null && includePatterns.size() > 0) {
111                    return matchesAny(includePatterns, candidate);
112                }
113    
114            }
115            return true;
116        }
117    
118        private boolean matchesAny(List<String> patterns, String candidate) {
119            for (String pattern : patterns) {
120                if (matcher.match(pattern, candidate)) {
121                    return true;
122                }
123            }
124            return false;
125        }
126    
127    }