1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.start;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.FileSystem;
24 import java.nio.file.FileSystems;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.PathMatcher;
28
29
30
31
32 public class PathMatchers
33 {
34 private static class NonHiddenMatcher implements PathMatcher
35 {
36 @Override
37 public boolean matches(Path path)
38 {
39 try
40 {
41 return !Files.isHidden(path);
42 }
43 catch (IOException e)
44 {
45 StartLog.debug(e);
46 return false;
47 }
48 }
49 }
50
51 private static final char GLOB_CHARS[] = "*?".toCharArray();
52 private static final char SYNTAXED_GLOB_CHARS[] = "{}[]|:".toCharArray();
53 private static final Path EMPTY_PATH = new File(".").toPath();
54
55
56
57
58
59
60
61
62 private static Path asPath(final String pattern)
63 {
64 String test = pattern;
65 if (test.startsWith("glob:"))
66 {
67 test = test.substring("glob:".length());
68 }
69 else if (test.startsWith("regex:"))
70 {
71 test = test.substring("regex:".length());
72 }
73 return new File(test).toPath();
74 }
75
76 public static PathMatcher getMatcher(final String rawpattern)
77 {
78 FileSystem fs = FileSystems.getDefault();
79
80 String pattern = rawpattern;
81
82
83 int lastchar = pattern.charAt(pattern.length() - 1);
84 if (lastchar == '/' || lastchar == '\\')
85 {
86 pattern = pattern.substring(0,pattern.length() - 1);
87 }
88
89
90
91 if (pattern.startsWith("glob:") || pattern.startsWith("regex:"))
92 {
93 StartLog.debug("Using Standard " + fs.getClass().getName() + " pattern: " + pattern);
94 return fs.getPathMatcher(pattern);
95 }
96
97
98
99 if (isAbsolute(pattern))
100 {
101 String pat = "glob:" + pattern;
102 StartLog.debug("Using absolute path pattern: " + pat);
103 return fs.getPathMatcher(pat);
104 }
105
106
107
108 String pat = "glob:**/" + pattern;
109 StartLog.debug("Using relative path pattern: " + pat);
110 return fs.getPathMatcher(pat);
111 }
112
113 public static PathMatcher getNonHidden()
114 {
115 return new NonHiddenMatcher();
116 }
117
118
119
120
121
122
123
124
125 public static Path getSearchRoot(final String pattern)
126 {
127 StringBuilder root = new StringBuilder();
128
129 int start = 0;
130 boolean syntaxed = false;
131 if (pattern.startsWith("glob:"))
132 {
133 start = "glob:".length();
134 syntaxed = true;
135 }
136 else if (pattern.startsWith("regex:"))
137 {
138 start = "regex:".length();
139 syntaxed = true;
140 }
141 int len = pattern.length();
142 int lastSep = 0;
143 for (int i = start; i < len; i++)
144 {
145 int cp = pattern.codePointAt(i);
146 if (cp < 127)
147 {
148 char c = (char)cp;
149
150
151 if (c == '/')
152 {
153 root.append(c);
154 lastSep = root.length();
155 }
156 else if (c == '\\')
157 {
158 root.append("\\");
159 lastSep = root.length();
160
161
162
163 int count = countChars(pattern,i+1,'\\');
164 if (count > 0)
165 {
166
167 i += count;
168 }
169 }
170 else
171 {
172 if (isGlob(c,syntaxed))
173 {
174 break;
175 }
176 root.append(c);
177 }
178 }
179 else
180 {
181 root.appendCodePoint(cp);
182 }
183 }
184
185 String rootPath = root.substring(0,lastSep);
186 if (rootPath.length() <= 0)
187 {
188 return EMPTY_PATH;
189 }
190
191 return asPath(rootPath);
192 }
193
194 private static int countChars(String pattern, int offset, char c)
195 {
196 int count = 0;
197 int len = pattern.length();
198 for (int i = offset; i < len; i++)
199 {
200 if (pattern.charAt(i) == c)
201 {
202 count++;
203 }
204 else
205 {
206 break;
207 }
208 }
209 return count;
210 }
211
212
213
214
215
216
217
218
219 public static boolean isAbsolute(final String pattern)
220 {
221 Path searchRoot = getSearchRoot(pattern);
222 if (searchRoot == EMPTY_PATH)
223 {
224 return false;
225 }
226 return searchRoot.isAbsolute();
227 }
228
229
230
231
232
233
234
235
236
237
238 private static boolean isGlob(char c, boolean syntaxed)
239 {
240 for (char g : GLOB_CHARS)
241 {
242 if (c == g)
243 {
244 return true;
245 }
246 }
247 if (syntaxed)
248 {
249 for (char g : SYNTAXED_GLOB_CHARS)
250 {
251 if (c == g)
252 {
253 return true;
254 }
255 }
256 }
257 return false;
258 }
259 }