1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.misc;
27
28 import java.util.*;
29 import java.util.jar.JarFile;
30 import sun.misc.JarIndex;
31 import sun.misc.InvalidJarIndexException;
32 import sun.net.www.ParseUtil;
33 import java.util.zip.ZipEntry;
34 import java.util.jar.JarEntry;
35 import java.util.jar.Manifest;
36 import java.util.jar.Attributes;
37 import java.util.jar.Attributes.Name;
38 import java.net.JarURLConnection;
39 import java.net.MalformedURLException;
40 import java.net.URL;
41 import java.net.URLConnection;
42 import java.net.HttpURLConnection;
43 import java.net.URLStreamHandler;
44 import java.net.URLStreamHandlerFactory;
45 import java.io.*;
46 import java.security.AccessController;
47 import java.security.AccessControlException;
48 import java.security.CodeSigner;
49 import java.security.Permission;
50 import java.security.PrivilegedAction;
51 import java.security.PrivilegedExceptionAction;
52 import java.security.cert.Certificate;
53 import sun.misc.FileURLMapper;
54 import sun.net.util.URLUtil;
55
56 /**
57 * This class is used to maintain a search path of URLs for loading classes
58 * and resources from both JAR files and directories.
59 *
60 * @author David Connelly
61 */
62 public class URLClassPath {
63 final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
64 final static String JAVA_VERSION;
65 private static final boolean DEBUG;
66 private static final boolean DISABLE_JAR_CHECKING;
67
68 static {
69 JAVA_VERSION = java.security.AccessController.doPrivileged(
70 new sun.security.action.GetPropertyAction("java.version"));
71 DEBUG = (java.security.AccessController.doPrivileged(
72 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
73 String p = java.security.AccessController.doPrivileged(
74 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
75 DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
76 }
77
78 /* The original search path of URLs. */
79 private ArrayList<URL> path = new ArrayList<URL>();
80
81 /* The stack of unopened URLs */
82 Stack<URL> urls = new Stack<URL>();
83
84 /* The resulting search path of Loaders */
85 ArrayList<Loader> loaders = new ArrayList<Loader>();
86
87 /* Map of each URL opened to its corresponding Loader */
88 HashMap<String, Loader> lmap = new HashMap<String, Loader>();
89
90 /* The jar protocol handler to use when creating new URLs */
91 private URLStreamHandler jarHandler;
92
93 /* Whether this URLClassLoader has been closed yet */
94 private boolean closed = false;
132 closed = true;
133 return result;
134 }
135
136 /**
137 * Appends the specified URL to the search path of directory and JAR
138 * file URLs from which to load classes and resources.
139 * <p>
140 * If the URL specified is null or is already in the list of
141 * URLs, then invoking this method has no effect.
142 */
143 public synchronized void addURL(URL url) {
144 if (closed)
145 return;
146 synchronized (urls) {
147 if (url == null || path.contains(url))
148 return;
149
150 urls.add(0, url);
151 path.add(url);
152 }
153 }
154
155 /**
156 * Returns the original search path of URLs.
157 */
158 public URL[] getURLs() {
159 synchronized (urls) {
160 return path.toArray(new URL[path.size()]);
161 }
162 }
163
164 /**
165 * Finds the resource with the specified name on the URL search path
166 * or null if not found or security check fails.
167 *
168 * @param name the name of the resource
169 * @param check whether to perform a security check
170 * @return a <code>URL</code> for the resource, or <code>null</code>
171 * if the resource could not be found.
172 */
173 public URL findResource(String name, boolean check) {
174 Loader loader;
175 for (int i = 0; (loader = getLoader(i)) != null; i++) {
176 URL url = loader.findResource(name, check);
177 if (url != null) {
178 return url;
179 }
180 }
181 return null;
182 }
183
184 /**
185 * Finds the first Resource on the URL search path which has the specified
186 * name. Returns null if no Resource could be found.
187 *
188 * @param name the name of the Resource
189 * @param check whether to perform a security check
190 * @return the Resource, or null if not found
191 */
192 public Resource getResource(String name, boolean check) {
193 if (DEBUG) {
194 System.err.println("URLClassPath.getResource(\"" + name + "\")");
195 }
196
197 Loader loader;
198 for (int i = 0; (loader = getLoader(i)) != null; i++) {
199 Resource res = loader.getResource(name, check);
200 if (res != null) {
201 return res;
202 }
203 }
204 return null;
205 }
206
207 /**
208 * Finds all resources on the URL search path with the given name.
209 * Returns an enumeration of the URL objects.
210 *
211 * @param name the resource name
212 * @return an Enumeration of all the urls having the specified name
213 */
214 public Enumeration<URL> findResources(final String name,
215 final boolean check) {
216 return new Enumeration<URL>() {
217 private int index = 0;
218 private URL url = null;
219
220 private boolean next() {
221 if (url != null) {
222 return true;
223 } else {
224 Loader loader;
225 while ((loader = getLoader(index++)) != null) {
226 url = loader.findResource(name, check);
227 if (url != null) {
228 return true;
229 }
230 }
231 return false;
232 }
233 }
234
235 public boolean hasMoreElements() {
236 return next();
237 }
238
239 public URL nextElement() {
240 if (!next()) {
241 throw new NoSuchElementException();
242 }
243 URL u = url;
244 url = null;
245 return u;
246 }
247 };
248 }
249
250 public Resource getResource(String name) {
251 return getResource(name, true);
252 }
253
254 /**
255 * Finds all resources on the URL search path with the given name.
256 * Returns an enumeration of the Resource objects.
257 *
258 * @param name the resource name
259 * @return an Enumeration of all the resources having the specified name
260 */
261 public Enumeration<Resource> getResources(final String name,
262 final boolean check) {
263 return new Enumeration<Resource>() {
264 private int index = 0;
265 private Resource res = null;
266
267 private boolean next() {
268 if (res != null) {
269 return true;
270 } else {
271 Loader loader;
272 while ((loader = getLoader(index++)) != null) {
273 res = loader.getResource(name, check);
274 if (res != null) {
275 return true;
276 }
277 }
278 return false;
279 }
280 }
281
282 public boolean hasMoreElements() {
283 return next();
284 }
285
286 public Resource nextElement() {
287 if (!next()) {
288 throw new NoSuchElementException();
289 }
290 Resource r = res;
291 res = null;
292 return r;
293 }
294 };
295 }
296
297 public Enumeration<Resource> getResources(final String name) {
298 return getResources(name, true);
299 }
300
301 /*
302 * Returns the Loader at the specified position in the URL search
303 * path. The URLs are opened and expanded as needed. Returns null
304 * if the specified index is out of range.
305 */
306 private synchronized Loader getLoader(int index) {
307 if (closed) {
308 return null;
309 }
310 // Expand URL search path until the request can be satisfied
311 // or the URL stack is empty.
312 while (loaders.size() < index + 1) {
313 // Pop the next URL from the URL stack
314 URL url;
315 synchronized (urls) {
316 if (urls.empty()) {
317 return null;
318 } else {
319 url = urls.pop();
320 }
324 // but is referenced by a JAR index.)
325 String urlNoFragString = URLUtil.urlNoFragString(url);
326 if (lmap.containsKey(urlNoFragString)) {
327 continue;
328 }
329 // Otherwise, create a new Loader for the URL.
330 Loader loader;
331 try {
332 loader = getLoader(url);
333 // If the loader defines a local class path then add the
334 // URLs to the list of URLs to be opened.
335 URL[] urls = loader.getClassPath();
336 if (urls != null) {
337 push(urls);
338 }
339 } catch (IOException e) {
340 // Silently ignore for now...
341 continue;
342 }
343 // Finally, add the Loader to the search path.
344 loaders.add(loader);
345 lmap.put(urlNoFragString, loader);
346 }
347 return loaders.get(index);
348 }
349
350 /*
351 * Returns the Loader for the specified base URL.
352 */
353 private Loader getLoader(final URL url) throws IOException {
354 try {
355 return java.security.AccessController.doPrivileged(
356 new java.security.PrivilegedExceptionAction<Loader>() {
357 public Loader run() throws IOException {
358 String file = url.getFile();
359 if (file != null && file.endsWith("/")) {
360 if ("file".equals(url.getProtocol())) {
361 return new FileLoader(url);
362 } else {
363 return new Loader(url);
364 }
365 } else {
|
1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.misc;
27
28 import java.util.*;
29 import java.util.jar.JarFile;
30 import sun.misc.JarIndex;
31 import sun.misc.InvalidJarIndexException;
32 import sun.net.www.ParseUtil;
33 import java.util.zip.ZipEntry;
34 import java.util.jar.JarEntry;
35 import java.util.jar.Manifest;
36 import java.util.jar.Attributes;
37 import java.util.jar.Attributes.Name;
38 import java.net.JarURLConnection;
39 import java.net.MalformedURLException;
40 import java.net.URL;
41 import java.net.URLClassLoader;
42 import java.net.URLConnection;
43 import java.net.HttpURLConnection;
44 import java.net.URLStreamHandler;
45 import java.net.URLStreamHandlerFactory;
46 import java.io.*;
47 import java.security.AccessController;
48 import java.security.AccessControlException;
49 import java.security.CodeSigner;
50 import java.security.Permission;
51 import java.security.PrivilegedAction;
52 import java.security.PrivilegedExceptionAction;
53 import java.security.cert.Certificate;
54 import sun.misc.FileURLMapper;
55 import sun.net.util.URLUtil;
56 import sun.security.action.GetPropertyAction;
57
58 /**
59 * This class is used to maintain a search path of URLs for loading classes
60 * and resources from both JAR files and directories.
61 *
62 * @author David Connelly
63 */
64 public class URLClassPath {
65 final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
66 final static String JAVA_VERSION;
67 private static final boolean DEBUG;
68 private static final boolean DEBUG_LOOKUP_CACHE;
69 private static final boolean DISABLE_JAR_CHECKING;
70
71 static {
72 JAVA_VERSION = java.security.AccessController.doPrivileged(
73 new GetPropertyAction("java.version"));
74 DEBUG = (java.security.AccessController.doPrivileged(
75 new GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
76 DEBUG_LOOKUP_CACHE = (java.security.AccessController.doPrivileged(
77 new GetPropertyAction("sun.misc.URLClassPath.debugLookupCache")) != null);
78 String p = java.security.AccessController.doPrivileged(
79 new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
80 DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
81 }
82
83 /* The original search path of URLs. */
84 private ArrayList<URL> path = new ArrayList<URL>();
85
86 /* The stack of unopened URLs */
87 Stack<URL> urls = new Stack<URL>();
88
89 /* The resulting search path of Loaders */
90 ArrayList<Loader> loaders = new ArrayList<Loader>();
91
92 /* Map of each URL opened to its corresponding Loader */
93 HashMap<String, Loader> lmap = new HashMap<String, Loader>();
94
95 /* The jar protocol handler to use when creating new URLs */
96 private URLStreamHandler jarHandler;
97
98 /* Whether this URLClassLoader has been closed yet */
99 private boolean closed = false;
137 closed = true;
138 return result;
139 }
140
141 /**
142 * Appends the specified URL to the search path of directory and JAR
143 * file URLs from which to load classes and resources.
144 * <p>
145 * If the URL specified is null or is already in the list of
146 * URLs, then invoking this method has no effect.
147 */
148 public synchronized void addURL(URL url) {
149 if (closed)
150 return;
151 synchronized (urls) {
152 if (url == null || path.contains(url))
153 return;
154
155 urls.add(0, url);
156 path.add(url);
157
158 if (lookupCacheURLs != null) {
159 // The lookup cache is no longer valid, since getLookupCache()
160 // does not consider the newly added url.
161 disableAllLookupCaches();
162 }
163 }
164 }
165
166 /**
167 * Returns the original search path of URLs.
168 */
169 public URL[] getURLs() {
170 synchronized (urls) {
171 return path.toArray(new URL[path.size()]);
172 }
173 }
174
175 /**
176 * Finds the resource with the specified name on the URL search path
177 * or null if not found or security check fails.
178 *
179 * @param name the name of the resource
180 * @param check whether to perform a security check
181 * @return a <code>URL</code> for the resource, or <code>null</code>
182 * if the resource could not be found.
183 */
184 public URL findResource(String name, boolean check) {
185 Loader loader;
186 int[] cache = getLookupCache(name);
187 for (int i = 0; (loader = getNextLoader(cache, i)) != null; i++) {
188 URL url = loader.findResource(name, check);
189 if (url != null) {
190 return url;
191 }
192 }
193 return null;
194 }
195
196 /**
197 * Finds the first Resource on the URL search path which has the specified
198 * name. Returns null if no Resource could be found.
199 *
200 * @param name the name of the Resource
201 * @param check whether to perform a security check
202 * @return the Resource, or null if not found
203 */
204 public Resource getResource(String name, boolean check) {
205 if (DEBUG) {
206 System.err.println("URLClassPath.getResource(\"" + name + "\")");
207 }
208
209 Loader loader;
210 int[] cache = getLookupCache(name);
211 for (int i = 0; (loader = getNextLoader(cache, i)) != null; i++) {
212 Resource res = loader.getResource(name, check);
213 if (res != null) {
214 return res;
215 }
216 }
217 return null;
218 }
219
220 /**
221 * Finds all resources on the URL search path with the given name.
222 * Returns an enumeration of the URL objects.
223 *
224 * @param name the resource name
225 * @return an Enumeration of all the urls having the specified name
226 */
227 public Enumeration<URL> findResources(final String name,
228 final boolean check) {
229 return new Enumeration<URL>() {
230 private int index = 0;
231 private int[] cache = getLookupCache(name);
232 private URL url = null;
233
234 private boolean next() {
235 if (url != null) {
236 return true;
237 } else {
238 Loader loader;
239 while ((loader = getNextLoader(cache, index++)) != null) {
240 url = loader.findResource(name, check);
241 if (url != null) {
242 return true;
243 }
244 }
245 return false;
246 }
247 }
248
249 public boolean hasMoreElements() {
250 return next();
251 }
252
253 public URL nextElement() {
254 if (!next()) {
255 throw new NoSuchElementException();
256 }
257 URL u = url;
258 url = null;
259 return u;
260 }
261 };
262 }
263
264 public Resource getResource(String name) {
265 return getResource(name, true);
266 }
267
268 /**
269 * Finds all resources on the URL search path with the given name.
270 * Returns an enumeration of the Resource objects.
271 *
272 * @param name the resource name
273 * @return an Enumeration of all the resources having the specified name
274 */
275 public Enumeration<Resource> getResources(final String name,
276 final boolean check) {
277 return new Enumeration<Resource>() {
278 private int index = 0;
279 private int[] cache = getLookupCache(name);
280 private Resource res = null;
281
282 private boolean next() {
283 if (res != null) {
284 return true;
285 } else {
286 Loader loader;
287 while ((loader = getNextLoader(cache, index++)) != null) {
288 res = loader.getResource(name, check);
289 if (res != null) {
290 return true;
291 }
292 }
293 return false;
294 }
295 }
296
297 public boolean hasMoreElements() {
298 return next();
299 }
300
301 public Resource nextElement() {
302 if (!next()) {
303 throw new NoSuchElementException();
304 }
305 Resource r = res;
306 res = null;
307 return r;
308 }
309 };
310 }
311
312 public Enumeration<Resource> getResources(final String name) {
313 return getResources(name, true);
314 }
315
316 private static volatile boolean lookupCacheEnabled
317 = "true".equals(VM.getSavedProperty("sun.cds.enableSharedLookupCache"));
318 private URL[] lookupCacheURLs;
319 private ClassLoader lookupCacheLoader;
320
321 synchronized void initLookupCache(ClassLoader loader) {
322 if ((lookupCacheURLs = getLookupCacheURLs(loader)) != null) {
323 lookupCacheLoader = loader;
324 } else {
325 // This JVM instance does not support lookup cache.
326 disableAllLookupCaches();
327 }
328 }
329
330 static void disableAllLookupCaches() {
331 lookupCacheEnabled = false;
332 }
333
334 private static native URL[] getLookupCacheURLs(ClassLoader loader);
335 private static native int[] getLookupCacheForClassLoader(ClassLoader loader,
336 String name);
337 private static native boolean knownToNotExist0(ClassLoader loader,
338 String className);
339
340 synchronized boolean knownToNotExist(String className) {
341 if (lookupCacheURLs != null && lookupCacheEnabled) {
342 return knownToNotExist0(lookupCacheLoader, className);
343 }
344
345 // Don't know if this class exists or not -- need to do a full search.
346 return false;
347 }
348
349 /**
350 * Returns an array of the index to lookupCacheURLs that may
351 * contain the specified resource. The values in the returned
352 * array are in strictly ascending order and must be a valid index
353 * to lookupCacheURLs array.
354 *
355 * This method returns an empty array if the specified resource
356 * cannot be found in this URLClassPath. If there is no lookup
357 * cache or it's disabled, this method returns null and the lookup
358 * should search the entire classpath.
359 *
360 * Example: if lookupCacheURLs contains {a.jar, b.jar, c.jar, d.jar}
361 * and package "foo" only exists in a.jar and c.jar,
362 * getLookupCache("foo/Bar.class") will return {0, 2}
363 *
364 * @param name the resource name
365 * @return an array of the index to lookupCacheURLs that may contain the
366 * specified resource; or null if no lookup cache is used.
367 */
368 private synchronized int[] getLookupCache(String name) {
369 if (lookupCacheURLs == null || !lookupCacheEnabled) {
370 return null;
371 }
372
373 int[] cache = getLookupCacheForClassLoader(lookupCacheLoader, name);
374 if (cache != null && cache.length > 0) {
375 int maxindex = cache[cache.length - 1]; // cache[] is strictly ascending.
376 if (!ensureLoaderOpened(maxindex)) {
377 if (DEBUG_LOOKUP_CACHE) {
378 System.out.println("Expanded loaders FAILED " +
379 loaders.size() + " for maxindex=" + maxindex);
380 }
381 return null;
382 }
383 }
384
385 return cache;
386 }
387
388 private boolean ensureLoaderOpened(int index) {
389 if (loaders.size() <= index) {
390 // Open all Loaders up to, and including, index
391 if (getLoader(index) == null) {
392 return false;
393 }
394 if (!lookupCacheEnabled) {
395 // cache was invalidated as the result of the above call.
396 return false;
397 }
398 if (DEBUG_LOOKUP_CACHE) {
399 System.out.println("Expanded loaders " + loaders.size() +
400 " to index=" + index);
401 }
402 }
403 return true;
404 }
405
406 /*
407 * The CLASS-PATH attribute was expanded by the VM when building
408 * the resource lookup cache in the same order as the getLoader
409 * method does. This method validates if the URL from the lookup
410 * cache matches the URL of the Loader at the given index;
411 * otherwise, this method disables the lookup cache.
412 */
413 private synchronized void validateLookupCache(int index,
414 String urlNoFragString) {
415 if (lookupCacheURLs != null && lookupCacheEnabled) {
416 if (index < lookupCacheURLs.length &&
417 urlNoFragString.equals(
418 URLUtil.urlNoFragString(lookupCacheURLs[index]))) {
419 return;
420 }
421 if (DEBUG || DEBUG_LOOKUP_CACHE) {
422 System.out.println("WARNING: resource lookup cache invalidated "
423 + "for lookupCacheLoader at " + index);
424 }
425 disableAllLookupCaches();
426 }
427 }
428
429 /**
430 * Returns the next Loader that may contain the resource to
431 * lookup. If the given cache is null, return loaders.get(index)
432 * that may be lazily created; otherwise, cache[index] is the next
433 * Loader that may contain the resource to lookup and so returns
434 * loaders.get(cache[index]).
435 *
436 * If cache is non-null, loaders.get(cache[index]) must be present.
437 *
438 * @param cache lookup cache. If null, search the entire class path
439 * @param index index to the given cache array; or to the loaders list.
440 */
441 private synchronized Loader getNextLoader(int[] cache, int index) {
442 if (closed) {
443 return null;
444 }
445 if (cache != null) {
446 if (index < cache.length) {
447 Loader loader = loaders.get(cache[index]);
448 if (DEBUG_LOOKUP_CACHE) {
449 System.out.println("HASCACHE: Loading from : " + cache[index]
450 + " = " + loader.getBaseURL());
451 }
452 return loader;
453 } else {
454 return null; // finished iterating over cache[]
455 }
456 } else {
457 return getLoader(index);
458 }
459 }
460
461 /*
462 * Returns the Loader at the specified position in the URL search
463 * path. The URLs are opened and expanded as needed. Returns null
464 * if the specified index is out of range.
465 */
466 private synchronized Loader getLoader(int index) {
467 if (closed) {
468 return null;
469 }
470 // Expand URL search path until the request can be satisfied
471 // or the URL stack is empty.
472 while (loaders.size() < index + 1) {
473 // Pop the next URL from the URL stack
474 URL url;
475 synchronized (urls) {
476 if (urls.empty()) {
477 return null;
478 } else {
479 url = urls.pop();
480 }
484 // but is referenced by a JAR index.)
485 String urlNoFragString = URLUtil.urlNoFragString(url);
486 if (lmap.containsKey(urlNoFragString)) {
487 continue;
488 }
489 // Otherwise, create a new Loader for the URL.
490 Loader loader;
491 try {
492 loader = getLoader(url);
493 // If the loader defines a local class path then add the
494 // URLs to the list of URLs to be opened.
495 URL[] urls = loader.getClassPath();
496 if (urls != null) {
497 push(urls);
498 }
499 } catch (IOException e) {
500 // Silently ignore for now...
501 continue;
502 }
503 // Finally, add the Loader to the search path.
504 validateLookupCache(loaders.size(), urlNoFragString);
505 loaders.add(loader);
506 lmap.put(urlNoFragString, loader);
507 }
508 if (DEBUG_LOOKUP_CACHE) {
509 System.out.println("NOCACHE: Loading from : " + index );
510 }
511 return loaders.get(index);
512 }
513
514 /*
515 * Returns the Loader for the specified base URL.
516 */
517 private Loader getLoader(final URL url) throws IOException {
518 try {
519 return java.security.AccessController.doPrivileged(
520 new java.security.PrivilegedExceptionAction<Loader>() {
521 public Loader run() throws IOException {
522 String file = url.getFile();
523 if (file != null && file.endsWith("/")) {
524 if ("file".equals(url.getProtocol())) {
525 return new FileLoader(url);
526 } else {
527 return new Loader(url);
528 }
529 } else {
|