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