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.core.xml.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    
025    /**
026     * <code>PatternBasedPackageScanFilter</code> uses an underlying
027     * {@link AntPathMatcher} to filter scanned files according to include and
028     * exclude patterns.
029     * 
030     * @see AntPathMatcher
031     */
032    public class PatternBasedPackageScanFilter implements PackageScanFilter {
033        private AntPathMatcher matcher = new AntPathMatcher();
034    
035        private List<String> excludePatterns;
036        private List<String> includePatterns;
037    
038        /**
039         * add and exclude pattern to the filter. Classes matching this pattern will
040         * not match the filter 
041         * 
042         * @param excludePattern
043         */
044        public void addExcludePattern(String excludePattern) {
045            if (excludePatterns == null) {
046                excludePatterns = new ArrayList<String>();
047            }
048            excludePatterns.add(excludePattern);
049        }
050    
051        /**
052         * add and include pattern to the filter. Classes must match one of supplied
053         * include patterns to match the filter 
054         * 
055         * @param includePattern
056         */
057        public void addIncludePattern(String includePattern) {
058            if (includePatterns == null) {
059                includePatterns = new ArrayList<String>();
060            }
061            includePatterns.add(includePattern);
062        }
063        
064        public void addIncludePatterns(Collection<String> includes) {
065            if (includePatterns == null) {
066                includePatterns = new ArrayList<String>();
067            }
068            includePatterns.addAll(includes);
069        }
070        
071        public void addExcludePatterns(Collection<String> excludes) {
072            if (excludePatterns == null) {
073                excludePatterns = new ArrayList<String>();
074            }
075            excludePatterns.addAll(excludes);
076        }
077    
078        /**
079         * Tests if a given class matches the patterns in this filter. Patterns are
080         * specified by {@link AntPathMatcher}
081         * <p>
082         * if no include or exclude patterns are set then all classes match.
083         * <p>
084         * If the filter contains only include filters, then the candidate class
085         * must match one of the include patterns to match the filter and return
086         * true.
087         * <p>
088         * If the filter contains only exclude filters, then the filter will return
089         * true unless the candidate class matches an exclude pattern.
090         * <p>
091         * if this contains both include and exclude filters, then the above rules
092         * apply with excludes taking precedence over includes i.e. an include
093         * pattern of java.util.* and an exclude pattern of java.util.jar.* will
094         * include a file only if it is in the util pkg and not in the util.jar
095         * package.
096         * 
097         * @return true if candidate class matches according to the above rules
098         */
099        public boolean matches(Class<?> candidateClass) {
100            String candidate = candidateClass.getName();
101            if (includePatterns != null || excludePatterns != null) {
102    
103                if (excludePatterns != null && excludePatterns.size() > 0) {
104                    if (matchesAny(excludePatterns, candidate)) {
105                        return false;
106                    }
107                }
108    
109                if (includePatterns != null && includePatterns.size() > 0) {
110                    return matchesAny(includePatterns, candidate);
111                }
112    
113            }
114            return true;
115        }
116    
117        private boolean matchesAny(List<String> patterns, String candidate) {
118            for (String pattern : patterns) {
119                if (matcher.match(pattern, candidate)) {
120                    return true;
121                }
122            }
123            return false;
124        }
125    
126    }