Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
FilePatternMatcher |
|
| 4.0;4 |
1 | /* | |
2 | StatCvs - CVS statistics generation | |
3 | Copyright (C) 2002 Lukasz Pekacki <lukasz@pekacki.de> | |
4 | http://statcvs.sf.net/ | |
5 | | |
6 | This library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | This library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
17 | License along with this library; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | | |
20 | $RCSfile: FilePatternMatcher.java,v $ | |
21 | $Date: 2008/04/02 11:22:15 $ | |
22 | */ | |
23 | package net.sf.statcvs.util; | |
24 | ||
25 | import java.util.ArrayList; | |
26 | import java.util.Iterator; | |
27 | import java.util.List; | |
28 | import java.util.StringTokenizer; | |
29 | import java.util.regex.Pattern; | |
30 | ||
31 | /** | |
32 | * <p>Matches filenames against an Ant-style wildcard pattern list.</p> | |
33 | * | |
34 | * <p>In short, ? matches one character, * matches zero or more characters | |
35 | * but no directory changes (it doesn't match / or \), and ** | |
36 | * matches zero or more directory levels. If the wildcard pattern | |
37 | * ends in / or \, an implicit ** is added.</p> | |
38 | * | |
39 | * <p>Several patterns can be specified, seperated by : or ;.</p> | |
40 | * | |
41 | * <p>Everything is case sensitive. If you need case insensitive pattern | |
42 | * matching, use <tt>String.toLower()</tt> on the pattern and on the | |
43 | * candidate string.</p> | |
44 | * | |
45 | * @author Richard Cyganiak <rcyg@gmx.de> | |
46 | * @version $Id: FilePatternMatcher.java,v 1.3 2008/04/02 11:22:15 benoitx Exp $ | |
47 | */ | |
48 | public class FilePatternMatcher { | |
49 | private final String originalPattern; | |
50 | 128 | private final List patterns = new ArrayList(); |
51 | ||
52 | /** | |
53 | * Creates a matcher to match filenames against a specified | |
54 | * wildcard pattern | |
55 | * @param wildcardPattern an Ant-style wildcard pattern | |
56 | */ | |
57 | 128 | public FilePatternMatcher(final String wildcardPattern) { |
58 | 128 | this.originalPattern = wildcardPattern; |
59 | 128 | final StringTokenizer tokenizer = new StringTokenizer(wildcardPattern, ":;"); |
60 | 288 | while (tokenizer.hasMoreTokens()) { |
61 | 160 | patterns.add(Pattern.compile(buildRegex(tokenizer.nextToken()))); |
62 | } | |
63 | 128 | } |
64 | ||
65 | /** | |
66 | * Matches a filename against the wildcard pattern. | |
67 | * @param filename a filename | |
68 | * @return <tt>true</tt> if the filename matches the pattern | |
69 | */ | |
70 | public boolean matches(final String filename) { | |
71 | 728 | final Iterator it = patterns.iterator(); |
72 | 1224 | while (it.hasNext()) { |
73 | 840 | final Pattern regex = (Pattern) it.next(); |
74 | 840 | if (regex.matcher(filename).matches()) { |
75 | 344 | return true; |
76 | } | |
77 | 434 | } |
78 | 384 | return false; |
79 | } | |
80 | ||
81 | private String buildRegex(final String wildcardPattern) { | |
82 | 160 | String temp = wildcardPattern; |
83 | 160 | temp = temp.replace('\\', '/'); |
84 | 160 | if (temp.endsWith("/")) { |
85 | 16 | temp += "**"; |
86 | } | |
87 | // replace **/** with ** | |
88 | 160 | temp = temp.replaceAll("\\*\\*/\\*\\*", "**"); |
89 | 160 | if ("**".equals(temp)) { |
90 | 0 | return ".*"; |
91 | } | |
92 | // replace **/ at start with (.*/)? and /** at end with (/.*)? | |
93 | 160 | if (temp.startsWith("**/") && temp.endsWith("/**")) { |
94 | 8 | final String inner = temp.substring(3, temp.length() - 3); |
95 | 8 | return "(.*/)?" + buildInnerRegex(inner) + "(/.*)?"; |
96 | } | |
97 | 152 | if (temp.startsWith("**/")) { |
98 | 8 | final String inner = temp.substring(3); |
99 | 8 | return "(.*/)?" + buildInnerRegex(inner); |
100 | } | |
101 | 144 | if (temp.endsWith("/**")) { |
102 | 16 | final String inner = temp.substring(0, temp.length() - 3); |
103 | 16 | return buildInnerRegex(inner) + "(/.*)?"; |
104 | } | |
105 | 128 | return buildInnerRegex(temp); |
106 | } | |
107 | ||
108 | private String buildInnerRegex(final String wildcardPattern) { | |
109 | // replace /**/ with /(.*/)? | |
110 | 192 | final int pos = wildcardPattern.indexOf("/**/"); |
111 | 192 | if (pos > -1) { |
112 | 16 | final String before = wildcardPattern.substring(0, pos); |
113 | 16 | final String after = wildcardPattern.substring(pos + 4); |
114 | 16 | return buildInnerRegex(before) + "/(.*/)?" + buildInnerRegex(after); |
115 | } | |
116 | // replace ? with [^/] and * with [^/]* | |
117 | 176 | return wildcardPattern.replaceAll("\\?", "[^/]").replaceAll("\\*", "[^/]*"); |
118 | } | |
119 | ||
120 | public String toString() { | |
121 | 0 | return this.originalPattern; |
122 | } | |
123 | } |