Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ClassLoaderResourceLoader |
|
| 3.0;3 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.myfaces.shared.resource; | |
20 | ||
21 | import java.io.InputStream; | |
22 | import java.net.URL; | |
23 | ||
24 | import org.apache.myfaces.shared.util.ClassUtils; | |
25 | ||
26 | /** | |
27 | * A resource loader implementation which loads resources from the thread ClassLoader. | |
28 | * | |
29 | */ | |
30 | public class ClassLoaderResourceLoader extends ResourceLoader | |
31 | { | |
32 | /** | |
33 | * It checks version like this: 1, 1_0, 1_0_0, 100_100 | |
34 | * | |
35 | * Used on getLibraryVersion to filter resource directories | |
36 | **/ | |
37 | //protected static Pattern VERSION_CHECKER = Pattern.compile("\\p{Digit}+(_\\p{Digit}*)*"); | |
38 | ||
39 | /** | |
40 | * It checks version like this: /1.js, /1_0.js, /1_0_0.js, /100_100.js | |
41 | * | |
42 | * Used on getResourceVersion to filter resources | |
43 | **/ | |
44 | //protected static Pattern RESOURCE_VERSION_CHECKER = Pattern.compile("/\\p{Digit}+(_\\p{Digit}*)*\\..*"); | |
45 | ||
46 | /* | |
47 | private FileFilter _libraryFileFilter = new FileFilter() | |
48 | { | |
49 | public boolean accept(File pathname) | |
50 | { | |
51 | if (pathname.isDirectory() && VERSION_CHECKER.matcher(pathname.getName()).matches()) | |
52 | { | |
53 | return true; | |
54 | } | |
55 | return false; | |
56 | } | |
57 | };*/ | |
58 | ||
59 | /* | |
60 | private FileFilter _resourceFileFilter = new FileFilter() | |
61 | { | |
62 | public boolean accept(File pathname) | |
63 | { | |
64 | if (pathname.isDirectory() && RESOURCE_VERSION_CHECKER.matcher(pathname.getName()).matches()) | |
65 | { | |
66 | return true; | |
67 | } | |
68 | return false; | |
69 | } | |
70 | };*/ | |
71 | ||
72 | public ClassLoaderResourceLoader(String prefix) | |
73 | { | |
74 | 0 | super(prefix); |
75 | 0 | } |
76 | ||
77 | @Override | |
78 | public String getLibraryVersion(String path) | |
79 | { | |
80 | 0 | return null; |
81 | /* | |
82 | String libraryVersion = null; | |
83 | if (getPrefix() != null) | |
84 | path = getPrefix() + '/' + path; | |
85 | ||
86 | URL url = getClassLoader().getResource(path); | |
87 | ||
88 | if (url == null) | |
89 | { | |
90 | // This library does not exists for this | |
91 | // ResourceLoader | |
92 | return null; | |
93 | } | |
94 | ||
95 | // The problem here is how to scan the directory. When a ClassLoader | |
96 | // is used two cases could occur | |
97 | // 1. The files are unpacked so we can use Url.toURI and crawl | |
98 | // the directory using the api for files. | |
99 | // 2. The files are packed in a jar. This case is more tricky, | |
100 | // because we only have a URL. Checking the jar api we can use | |
101 | // JarURLConnection (Sounds strange, but the api of | |
102 | // URL.openConnection says that for a jar connection a | |
103 | // JarURLConnection is returned). From this point we can access | |
104 | // to the jar api and solve the algoritm. | |
105 | if (url.getProtocol().equals("file")) | |
106 | { | |
107 | try | |
108 | { | |
109 | File directory = new File(url.toURI()); | |
110 | if (directory.isDirectory()) | |
111 | { | |
112 | File[] versions = directory.listFiles(_libraryFileFilter); | |
113 | for (int i = 0; i < versions.length; i++) | |
114 | { | |
115 | String version = versions[i].getName(); | |
116 | if (VERSION_CHECKER.matcher(version).matches()) | |
117 | { | |
118 | if (libraryVersion == null) | |
119 | { | |
120 | libraryVersion = version; | |
121 | } | |
122 | else if (getVersionComparator().compare(libraryVersion, version) < 0) | |
123 | { | |
124 | libraryVersion = version; | |
125 | } | |
126 | } | |
127 | } | |
128 | } | |
129 | } | |
130 | catch (URISyntaxException e) | |
131 | { | |
132 | // Just return null, because library version cannot be | |
133 | // resolved. | |
134 | Logger log = Logger.getLogger(ClassLoaderResourceLoader.class.getName()); | |
135 | if (log.isLoggable(Level.WARNING)) | |
136 | { | |
137 | log.log(Level.WARNING, "url "+url.toString()+" cannot be translated to uri: "+e.getMessage(), e); | |
138 | } | |
139 | } | |
140 | } | |
141 | else if (isJarResourceProtocol(url.getProtocol())) | |
142 | { | |
143 | try | |
144 | { | |
145 | url = getClassLoader().getResource(path + '/'); | |
146 | ||
147 | if (url != null) | |
148 | { | |
149 | JarURLConnection conn = (JarURLConnection)url.openConnection(); | |
150 | // See DIGESTER-29 for related problem | |
151 | conn.setUseCaches(false); | |
152 | ||
153 | try | |
154 | { | |
155 | if (conn.getJarEntry().isDirectory()) | |
156 | { | |
157 | // Unfortunately, we have to scan all entry files | |
158 | // because there is no proper api to scan it as a | |
159 | // directory tree. | |
160 | JarFile file = conn.getJarFile(); | |
161 | for (Enumeration<JarEntry> en = file.entries(); en.hasMoreElements();) | |
162 | { | |
163 | JarEntry entry = en.nextElement(); | |
164 | String entryName = entry.getName(); | |
165 | | |
166 | if (entryName.startsWith(path + '/')) | |
167 | { | |
168 | if (entryName.length() == path.length() + 1) | |
169 | { | |
170 | // the same string, just skip it | |
171 | continue; | |
172 | } | |
173 | | |
174 | if (entryName.charAt(entryName.length() - 1) != '/') | |
175 | { | |
176 | // Skip files | |
177 | continue; | |
178 | } | |
179 | | |
180 | entryName = entryName.substring(path.length() + 1, entryName.length() - 1); | |
181 | | |
182 | if (entryName.indexOf('/') >= 0) | |
183 | { | |
184 | // Inner Directory | |
185 | continue; | |
186 | } | |
187 | | |
188 | String version = entryName; | |
189 | if (VERSION_CHECKER.matcher(version).matches()) | |
190 | { | |
191 | if (libraryVersion == null) | |
192 | { | |
193 | libraryVersion = version; | |
194 | } | |
195 | else if (getVersionComparator().compare(libraryVersion, version) < 0) | |
196 | { | |
197 | libraryVersion = version; | |
198 | } | |
199 | } | |
200 | } | |
201 | } | |
202 | } | |
203 | } | |
204 | finally | |
205 | { | |
206 | //See TRINIDAD-73 | |
207 | //just close the input stream again if | |
208 | //by inspecting the entries the stream | |
209 | //was let open. | |
210 | try | |
211 | { | |
212 | conn.getInputStream().close(); | |
213 | } | |
214 | catch (Exception exception) | |
215 | { | |
216 | // Ignored | |
217 | } | |
218 | } | |
219 | } | |
220 | } | |
221 | catch (IOException e) | |
222 | { | |
223 | // Just return null, because library version cannot be | |
224 | // resolved. | |
225 | Logger log = Logger.getLogger(ClassLoaderResourceLoader.class.getName()); | |
226 | if (log.isLoggable(Level.WARNING)) | |
227 | { | |
228 | log.log(Level.WARNING, "IOException when scanning for resource in jar file:", e); | |
229 | } | |
230 | } | |
231 | } | |
232 | return libraryVersion; | |
233 | */ | |
234 | } | |
235 | ||
236 | @Override | |
237 | public InputStream getResourceInputStream(ResourceMeta resourceMeta) | |
238 | { | |
239 | 0 | InputStream is = null; |
240 | 0 | if (getPrefix() != null && !"".equals(getPrefix())) |
241 | { | |
242 | 0 | String name = getPrefix() + '/' + resourceMeta.getResourceIdentifier(); |
243 | 0 | is = getClassLoader().getResourceAsStream(name); |
244 | 0 | if (is == null) |
245 | { | |
246 | 0 | is = this.getClass().getClassLoader().getResourceAsStream(name); |
247 | } | |
248 | 0 | return is; |
249 | } | |
250 | else | |
251 | { | |
252 | 0 | is = getClassLoader().getResourceAsStream(resourceMeta.getResourceIdentifier()); |
253 | 0 | if (is == null) |
254 | { | |
255 | 0 | is = this.getClass().getClassLoader().getResourceAsStream(resourceMeta.getResourceIdentifier()); |
256 | } | |
257 | 0 | return is; |
258 | } | |
259 | } | |
260 | ||
261 | //@Override | |
262 | public URL getResourceURL(String resourceId) | |
263 | { | |
264 | 0 | URL url = null; |
265 | 0 | if (getPrefix() != null && !"".equals(getPrefix())) |
266 | { | |
267 | 0 | String name = getPrefix() + '/' + resourceId; |
268 | 0 | url = getClassLoader().getResource(name); |
269 | 0 | if (url == null) |
270 | { | |
271 | 0 | url = this.getClass().getClassLoader().getResource(name); |
272 | } | |
273 | 0 | return url; |
274 | } | |
275 | else | |
276 | { | |
277 | 0 | url = getClassLoader().getResource(resourceId); |
278 | 0 | if (url == null) |
279 | { | |
280 | 0 | url = this.getClass().getClassLoader().getResource(resourceId); |
281 | } | |
282 | 0 | return url; |
283 | } | |
284 | } | |
285 | ||
286 | @Override | |
287 | public URL getResourceURL(ResourceMeta resourceMeta) | |
288 | { | |
289 | 0 | return getResourceURL(resourceMeta.getResourceIdentifier()); |
290 | } | |
291 | ||
292 | @Override | |
293 | public String getResourceVersion(String path) | |
294 | { | |
295 | 0 | return null; |
296 | /* | |
297 | String resourceVersion = null; | |
298 | ||
299 | if (getPrefix() != null) | |
300 | path = getPrefix() + '/' + path; | |
301 | ||
302 | URL url = getClassLoader().getResource(path); | |
303 | ||
304 | if (url == null) | |
305 | { | |
306 | // This library does not exists for this | |
307 | // ResourceLoader | |
308 | return null; | |
309 | } | |
310 | ||
311 | if (url.getProtocol().equals("file")) | |
312 | { | |
313 | try | |
314 | { | |
315 | File directory = new File(url.toURI()); | |
316 | if (directory.isDirectory()) | |
317 | { | |
318 | File[] versions = directory.listFiles(_resourceFileFilter); | |
319 | for (int i = 0; i < versions.length; i++) | |
320 | { | |
321 | String version = versions[i].getName(); | |
322 | if (resourceVersion == null) | |
323 | { | |
324 | resourceVersion = version; | |
325 | } | |
326 | else if (getVersionComparator().compare(resourceVersion, version) < 0) | |
327 | { | |
328 | resourceVersion = version; | |
329 | } | |
330 | } | |
331 | //Since it is a directory and no version found set resourceVersion as invalid | |
332 | if (resourceVersion == null) | |
333 | { | |
334 | resourceVersion = VERSION_INVALID; | |
335 | } | |
336 | } | |
337 | } | |
338 | catch (URISyntaxException e) | |
339 | { | |
340 | Logger log = Logger.getLogger(ClassLoaderResourceLoader.class.getName()); | |
341 | if (log.isLoggable(Level.WARNING)) | |
342 | { | |
343 | log.log(Level.WARNING, "url "+url.toString()+" cannot be translated to uri: "+e.getMessage(), e); | |
344 | } | |
345 | } | |
346 | } | |
347 | else if (isJarResourceProtocol(url.getProtocol())) | |
348 | { | |
349 | try | |
350 | { | |
351 | url = getClassLoader().getResource(path + '/'); | |
352 | ||
353 | if (url != null) | |
354 | { | |
355 | JarURLConnection conn = (JarURLConnection)url.openConnection(); | |
356 | // See DIGESTER-29 for related problem | |
357 | conn.setUseCaches(false); | |
358 | ||
359 | try | |
360 | { | |
361 | if (conn.getJarEntry().isDirectory()) | |
362 | { | |
363 | // Unfortunately, we have to scan all entry files | |
364 | JarFile file = conn.getJarFile(); | |
365 | for (Enumeration<JarEntry> en = file.entries(); en.hasMoreElements();) | |
366 | { | |
367 | JarEntry entry = en.nextElement(); | |
368 | String entryName = entry.getName(); | |
369 | | |
370 | if (entryName.startsWith(path + '/')) | |
371 | { | |
372 | if (entryName.length() == path.length() + 1) | |
373 | { | |
374 | // the same string, just skip it | |
375 | continue; | |
376 | } | |
377 | | |
378 | entryName = entryName.substring(path.length()); | |
379 | if (RESOURCE_VERSION_CHECKER.matcher(entryName).matches()) | |
380 | { | |
381 | String version = entryName.substring(1, entryName.lastIndexOf('.')); | |
382 | if (resourceVersion == null) | |
383 | { | |
384 | resourceVersion = version; | |
385 | } | |
386 | else if (getVersionComparator().compare(resourceVersion, version) < 0) | |
387 | { | |
388 | resourceVersion = version; | |
389 | } | |
390 | } | |
391 | } | |
392 | } | |
393 | if (resourceVersion == null) | |
394 | { | |
395 | resourceVersion = VERSION_INVALID; | |
396 | } | |
397 | } | |
398 | } | |
399 | finally | |
400 | { | |
401 | //See TRINIDAD-73 | |
402 | //just close the input stream again if | |
403 | //by inspecting the entries the stream | |
404 | //was let open. | |
405 | try | |
406 | { | |
407 | conn.getInputStream().close(); | |
408 | } | |
409 | catch (Exception exception) | |
410 | { | |
411 | // Ignored | |
412 | } | |
413 | } | |
414 | ||
415 | } | |
416 | } | |
417 | catch (IOException e) | |
418 | { | |
419 | // Just return null, because library version cannot be | |
420 | // resolved. | |
421 | Logger log = Logger.getLogger(ClassLoaderResourceLoader.class.getName()); | |
422 | if (log.isLoggable(Level.WARNING)) | |
423 | { | |
424 | log.log(Level.WARNING, "IOException when scanning for resource in jar file:", e); | |
425 | } | |
426 | } | |
427 | } | |
428 | return resourceVersion; | |
429 | */ | |
430 | } | |
431 | ||
432 | @Override | |
433 | public ResourceMeta createResourceMeta(String prefix, String libraryName, String libraryVersion, | |
434 | String resourceName, String resourceVersion) | |
435 | { | |
436 | //if (_developmentStage && libraryName != null && | |
437 | // ResourceUtils.JAVAX_FACES_LIBRARY_NAME.equals(libraryName) && | |
438 | // ResourceUtils.JSF_JS_RESOURCE_NAME.equals(resourceName)) | |
439 | //{ | |
440 | // InternalClassLoaderResourceLoader will serve it, so return null in this case. | |
441 | // return null; | |
442 | //} else if (_developmentStage && libraryName != null && | |
443 | // ResourceUtils.MYFACES_LIBRARY_NAME.equals(libraryName) && | |
444 | // ResourceUtils.MYFACES_JS_RESOURCE_NAME.equals(resourceName)) { | |
445 | // InternalClassLoaderResourceLoader will serve it, so return null in this case. | |
446 | // return null; | |
447 | //} else | |
448 | //{ | |
449 | 0 | return new ResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion); |
450 | //} | |
451 | } | |
452 | ||
453 | /** | |
454 | * Returns the ClassLoader to use when looking up resources under the top level package. By default, this is the | |
455 | * context class loader. | |
456 | * | |
457 | * @return the ClassLoader used to lookup resources | |
458 | */ | |
459 | protected ClassLoader getClassLoader() | |
460 | { | |
461 | 0 | return ClassUtils.getContextClassLoader(); |
462 | } | |
463 | ||
464 | @Override | |
465 | public boolean libraryExists(String libraryName) | |
466 | { | |
467 | 0 | if (getPrefix() != null && !"".equals(getPrefix())) |
468 | { | |
469 | 0 | URL url = getClassLoader().getResource(getPrefix() + '/' + libraryName); |
470 | 0 | if (url == null) |
471 | { | |
472 | 0 | url = this.getClass().getClassLoader().getResource(getPrefix() + '/' + libraryName); |
473 | } | |
474 | 0 | if (url != null) |
475 | { | |
476 | 0 | return true; |
477 | } | |
478 | 0 | } |
479 | else | |
480 | { | |
481 | 0 | URL url = getClassLoader().getResource(libraryName); |
482 | 0 | if (url == null) |
483 | { | |
484 | 0 | url = this.getClass().getClassLoader().getResource(libraryName); |
485 | } | |
486 | 0 | if (url != null) |
487 | { | |
488 | 0 | return true; |
489 | } | |
490 | } | |
491 | 0 | return false; |
492 | } | |
493 | ||
494 | /** | |
495 | * <p>Determines whether the given URL resource protocol refers to a JAR file. Note that | |
496 | * BEA WebLogic and IBM WebSphere don't use the "jar://" protocol for some reason even | |
497 | * though you can treat these resources just like normal JAR files, i.e. you can ignore | |
498 | * the difference between these protocols after this method has returned.</p> | |
499 | * | |
500 | * @param protocol the URL resource protocol you want to check | |
501 | * | |
502 | * @return <code>true</code> if the given URL resource protocol refers to a JAR file, | |
503 | * <code>false</code> otherwise | |
504 | */ | |
505 | /* | |
506 | private static boolean isJarResourceProtocol(String protocol) | |
507 | { | |
508 | // Websphere uses the protocol "wsjar://" and Weblogic uses the protocol "zip://". | |
509 | return "jar".equals(protocol) || "wsjar".equals(protocol) || "zip".equals(protocol); | |
510 | }*/ | |
511 | ||
512 | } |