View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.cp;
18  
19  import static java.util.Locale.*;
20  import static org.apache.juneau.commons.utils.CollectionUtils.*;
21  import static org.apache.juneau.commons.utils.StringUtils.*;
22  import static org.apache.juneau.junit.bct.BctAssertions.*;
23  import static org.junit.jupiter.api.Assertions.*;
24  
25  import java.nio.file.*;
26  import java.util.*;
27  
28  import org.apache.juneau.*;
29  import org.apache.juneau.commons.io.*;
30  import org.apache.juneau.cp.sub.*;
31  import org.junit.jupiter.api.*;
32  
33  public class FileFinder_Test extends TestBase {  // NOSONAR - Needs to be public.
34  
35  	private static String read(FileFinder ff, String path) throws Exception {
36  		return toUtf8(ff.getStream(path, null).orElse(null));
37  	}
38  
39  	private static String read(FileFinder ff, String path, Locale locale) throws Exception {
40  		return toUtf8(ff.getStream(path, locale).orElse(null));
41  	}
42  
43  	//-----------------------------------------------------------------------------------------------------------------
44  	// Basic tests.
45  	//-----------------------------------------------------------------------------------------------------------------
46  
47  	@Test void a01_empty() throws Exception {
48  		var x = FileFinder
49  			.create()
50  			.build();
51  
52  		assertNull(read(x,"files/test1a"));
53  	}
54  
55  	//-----------------------------------------------------------------------------------------------------------------
56  	// File system tests.
57  	//-----------------------------------------------------------------------------------------------------------------
58  
59  	@Test void b01_fileSystem_rootDir() throws Exception {
60  		var x = FileFinder
61  			.create()
62  			.dir(".")
63  			.build();
64  
65  		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
66  
67  		for (var p : patterns) {
68  			assertContains("[home:/files/test1/"+p+"]", read(x,"files/test1/"+p));
69  			assertContains("[home:/files/test1/dir/"+p+"]", read(x,"files/test1/dir/"+p));
70  			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x,"files/test1/dir/dir/"+p));
71  			assertContains("[home:/files/test1/"+p+"]", read(x," / files/test1/"+p+" / "));
72  			assertContains("[home:/files/test1/dir/"+p+"]", read(x," / files/test1/dir/"+p+" / "));
73  			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x," / files/test1/dir/dir/"+p+" / "));
74  		}
75  
76  		var badPatterns = a("files/test1/bad.txt","files/test1/../test1/_a.txt","files/test1/%2E%2E/test1/_a.txt","files/bad.txt",null,"",".","..","%2E","%2E%2E","j.class","k.properties");
77  
78  		for (var p : badPatterns) {
79  			assertNull(read(x,p));
80  		}
81  	}
82  
83  	@Test void b02_fileSystem_subDir() throws Exception {
84  		var x = FileFinder
85  			.create()
86  			.dir("files")
87  			.build();
88  
89  		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
90  
91  		for (var p : patterns) {
92  			assertContains("[home:/files/test1/"+p+"]", read(x,"test1/"+p));
93  			assertContains("[home:/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p));
94  			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p));
95  			assertContains("[home:/files/test1/"+p+"]", read(x,"/test1/"+p+"/"));
96  			assertContains("[home:/files/test1/dir/"+p+"]", read(x,"/test1/dir/"+p+"/"));
97  			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x,"/test1/dir/dir/"+p+"/"));
98  		}
99  
100 		var badPatterns = a("test1/bad.txt","test1/../test1/_a.txt","bad.txt",null,"",".","..");
101 
102 		for (var p : badPatterns) {
103 			assertNull(read(x,p));
104 		}
105 	}
106 
107 	@Test void b03_fileSystem_localized_flat() throws Exception {
108 		var x = FileFinder
109 			.create()
110 			.dir("files")
111 			.build();
112 
113 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
114 		var patterns_ja = a("_a_ja.txt","_b_ja",".c",".d_ja.txt","e_ja.txt","f_ja","g_foo_ja.txt","h.foo_ja.txt","i_foo_ja");
115 		var patterns_ja_JP = a("_a_ja_JP.txt","_b_ja_JP",".c",".d_ja_JP.txt","e_ja_JP.txt","f_ja_JP","g_foo_ja_JP.txt","h.foo_ja_JP.txt","i_foo_ja_JP");
116 
117 		for (var i = 0; i < patterns.length; i++) {
118 			var p = patterns[i];
119 			var p_ja = patterns_ja[i];
120 			var p_ja_JP = patterns_ja_JP[i];
121 
122 			assertContains("[home:/files/test1/"+p+"]", read(x,"test1/"+p,null));
123 			assertContains("[home:/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p,null));
124 			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p,null));
125 			assertContains("[home:/files/test1/"+p+"]", read(x,"/test1/"+p+"/",null));
126 			assertContains("[home:/files/test1/dir/"+p+"]", read(x,"/test1/dir/"+p+"/",null));
127 			assertContains("[home:/files/test1/dir/dir/"+p+"]", read(x,"/test1/dir/dir/"+p+"/",null));
128 
129 			assertContains("[home:/files/test1/"+p_ja+"]", read(x,"test1/"+p,JAPANESE));
130 			assertContains("[home:/files/test1/dir/"+p_ja+"]", read(x,"test1/dir/"+p,JAPANESE));
131 			assertContains("[home:/files/test1/dir/dir/"+p_ja+"]", read(x,"test1/dir/dir/"+p,JAPANESE));
132 			assertContains("[home:/files/test1/"+p_ja+"]", read(x,"/test1/"+p+"/",JAPANESE));
133 			assertContains("[home:/files/test1/dir/"+p_ja+"]", read(x,"/test1/dir/"+p+"/",JAPANESE));
134 			assertContains("[home:/files/test1/dir/dir/"+p_ja+"]", read(x,"/test1/dir/dir/"+p+"/",JAPANESE));
135 
136 			assertContains("[home:/files/test1/"+p_ja_JP+"]", read(x,"test1/"+p,JAPAN));
137 			assertContains("[home:/files/test1/dir/"+p_ja_JP+"]", read(x,"test1/dir/"+p,JAPAN));
138 			assertContains("[home:/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"test1/dir/dir/"+p,JAPAN));
139 			assertContains("[home:/files/test1/"+p_ja_JP+"]", read(x,"/test1/"+p+"/",JAPAN));
140 			assertContains("[home:/files/test1/dir/"+p_ja_JP+"]", read(x,"/test1/dir/"+p+"/",JAPAN));
141 			assertContains("[home:/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"/test1/dir/dir/"+p+"/",JAPAN));
142 		}
143 
144 		var badPatterns = a("test1/bad.txt","test1/../test1/_a.txt","bad.txt",null,"",".","..","j.class","k.properties");
145 
146 		for (var p : badPatterns) {
147 			assertNull(read(x,p,null));
148 			assertNull(read(x,p,JAPANESE));
149 			assertNull(read(x,p,JAPAN));
150 		}
151 	}
152 
153 	@Test void b04_fileSystem_localized_hierarchical() throws Exception {
154 		var x = FileFinder
155 			.create()
156 			.dir("files/test2")
157 			.build();
158 
159 		assertContains("[home:/files/test2/a.txt]", read(x,"a.txt", null));
160 		assertContains("[home:/files/test2/ja/a.txt]", read(x,"a.txt", JAPANESE));
161 		assertContains("[home:/files/test2/ja/JP/a.txt]", read(x,"a.txt", JAPAN));
162 		assertContains("[home:/files/test2/a.txt]", read(x,"/a.txt/", null));
163 		assertContains("[home:/files/test2/ja/a.txt]", read(x,"/a.txt/", JAPANESE));
164 		assertContains("[home:/files/test2/ja/JP/a.txt]", read(x,"/a.txt/", JAPAN));
165 
166 		assertContains("[home:/files/test2/dir/a.txt]", read(x,"dir/a.txt", null));
167 		assertContains("[home:/files/test2/ja/dir/a.txt]", read(x,"dir/a.txt", JAPANESE));
168 		assertContains("[home:/files/test2/ja/JP/dir/a.txt]", read(x,"dir/a.txt", JAPAN));
169 		assertContains("[home:/files/test2/dir/a.txt]", read(x,"/dir/a.txt/", null));
170 		assertContains("[home:/files/test2/ja/dir/a.txt]", read(x,"/dir/a.txt/", JAPANESE));
171 		assertContains("[home:/files/test2/ja/JP/dir/a.txt]", read(x,"/dir/a.txt/", JAPAN));
172 
173 		assertContains("[home:/files/test2/dir/dir/a.txt]", read(x,"dir/dir/a.txt", null));
174 		assertContains("[home:/files/test2/ja/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPANESE));
175 		assertContains("[home:/files/test2/ja/JP/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPAN));
176 		assertContains("[home:/files/test2/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", null));
177 		assertContains("[home:/files/test2/ja/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPANESE));
178 		assertContains("[home:/files/test2/ja/JP/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPAN));
179 	}
180 
181 	//-----------------------------------------------------------------------------------------------------------------
182 	// Classpath tests - Classpath root
183 	//-----------------------------------------------------------------------------------------------------------------
184 
185 	@Test void c01_classpathRoot_rootDir() throws Exception {
186 		var x = FileFinder
187 			.create()
188 			.cp(FileFinder_Test.class, "/", false)
189 			.build();
190 
191 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
192 
193 		for (var p : patterns) {
194 			assertContains("[cp:/files/test1/"+p+"]", read(x,"files/test1/"+p));
195 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x,"files/test1/dir/"+p));
196 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x,"files/test1/dir/dir/"+p));
197 			assertContains("[cp:/files/test1/"+p+"]", read(x," / files/test1/"+p+" / "));
198 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x," / files/test1/dir/"+p+" / "));
199 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x," / files/test1/dir/dir/"+p+" / "));
200 		}
201 
202 		var badPatterns = a("files/test1/bad.txt","files/test1/../test1/_a.txt","files/bad.txt",null,"",".","..","LocalizedFileStore_Test.class");
203 
204 		for (var p : badPatterns) {
205 			assertNull(read(x,p));
206 		}
207 	}
208 
209 	@Test void c02_classpathRoot_subdir() throws Exception {
210 		var x = FileFinder
211 			.create()
212 			.cp(FileFinder_Test.class, "/files", false)
213 			.build();
214 
215 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
216 
217 		for (var p : patterns) {
218 			assertContains("[cp:/files/test1/"+p+"]", read(x,"test1/"+p));
219 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p));
220 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p));
221 			assertContains("[cp:/files/test1/"+p+"]", read(x," / test1/"+p+" / "));
222 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x," / test1/dir/"+p+" / "));
223 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x," / test1/dir/dir/"+p+" / "));
224 		}
225 
226 		var badPatterns = a("files/test1/bad.txt","files/test1/../test1/_a.txt","files/bad.txt",null,"",".","..");
227 
228 		for (var p : badPatterns) {
229 			assertNull(read(x,p));
230 		}
231 	}
232 
233 	@Test void c03_classpathRoot_localized_flat() throws Exception {
234 		var x = FileFinder
235 			.create()
236 			.cp(FileFinder_Test.class, "/files", false)
237 			.build();
238 
239 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
240 		var patterns_ja = a("_a_ja.txt","_b_ja",".c",".d_ja.txt","e_ja.txt","f_ja","g_foo_ja.txt","h.foo_ja.txt","i_foo_ja");
241 		var patterns_ja_JP = a("_a_ja_JP.txt","_b_ja_JP",".c",".d_ja_JP.txt","e_ja_JP.txt","f_ja_JP","g_foo_ja_JP.txt","h.foo_ja_JP.txt","i_foo_ja_JP");
242 
243 		for (var i = 0; i < patterns.length; i++) {
244 			var p = patterns[i];
245 			var p_ja = patterns_ja[i];
246 			var p_ja_JP = patterns_ja_JP[i];
247 
248 			assertContains("[cp:/files/test1/"+p+"]", read(x,"test1/"+p,null));
249 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p,null));
250 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p,null));
251 			assertContains("[cp:/files/test1/"+p+"]", read(x,"/test1/"+p+"/",null));
252 			assertContains("[cp:/files/test1/dir/"+p+"]", read(x,"/test1/dir/"+p+"/",null));
253 			assertContains("[cp:/files/test1/dir/dir/"+p+"]", read(x,"/test1/dir/dir/"+p+"/",null));
254 
255 			assertContains("[cp:/files/test1/"+p_ja+"]", read(x,"test1/"+p,JAPANESE));
256 			assertContains("[cp:/files/test1/dir/"+p_ja+"]", read(x,"test1/dir/"+p,JAPANESE));
257 			assertContains("[cp:/files/test1/dir/dir/"+p_ja+"]", read(x,"test1/dir/dir/"+p,JAPANESE));
258 			assertContains("[cp:/files/test1/"+p_ja+"]", read(x,"/test1/"+p+"/",JAPANESE));
259 			assertContains("[cp:/files/test1/dir/"+p_ja+"]", read(x,"/test1/dir/"+p+"/",JAPANESE));
260 			assertContains("[cp:/files/test1/dir/dir/"+p_ja+"]", read(x,"/test1/dir/dir/"+p+"/",JAPANESE));
261 
262 			assertContains("[cp:/files/test1/"+p_ja_JP+"]", read(x,"test1/"+p,JAPAN));
263 			assertContains("[cp:/files/test1/dir/"+p_ja_JP+"]", read(x,"test1/dir/"+p,JAPAN));
264 			assertContains("[cp:/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"test1/dir/dir/"+p,JAPAN));
265 			assertContains("[cp:/files/test1/"+p_ja_JP+"]", read(x,"/test1/"+p+"/",JAPAN));
266 			assertContains("[cp:/files/test1/dir/"+p_ja_JP+"]", read(x,"/test1/dir/"+p+"/",JAPAN));
267 			assertContains("[cp:/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"/test1/dir/dir/"+p+"/",JAPAN));
268 		}
269 
270 		var badPatterns = a("test1/bad.txt","test1/../test1/_a.txt","bad.txt",null,"",".","..");
271 
272 		for (var p : badPatterns) {
273 			assertNull(read(x,p,null));
274 			assertNull(read(x,p,JAPANESE));
275 			assertNull(read(x,p,JAPAN));
276 		}
277 	}
278 
279 	@Test void c04_classpathRoot_localized_hierarchical() throws Exception {
280 		var x = FileFinder
281 			.create()
282 			.cp(FileFinder_Test.class, "/files/test2", false)
283 			.build();
284 
285 		assertContains("[cp:/files/test2/a.txt]", read(x,"a.txt", null));
286 		assertContains("[cp:/files/test2/ja/a.txt]", read(x,"a.txt", JAPANESE));
287 		assertContains("[cp:/files/test2/ja/JP/a.txt]", read(x,"a.txt", JAPAN));
288 		assertContains("[cp:/files/test2/a.txt]", read(x,"/a.txt/", null));
289 		assertContains("[cp:/files/test2/ja/a.txt]", read(x,"/a.txt/", JAPANESE));
290 		assertContains("[cp:/files/test2/ja/JP/a.txt]", read(x,"/a.txt/", JAPAN));
291 
292 		assertContains("[cp:/files/test2/dir/a.txt]", read(x,"dir/a.txt", null));
293 		assertContains("[cp:/files/test2/ja/dir/a.txt]", read(x,"dir/a.txt", JAPANESE));
294 		assertContains("[cp:/files/test2/ja/JP/dir/a.txt]", read(x,"dir/a.txt", JAPAN));
295 		assertContains("[cp:/files/test2/dir/a.txt]", read(x,"/dir/a.txt/", null));
296 		assertContains("[cp:/files/test2/ja/dir/a.txt]", read(x,"/dir/a.txt/", JAPANESE));
297 		assertContains("[cp:/files/test2/ja/JP/dir/a.txt]", read(x,"/dir/a.txt/", JAPAN));
298 
299 		assertContains("[cp:/files/test2/dir/dir/a.txt]", read(x,"dir/dir/a.txt", null));
300 		assertContains("[cp:/files/test2/ja/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPANESE));
301 		assertContains("[cp:/files/test2/ja/JP/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPAN));
302 		assertContains("[cp:/files/test2/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", null));
303 		assertContains("[cp:/files/test2/ja/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPANESE));
304 		assertContains("[cp:/files/test2/ja/JP/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPAN));
305 	}
306 
307 	//-----------------------------------------------------------------------------------------------------------------
308 	// Classpath tests - Classpath relative
309 	//-----------------------------------------------------------------------------------------------------------------
310 
311 	@Test void d01a_classpathRelative_rootDir() throws Exception {
312 		var x = FileFinder
313 			.create()
314 			.cp(FileFinder_Test.class, "", false)
315 			.build();
316 
317 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
318 
319 		for (var p : patterns) {
320 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"files/test1/"+p));
321 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"files/test1/dir/"+p));
322 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"files/test1/dir/dir/"+p));
323 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x," / files/test1/"+p+" / "));
324 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x," / files/test1/dir/"+p+" / "));
325 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x," / files/test1/dir/dir/"+p+" / "));
326 		}
327 
328 		assertContains("[cp:/org/apache/juneau/cp/_a.txt]", read(x,"_a.txt"));
329 
330 		var badPatterns = a("files/test1/bad.txt","files/test1/../test1/_a.txt","files/bad.txt",null,"",".","..");
331 
332 		for (var p : badPatterns) {
333 			assertNull(read(x,p));
334 		}
335 	}
336 
337 	@Test void d01b_classpathRelative_rootDir_recursive() throws Exception {
338 		var x = FileFinder
339 			.create()
340 			.cp(FileFinder_Test2.class, "", true)
341 			.build();
342 
343 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
344 
345 		for (var p : patterns) {
346 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"files/test1/"+p));
347 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"files/test1/dir/"+p));
348 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"files/test1/dir/dir/"+p));
349 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x," / files/test1/"+p+" / "));
350 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x," / files/test1/dir/"+p+" / "));
351 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x," / files/test1/dir/dir/"+p+" / "));
352 		}
353 	}
354 
355 	@Test void d02a_classpathRelative_subdir() throws Exception {
356 		var x = FileFinder
357 			.create()
358 			.cp(FileFinder_Test.class, "files", false)
359 			.build();
360 
361 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
362 
363 		for (var p : patterns) {
364 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"test1/"+p));
365 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p));
366 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p));
367 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x," / test1/"+p+" / "));
368 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x," / test1/dir/"+p+" / "));
369 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x," / test1/dir/dir/"+p+" / "));
370 		}
371 
372 		var badPatterns = a("files/test1/bad.txt","files/test1/../test1/_a.txt","files/bad.txt",null,"",".","..");
373 
374 		for (var p : badPatterns) {
375 			assertNull(read(x,p));
376 		}
377 	}
378 
379 	@Test void d02b_classpathRelative_subdir_recursive() throws Exception {
380 		var x = FileFinder
381 			.create()
382 			.cp(FileFinder_Test2.class, "files", true)
383 			.build();
384 
385 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
386 
387 		for (var p : patterns) {
388 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"test1/"+p));
389 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p));
390 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p));
391 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x," / test1/"+p+" / "));
392 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x," / test1/dir/"+p+" / "));
393 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x," / test1/dir/dir/"+p+" / "));
394 		}
395 	}
396 
397 	@Test void d03a_classpathRelative_localized_flat() throws Exception {
398 		var x = FileFinder
399 			.create()
400 			.cp(FileFinder_Test.class, "files", false)
401 			.build();
402 
403 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
404 		var patterns_ja = a("_a_ja.txt","_b_ja",".c",".d_ja.txt","e_ja.txt","f_ja","g_foo_ja.txt","h.foo_ja.txt","i_foo_ja");
405 		var patterns_ja_JP = a("_a_ja_JP.txt","_b_ja_JP",".c",".d_ja_JP.txt","e_ja_JP.txt","f_ja_JP","g_foo_ja_JP.txt","h.foo_ja_JP.txt","i_foo_ja_JP");
406 
407 		for (var i = 0; i < patterns.length; i++) {
408 			var p = patterns[i];
409 			var p_ja = patterns_ja[i];
410 			var p_ja_JP = patterns_ja_JP[i];
411 
412 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"test1/"+p,null));
413 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p,null));
414 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p,null));
415 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"/test1/"+p+"/",null));
416 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"/test1/dir/"+p+"/",null));
417 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"/test1/dir/dir/"+p+"/",null));
418 
419 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja+"]", read(x,"test1/"+p,JAPANESE));
420 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja+"]", read(x,"test1/dir/"+p,JAPANESE));
421 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja+"]", read(x,"test1/dir/dir/"+p,JAPANESE));
422 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja+"]", read(x,"/test1/"+p+"/",JAPANESE));
423 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja+"]", read(x,"/test1/dir/"+p+"/",JAPANESE));
424 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja+"]", read(x,"/test1/dir/dir/"+p+"/",JAPANESE));
425 
426 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja_JP+"]", read(x,"test1/"+p,JAPAN));
427 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja_JP+"]", read(x,"test1/dir/"+p,JAPAN));
428 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"test1/dir/dir/"+p,JAPAN));
429 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja_JP+"]", read(x,"/test1/"+p+"/",JAPAN));
430 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja_JP+"]", read(x,"/test1/dir/"+p+"/",JAPAN));
431 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"/test1/dir/dir/"+p+"/",JAPAN));
432 		}
433 
434 		var badPatterns = a("test1/bad.txt","test1/../test1/_a.txt","bad.txt",null,"",".","..");
435 
436 		for (var p : badPatterns) {
437 			assertNull(read(x,p,null));
438 			assertNull(read(x,p,JAPANESE));
439 			assertNull(read(x,p,JAPAN));
440 		}
441 	}
442 
443 	@Test void d03b_classpathRelative_localized_flat_recursive() throws Exception {
444 		var x = FileFinder
445 			.create()
446 			.cp(FileFinder_Test2.class, "files", true)
447 			.build();
448 
449 		var patterns = a("_a.txt","_b",".c",".d.txt","e.txt","f","g_foo.txt","h.foo.txt","i_foo");
450 		var patterns_ja = a("_a_ja.txt","_b_ja",".c",".d_ja.txt","e_ja.txt","f_ja","g_foo_ja.txt","h.foo_ja.txt","i_foo_ja");
451 		var patterns_ja_JP = a("_a_ja_JP.txt","_b_ja_JP",".c",".d_ja_JP.txt","e_ja_JP.txt","f_ja_JP","g_foo_ja_JP.txt","h.foo_ja_JP.txt","i_foo_ja_JP");
452 
453 		for (var i = 0; i < patterns.length; i++) {
454 			var p = patterns[i];
455 			var p_ja = patterns_ja[i];
456 			var p_ja_JP = patterns_ja_JP[i];
457 
458 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"test1/"+p,null));
459 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"test1/dir/"+p,null));
460 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"test1/dir/dir/"+p,null));
461 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p+"]", read(x,"/test1/"+p+"/",null));
462 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p+"]", read(x,"/test1/dir/"+p+"/",null));
463 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p+"]", read(x,"/test1/dir/dir/"+p+"/",null));
464 
465 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja+"]", read(x,"test1/"+p,JAPANESE));
466 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja+"]", read(x,"test1/dir/"+p,JAPANESE));
467 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja+"]", read(x,"test1/dir/dir/"+p,JAPANESE));
468 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja+"]", read(x,"/test1/"+p+"/",JAPANESE));
469 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja+"]", read(x,"/test1/dir/"+p+"/",JAPANESE));
470 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja+"]", read(x,"/test1/dir/dir/"+p+"/",JAPANESE));
471 
472 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja_JP+"]", read(x,"test1/"+p,JAPAN));
473 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja_JP+"]", read(x,"test1/dir/"+p,JAPAN));
474 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"test1/dir/dir/"+p,JAPAN));
475 			assertContains("[cp:/org/apache/juneau/cp/files/test1/"+p_ja_JP+"]", read(x,"/test1/"+p+"/",JAPAN));
476 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/"+p_ja_JP+"]", read(x,"/test1/dir/"+p+"/",JAPAN));
477 			assertContains("[cp:/org/apache/juneau/cp/files/test1/dir/dir/"+p_ja_JP+"]", read(x,"/test1/dir/dir/"+p+"/",JAPAN));
478 		}
479 	}
480 
481 	@Test void d04a_classpathRelative_localized_hierarchical() throws Exception {
482 		var x = FileFinder
483 			.create()
484 			.cp(FileFinder_Test.class, "files/test2", false)
485 			.build();
486 
487 		assertContains("[cp:/org/apache/juneau/cp/files/test2/a.txt]", read(x,"a.txt", null));
488 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/a.txt]", read(x,"a.txt", JAPANESE));
489 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/a.txt]", read(x,"a.txt", JAPAN));
490 		assertContains("[cp:/org/apache/juneau/cp/files/test2/a.txt]", read(x,"/a.txt/", null));
491 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/a.txt]", read(x,"/a.txt/", JAPANESE));
492 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/a.txt]", read(x,"/a.txt/", JAPAN));
493 
494 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/a.txt]", read(x,"dir/a.txt", null));
495 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/a.txt]", read(x,"dir/a.txt", JAPANESE));
496 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/a.txt]", read(x,"dir/a.txt", JAPAN));
497 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/a.txt]", read(x,"/dir/a.txt/", null));
498 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/a.txt]", read(x,"/dir/a.txt/", JAPANESE));
499 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/a.txt]", read(x,"/dir/a.txt/", JAPAN));
500 
501 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/dir/a.txt]", read(x,"dir/dir/a.txt", null));
502 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPANESE));
503 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPAN));
504 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", null));
505 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPANESE));
506 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPAN));
507 	}
508 
509 	@Test void d04b_classpathRelative_localized_hierarchical_recursive() throws Exception {
510 		var x = FileFinder
511 			.create()
512 			.cp(FileFinder_Test2.class, "files/test2", true)
513 			.build();
514 
515 		assertContains("[cp:/org/apache/juneau/cp/files/test2/a.txt]", read(x,"a.txt", null));
516 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/a.txt]", read(x,"a.txt", JAPANESE));
517 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/a.txt]", read(x,"a.txt", JAPAN));
518 		assertContains("[cp:/org/apache/juneau/cp/files/test2/a.txt]", read(x,"/a.txt/", null));
519 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/a.txt]", read(x,"/a.txt/", JAPANESE));
520 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/a.txt]", read(x,"/a.txt/", JAPAN));
521 
522 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/a.txt]", read(x,"dir/a.txt", null));
523 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/a.txt]", read(x,"dir/a.txt", JAPANESE));
524 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/a.txt]", read(x,"dir/a.txt", JAPAN));
525 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/a.txt]", read(x,"/dir/a.txt/", null));
526 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/a.txt]", read(x,"/dir/a.txt/", JAPANESE));
527 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/a.txt]", read(x,"/dir/a.txt/", JAPAN));
528 
529 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/dir/a.txt]", read(x,"dir/dir/a.txt", null));
530 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPANESE));
531 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPAN));
532 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", null));
533 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPANESE));
534 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/dir/a.txt]", read(x,"/dir/dir/a.txt/", JAPAN));
535 
536 		FileFinder
537 			.create()
538 			.cp(FileFinder_Test2.class, "files/test2", true)
539 			.exclude("(?i).*\\.(class|properties)")
540 			.build();
541 	}
542 
543 	@Test void d05_classpathRelative_ignorePattern() throws Exception {
544 		var x = FileFinder
545 			.create()
546 			.cp(FileFinder_Test2.class, "files/test2", true)
547 			.exclude("(?i).*\\.(txt)")
548 			.build();
549 
550 		assertNull(read(x,"a.txt", null));
551 		assertNull(read(x,"a.txt", JAPANESE));
552 		assertNull(read(x,"a.txt", JAPAN));
553 
554 		assertNull(read(x,"dir/a.txt", null));
555 		assertNull(read(x,"dir/a.txt", JAPANESE));
556 		assertNull(read(x,"dir/a.txt", JAPAN));
557 
558 		assertNull(read(x,"dir/dir/a.txt", null));
559 		assertNull(read(x,"dir/dir/a.txt", JAPANESE));
560 		assertNull(read(x,"dir/dir/a.txt", JAPAN));
561 
562 		x = FileFinder
563 			.create()
564 			.cp(FileFinder_Test2.class, "files/test2", true)
565 			.exclude("(?i).*\\.(TXT)")
566 			.build();
567 
568 		assertNull(read(x,"a.txt", null));
569 		assertNull(read(x,"a.txt", JAPANESE));
570 		assertNull(read(x,"a.txt", JAPAN));
571 
572 		assertNull(read(x,"dir/a.txt", null));
573 		assertNull(read(x,"dir/a.txt", JAPANESE));
574 		assertNull(read(x,"dir/a.txt", JAPAN));
575 
576 		assertNull(read(x,"dir/dir/a.txt", null));
577 		assertNull(read(x,"dir/dir/a.txt", JAPANESE));
578 		assertNull(read(x,"dir/dir/a.txt", JAPAN));
579 
580 		x = FileFinder
581 			.create()
582 			.cp(FileFinder_Test2.class, "files/test2", true)
583 			.exclude()
584 			.build();
585 
586 		assertContains("[cp:/org/apache/juneau/cp/files/test2/a.txt]", read(x,"a.txt", null));
587 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/a.txt]", read(x,"a.txt", JAPANESE));
588 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/a.txt]", read(x,"a.txt", JAPAN));
589 
590 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/a.txt]", read(x,"dir/a.txt", null));
591 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/a.txt]", read(x,"dir/a.txt", JAPANESE));
592 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/a.txt]", read(x,"dir/a.txt", JAPAN));
593 
594 		assertContains("[cp:/org/apache/juneau/cp/files/test2/dir/dir/a.txt]", read(x,"dir/dir/a.txt", null));
595 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPANESE));
596 		assertContains("[cp:/org/apache/juneau/cp/files/test2/ja/JP/dir/dir/a.txt]", read(x,"dir/dir/a.txt", JAPAN));
597 	}
598 
599 	//-----------------------------------------------------------------------------------------------------------------
600 	// Other tests
601 	//-----------------------------------------------------------------------------------------------------------------
602 
603 	@Test void e01_localDir_hashCode() {
604 		var s = set(new LocalDir(Paths.get("test")), new LocalDir(Paths.get("test")));
605 		assertSize(1, s);
606 
607 		s = set(new LocalDir(Paths.get("test")), new LocalDir(Paths.get("test","test")));
608 		assertSize(2, s);
609 
610 		s = set(new LocalDir(List.class,null), new LocalDir(List.class,null));
611 		assertSize(1, s);
612 
613 		s = set(new LocalDir(List.class,null), new LocalDir(List.class,"foo"));
614 		assertSize(2, s);
615 
616 		s = set(new LocalDir(List.class,null), new LocalDir(String.class,null));
617 		assertSize(2, s);
618 	}
619 
620 	@Test void e02_caching() throws Exception {
621 		var x = FileFinder
622 			.create()
623 			.dir(".")
624 			.caching(100_000_000)
625 			.build();
626 
627 		assertContains("[home:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
628 		assertContains("[home:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
629 
630 		x = FileFinder
631 			.create()
632 			.dir(".")
633 			.caching(1)
634 			.build();
635 
636 		assertContains("[home:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
637 		assertContains("[home:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
638 
639 		x = FileFinder
640 			.create()
641 			.cp(FileFinder_Test.class, "/", false)
642 			.caching(100_000_000)
643 			.build();
644 
645 		assertContains("[cp:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
646 		assertContains("[cp:/files/test1/_a.txt]", read(x,"files/test1/_a.txt"));
647 	}
648 
649 	@Test void e03_subclassing() {
650 		var x = E03b
651 			.create()
652 			.dir(".")
653 			.caching(100_000_000)
654 			.type(E03b.class)
655 			.build();
656 		assertInstanceOf(E03b.class, x);
657 	}
658 
659 	public static class E03a extends FileFinder.Builder {
660 		protected E03a() {
661 			super(BeanStore.INSTANCE);
662 		}
663 	}
664 	public static class E03b extends BasicFileFinder {
665 		public static E03a create() {
666 			return new E03a();
667 		}
668 		public E03b(E03a x) {
669 			super(x);
670 		}
671 	}
672 }