73 *
74 * @author David Connelly
75 */
76 public class URLClassPath {
77 final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
78 final static String JAVA_VERSION;
79 private static final boolean DEBUG;
80 private static final boolean DISABLE_JAR_CHECKING;
81
82 static {
83 JAVA_VERSION = java.security.AccessController.doPrivileged(
84 new sun.security.action.GetPropertyAction("java.version"));
85 DEBUG = (java.security.AccessController.doPrivileged(
86 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
87 String p = java.security.AccessController.doPrivileged(
88 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
89 DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
90 }
91
92 /* The original search path of URLs. */
93 private ArrayList path = new ArrayList();
94
95 /* The stack of unopened URLs */
96 Stack urls = new Stack();
97
98 /* The resulting search path of Loaders */
99 ArrayList loaders = new ArrayList();
100
101 /* Map of each URL opened to its corresponding Loader */
102 HashMap lmap = new HashMap();
103
104 /* The jar protocol handler to use when creating new URLs */
105 private URLStreamHandler jarHandler;
106
107 /**
108 * Creates a new URLClassPath for the given URLs. The URLs will be
109 * searched in the order specified for classes and resources. A URL
110 * ending with a '/' is assumed to refer to a directory. Otherwise,
111 * the URL is assumed to refer to a JAR file.
112 *
113 * @param urls the directory and JAR file URLs to search for classes
114 * and resources
115 * @param factory the URLStreamHandlerFactory to use when creating new URLs
116 */
117 public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
118 for (int i = 0; i < urls.length; i++) {
119 path.add(urls[i]);
120 }
121 push(urls);
122 if (factory != null) {
130
131 /**
132 * Appends the specified URL to the search path of directory and JAR
133 * file URLs from which to load classes and resources.
134 */
135 public void addURL(URL url) {
136 synchronized (urls) {
137 if (path.contains(url))
138 return;
139
140 urls.add(0, url);
141 path.add(url);
142 }
143 }
144
145 /**
146 * Returns the original search path of URLs.
147 */
148 public URL[] getURLs() {
149 synchronized (urls) {
150 return (URL[])path.toArray(new URL[path.size()]);
151 }
152 }
153
154 /**
155 * Finds the resource with the specified name on the URL search path
156 * or null if not found or security check fails.
157 *
158 * @param name the name of the resource
159 * @param check whether to perform a security check
160 * @return a <code>URL</code> for the resource, or <code>null</code>
161 * if the resource could not be found.
162 */
163 public URL findResource(String name, boolean check) {
164 Loader loader;
165 for (int i = 0; (loader = getLoader(i)) != null; i++) {
166 URL url = loader.findResource(name, check);
167 if (url != null) {
168 return url;
169 }
170 }
184 System.err.println("URLClassPath.getResource(\"" + name + "\")");
185 }
186
187 Loader loader;
188 for (int i = 0; (loader = getLoader(i)) != null; i++) {
189 Resource res = loader.getResource(name, check);
190 if (res != null) {
191 return res;
192 }
193 }
194 return null;
195 }
196
197 /**
198 * Finds all resources on the URL search path with the given name.
199 * Returns an enumeration of the URL objects.
200 *
201 * @param name the resource name
202 * @return an Enumeration of all the urls having the specified name
203 */
204 public Enumeration findResources(final String name,
205 final boolean check) {
206 return new Enumeration() {
207 private int index = 0;
208 private URL url = null;
209
210 private boolean next() {
211 if (url != null) {
212 return true;
213 } else {
214 Loader loader;
215 while ((loader = getLoader(index++)) != null) {
216 url = loader.findResource(name, check);
217 if (url != null) {
218 return true;
219 }
220 }
221 return false;
222 }
223 }
224
225 public boolean hasMoreElements() {
226 return next();
227 }
228
229 public Object nextElement() {
230 if (!next()) {
231 throw new NoSuchElementException();
232 }
233 URL u = url;
234 url = null;
235 return u;
236 }
237 };
238 }
239
240 public Resource getResource(String name) {
241 return getResource(name, true);
242 }
243
244 /**
245 * Finds all resources on the URL search path with the given name.
246 * Returns an enumeration of the Resource objects.
247 *
248 * @param name the resource name
249 * @return an Enumeration of all the resources having the specified name
250 */
251 public Enumeration getResources(final String name,
252 final boolean check) {
253 return new Enumeration() {
254 private int index = 0;
255 private Resource res = null;
256
257 private boolean next() {
258 if (res != null) {
259 return true;
260 } else {
261 Loader loader;
262 while ((loader = getLoader(index++)) != null) {
263 res = loader.getResource(name, check);
264 if (res != null) {
265 return true;
266 }
267 }
268 return false;
269 }
270 }
271
272 public boolean hasMoreElements() {
273 return next();
274 }
275
276 public Object nextElement() {
277 if (!next()) {
278 throw new NoSuchElementException();
279 }
280 Resource r = res;
281 res = null;
282 return r;
283 }
284 };
285 }
286
287 public Enumeration getResources(final String name) {
288 return getResources(name, true);
289 }
290
291 /*
292 * Returns the Loader at the specified position in the URL search
293 * path. The URLs are opened and expanded as needed. Returns null
294 * if the specified index is out of range.
295 */
296 private synchronized Loader getLoader(int index) {
297 // Expand URL search path until the request can be satisfied
298 // or the URL stack is empty.
299 while (loaders.size() < index + 1) {
300 // Pop the next URL from the URL stack
301 URL url;
302 synchronized (urls) {
303 if (urls.empty()) {
304 return null;
305 } else {
306 url = (URL)urls.pop();
307 }
308 }
309 // Skip this URL if it already has a Loader. (Loader
310 // may be null in the case where URL has not been opened
311 // but is referenced by a JAR index.)
312 if (lmap.containsKey(url)) {
313 continue;
314 }
315 // Otherwise, create a new Loader for the URL.
316 Loader loader;
317 try {
318 loader = getLoader(url);
319 // If the loader defines a local class path then add the
320 // URLs to the list of URLs to be opened.
321 URL[] urls = loader.getClassPath();
322 if (urls != null) {
323 push(urls);
324 }
325 } catch (IOException e) {
326 // Silently ignore for now...
327 continue;
328 }
329 // Finally, add the Loader to the search path.
330 loaders.add(loader);
331 lmap.put(url, loader);
332 }
333 return (Loader)loaders.get(index);
334 }
335
336 /*
337 * Returns the Loader for the specified base URL.
338 */
339 private Loader getLoader(final URL url) throws IOException {
340 try {
341 return (Loader)java.security.AccessController.doPrivileged
342 (new java.security.PrivilegedExceptionAction() {
343 public Object run() throws IOException {
344 String file = url.getFile();
345 if (file != null && file.endsWith("/")) {
346 if ("file".equals(url.getProtocol())) {
347 return new FileLoader(url);
348 } else {
349 return new Loader(url);
350 }
351 } else {
352 return new JarLoader(url, jarHandler, lmap);
353 }
354 }
355 });
356 } catch (java.security.PrivilegedActionException pae) {
357 throw (IOException)pae.getException();
358 }
359 }
360
361 /*
362 * Pushes the specified URLs onto the list of unopened URLs.
363 */
545 return getResource(name, true);
546 }
547
548 /*
549 * Returns the local class path for this loader, or null if none.
550 */
551 URL[] getClassPath() throws IOException {
552 return null;
553 }
554 }
555
556 /*
557 * Inner class used to represent a Loader of resources from a JAR URL.
558 */
559 static class JarLoader extends Loader {
560 private JarFile jar;
561 private URL csu;
562 private JarIndex index;
563 private MetaIndex metaIndex;
564 private URLStreamHandler handler;
565 private HashMap lmap;
566 private static final sun.misc.JavaUtilZipFileAccess zipAccess =
567 sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
568
569 /*
570 * Creates a new JarLoader for the specified URL referring to
571 * a JAR file.
572 */
573 JarLoader(URL url, URLStreamHandler jarHandler, HashMap loaderMap)
574 throws IOException
575 {
576 super(new URL("jar", "", -1, url + "!/", jarHandler));
577 csu = url;
578 handler = jarHandler;
579 lmap = loaderMap;
580
581 if (!isOptimizable(url)) {
582 ensureOpen();
583 } else {
584 String fileName = url.getFile();
585 if (fileName != null) {
586 fileName = ParseUtil.decode(fileName);
587 File f = new File(fileName);
588 metaIndex = MetaIndex.forJar(f);
589 // If the meta index is found but the file is not
590 // installed, set metaIndex to null. A typical
591 // senario is charsets.jar which won't be installed
592 // when the user is running in certain locale environment.
593 // The side effect of null metaIndex will cause
601 // entry recorded in meta-index file or such jar file is
602 // missing in JRE. See bug 6340399.
603 if (metaIndex == null) {
604 ensureOpen();
605 }
606 }
607 }
608
609 JarFile getJarFile () {
610 return jar;
611 }
612
613 private boolean isOptimizable(URL url) {
614 return "file".equals(url.getProtocol());
615 }
616
617 private void ensureOpen() throws IOException {
618 if (jar == null) {
619 try {
620 java.security.AccessController.doPrivileged(
621 new java.security.PrivilegedExceptionAction() {
622 public Object run() throws IOException {
623 if (DEBUG) {
624 System.err.println("Opening " + csu);
625 Thread.dumpStack();
626 }
627
628 jar = getJarFile(csu);
629 index = JarIndex.getJarIndex(jar, metaIndex);
630 if (index != null) {
631 String[] jarfiles = index.getJarFiles();
632 // Add all the dependent URLs to the lmap so that loaders
633 // will not be created for them by URLClassPath.getLoader(int)
634 // if the same URL occurs later on the main class path. We set
635 // Loader to null here to avoid creating a Loader for each
636 // URL until we actually need to try to load something from them.
637 for(int i = 0; i < jarfiles.length; i++) {
638 try {
639 URL jarURL = new URL(csu, jarfiles[i]);
640 // If a non-null loader already exists, leave it alone.
641 if (!lmap.containsKey(jarURL)) {
642 lmap.put(jarURL, null);
727 { return entry.getCertificates(); };
728 public CodeSigner[] getCodeSigners()
729 { return entry.getCodeSigners(); };
730 };
731 }
732
733
734 /*
735 * Returns true iff atleast one resource in the jar file has the same
736 * package name as that of the specified resource name.
737 */
738 boolean validIndex(final String name) {
739 String packageName = name;
740 int pos;
741 if((pos = name.lastIndexOf("/")) != -1) {
742 packageName = name.substring(0, pos);
743 }
744
745 String entryName;
746 ZipEntry entry;
747 Enumeration enum_ = jar.entries();
748 while (enum_.hasMoreElements()) {
749 entry = (ZipEntry)enum_.nextElement();
750 entryName = entry.getName();
751 if((pos = entryName.lastIndexOf("/")) != -1)
752 entryName = entryName.substring(0, pos);
753 if (entryName.equals(packageName)) {
754 return true;
755 }
756 }
757 return false;
758 }
759
760 /*
761 * Returns the URL for a resource with the specified name
762 */
763 URL findResource(final String name, boolean check) {
764 Resource rsc = getResource(name, check);
765 if (rsc != null) {
766 return rsc.getURL();
767 }
768 return null;
769 }
773 */
774 Resource getResource(final String name, boolean check) {
775 if (metaIndex != null) {
776 if (!metaIndex.mayContain(name)) {
777 return null;
778 }
779 }
780
781 try {
782 ensureOpen();
783 } catch (IOException e) {
784 throw (InternalError) new InternalError().initCause(e);
785 }
786 final JarEntry entry = jar.getJarEntry(name);
787 if (entry != null)
788 return checkResource(name, check, entry);
789
790 if (index == null)
791 return null;
792
793 HashSet visited = new HashSet();
794 return getResource(name, check, visited);
795 }
796
797 /*
798 * Version of getResource() that tracks the jar files that have been
799 * visited by linking through the index files. This helper method uses
800 * a HashSet to store the URLs of jar files that have been searched and
801 * uses it to avoid going into an infinite loop, looking for a
802 * non-existent resource
803 */
804 Resource getResource(final String name, boolean check,
805 Set visited) {
806
807 Resource res;
808 Object[] jarFiles;
809 boolean done = false;
810 int count = 0;
811 LinkedList jarFilesList = null;
812
813 /* If there no jar files in the index that can potential contain
814 * this resource then return immediately.
815 */
816 if((jarFilesList = index.get(name)) == null)
817 return null;
818
819 do {
820 jarFiles = jarFilesList.toArray();
821 int size = jarFilesList.size();
822 /* loop through the mapped jar file list */
823 while(count < size) {
824 String jarName = (String)jarFiles[count++];
825 JarLoader newLoader;
826 final URL url;
827
828 try{
829 url = new URL(csu, jarName);
830 if ((newLoader = (JarLoader)lmap.get(url)) == null) {
831 /* no loader has been set up for this jar file
832 * before
833 */
834 newLoader = (JarLoader)
835 AccessController.doPrivileged(
836 new PrivilegedExceptionAction() {
837 public Object run() throws IOException {
838 return new JarLoader(url, handler,
839 lmap);
840 }
841 });
842
843 /* this newly opened jar file has its own index,
844 * merge it into the parent's index, taking into
845 * account the relative path.
846 */
847 JarIndex newIndex = newLoader.getIndex();
848 if(newIndex != null) {
849 int pos = jarName.lastIndexOf("/");
850 newIndex.merge(this.index, (pos == -1 ?
851 null : jarName.substring(0, pos + 1)));
852 }
853
854 /* put it in the global hashtable */
855 lmap.put(url, newLoader);
856 }
857 } catch (java.security.PrivilegedActionException pae) {
|
73 *
74 * @author David Connelly
75 */
76 public class URLClassPath {
77 final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
78 final static String JAVA_VERSION;
79 private static final boolean DEBUG;
80 private static final boolean DISABLE_JAR_CHECKING;
81
82 static {
83 JAVA_VERSION = java.security.AccessController.doPrivileged(
84 new sun.security.action.GetPropertyAction("java.version"));
85 DEBUG = (java.security.AccessController.doPrivileged(
86 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
87 String p = java.security.AccessController.doPrivileged(
88 new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
89 DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
90 }
91
92 /* The original search path of URLs. */
93 private ArrayList<URL> path = new ArrayList<URL>();
94
95 /* The stack of unopened URLs */
96 Stack<URL> urls = new Stack<URL>();
97
98 /* The resulting search path of Loaders */
99 ArrayList<Loader> loaders = new ArrayList<Loader>();
100
101 /* Map of each URL opened to its corresponding Loader */
102 HashMap<URL, Loader> lmap = new HashMap<URL, Loader>();
103
104 /* The jar protocol handler to use when creating new URLs */
105 private URLStreamHandler jarHandler;
106
107 /**
108 * Creates a new URLClassPath for the given URLs. The URLs will be
109 * searched in the order specified for classes and resources. A URL
110 * ending with a '/' is assumed to refer to a directory. Otherwise,
111 * the URL is assumed to refer to a JAR file.
112 *
113 * @param urls the directory and JAR file URLs to search for classes
114 * and resources
115 * @param factory the URLStreamHandlerFactory to use when creating new URLs
116 */
117 public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
118 for (int i = 0; i < urls.length; i++) {
119 path.add(urls[i]);
120 }
121 push(urls);
122 if (factory != null) {
130
131 /**
132 * Appends the specified URL to the search path of directory and JAR
133 * file URLs from which to load classes and resources.
134 */
135 public void addURL(URL url) {
136 synchronized (urls) {
137 if (path.contains(url))
138 return;
139
140 urls.add(0, url);
141 path.add(url);
142 }
143 }
144
145 /**
146 * Returns the original search path of URLs.
147 */
148 public URL[] getURLs() {
149 synchronized (urls) {
150 return path.toArray(new URL[path.size()]);
151 }
152 }
153
154 /**
155 * Finds the resource with the specified name on the URL search path
156 * or null if not found or security check fails.
157 *
158 * @param name the name of the resource
159 * @param check whether to perform a security check
160 * @return a <code>URL</code> for the resource, or <code>null</code>
161 * if the resource could not be found.
162 */
163 public URL findResource(String name, boolean check) {
164 Loader loader;
165 for (int i = 0; (loader = getLoader(i)) != null; i++) {
166 URL url = loader.findResource(name, check);
167 if (url != null) {
168 return url;
169 }
170 }
184 System.err.println("URLClassPath.getResource(\"" + name + "\")");
185 }
186
187 Loader loader;
188 for (int i = 0; (loader = getLoader(i)) != null; i++) {
189 Resource res = loader.getResource(name, check);
190 if (res != null) {
191 return res;
192 }
193 }
194 return null;
195 }
196
197 /**
198 * Finds all resources on the URL search path with the given name.
199 * Returns an enumeration of the URL objects.
200 *
201 * @param name the resource name
202 * @return an Enumeration of all the urls having the specified name
203 */
204 public Enumeration<URL> findResources(final String name,
205 final boolean check) {
206 return new Enumeration<URL>() {
207 private int index = 0;
208 private URL url = null;
209
210 private boolean next() {
211 if (url != null) {
212 return true;
213 } else {
214 Loader loader;
215 while ((loader = getLoader(index++)) != null) {
216 url = loader.findResource(name, check);
217 if (url != null) {
218 return true;
219 }
220 }
221 return false;
222 }
223 }
224
225 public boolean hasMoreElements() {
226 return next();
227 }
228
229 public URL nextElement() {
230 if (!next()) {
231 throw new NoSuchElementException();
232 }
233 URL u = url;
234 url = null;
235 return u;
236 }
237 };
238 }
239
240 public Resource getResource(String name) {
241 return getResource(name, true);
242 }
243
244 /**
245 * Finds all resources on the URL search path with the given name.
246 * Returns an enumeration of the Resource objects.
247 *
248 * @param name the resource name
249 * @return an Enumeration of all the resources having the specified name
250 */
251 public Enumeration<Resource> getResources(final String name,
252 final boolean check) {
253 return new Enumeration<Resource>() {
254 private int index = 0;
255 private Resource res = null;
256
257 private boolean next() {
258 if (res != null) {
259 return true;
260 } else {
261 Loader loader;
262 while ((loader = getLoader(index++)) != null) {
263 res = loader.getResource(name, check);
264 if (res != null) {
265 return true;
266 }
267 }
268 return false;
269 }
270 }
271
272 public boolean hasMoreElements() {
273 return next();
274 }
275
276 public Resource nextElement() {
277 if (!next()) {
278 throw new NoSuchElementException();
279 }
280 Resource r = res;
281 res = null;
282 return r;
283 }
284 };
285 }
286
287 public Enumeration<Resource> getResources(final String name) {
288 return getResources(name, true);
289 }
290
291 /*
292 * Returns the Loader at the specified position in the URL search
293 * path. The URLs are opened and expanded as needed. Returns null
294 * if the specified index is out of range.
295 */
296 private synchronized Loader getLoader(int index) {
297 // Expand URL search path until the request can be satisfied
298 // or the URL stack is empty.
299 while (loaders.size() < index + 1) {
300 // Pop the next URL from the URL stack
301 URL url;
302 synchronized (urls) {
303 if (urls.empty()) {
304 return null;
305 } else {
306 url = urls.pop();
307 }
308 }
309 // Skip this URL if it already has a Loader. (Loader
310 // may be null in the case where URL has not been opened
311 // but is referenced by a JAR index.)
312 if (lmap.containsKey(url)) {
313 continue;
314 }
315 // Otherwise, create a new Loader for the URL.
316 Loader loader;
317 try {
318 loader = getLoader(url);
319 // If the loader defines a local class path then add the
320 // URLs to the list of URLs to be opened.
321 URL[] urls = loader.getClassPath();
322 if (urls != null) {
323 push(urls);
324 }
325 } catch (IOException e) {
326 // Silently ignore for now...
327 continue;
328 }
329 // Finally, add the Loader to the search path.
330 loaders.add(loader);
331 lmap.put(url, loader);
332 }
333 return loaders.get(index);
334 }
335
336 /*
337 * Returns the Loader for the specified base URL.
338 */
339 private Loader getLoader(final URL url) throws IOException {
340 try {
341 return java.security.AccessController.doPrivileged(
342 new java.security.PrivilegedExceptionAction<Loader>() {
343 public Loader run() throws IOException {
344 String file = url.getFile();
345 if (file != null && file.endsWith("/")) {
346 if ("file".equals(url.getProtocol())) {
347 return new FileLoader(url);
348 } else {
349 return new Loader(url);
350 }
351 } else {
352 return new JarLoader(url, jarHandler, lmap);
353 }
354 }
355 });
356 } catch (java.security.PrivilegedActionException pae) {
357 throw (IOException)pae.getException();
358 }
359 }
360
361 /*
362 * Pushes the specified URLs onto the list of unopened URLs.
363 */
545 return getResource(name, true);
546 }
547
548 /*
549 * Returns the local class path for this loader, or null if none.
550 */
551 URL[] getClassPath() throws IOException {
552 return null;
553 }
554 }
555
556 /*
557 * Inner class used to represent a Loader of resources from a JAR URL.
558 */
559 static class JarLoader extends Loader {
560 private JarFile jar;
561 private URL csu;
562 private JarIndex index;
563 private MetaIndex metaIndex;
564 private URLStreamHandler handler;
565 private HashMap<URL, Loader> lmap;
566 private static final sun.misc.JavaUtilZipFileAccess zipAccess =
567 sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
568
569 /*
570 * Creates a new JarLoader for the specified URL referring to
571 * a JAR file.
572 */
573 JarLoader(URL url, URLStreamHandler jarHandler,
574 HashMap<URL, Loader> loaderMap)
575 throws IOException
576 {
577 super(new URL("jar", "", -1, url + "!/", jarHandler));
578 csu = url;
579 handler = jarHandler;
580 lmap = loaderMap;
581
582 if (!isOptimizable(url)) {
583 ensureOpen();
584 } else {
585 String fileName = url.getFile();
586 if (fileName != null) {
587 fileName = ParseUtil.decode(fileName);
588 File f = new File(fileName);
589 metaIndex = MetaIndex.forJar(f);
590 // If the meta index is found but the file is not
591 // installed, set metaIndex to null. A typical
592 // senario is charsets.jar which won't be installed
593 // when the user is running in certain locale environment.
594 // The side effect of null metaIndex will cause
602 // entry recorded in meta-index file or such jar file is
603 // missing in JRE. See bug 6340399.
604 if (metaIndex == null) {
605 ensureOpen();
606 }
607 }
608 }
609
610 JarFile getJarFile () {
611 return jar;
612 }
613
614 private boolean isOptimizable(URL url) {
615 return "file".equals(url.getProtocol());
616 }
617
618 private void ensureOpen() throws IOException {
619 if (jar == null) {
620 try {
621 java.security.AccessController.doPrivileged(
622 new java.security.PrivilegedExceptionAction<Void>() {
623 public Void run() throws IOException {
624 if (DEBUG) {
625 System.err.println("Opening " + csu);
626 Thread.dumpStack();
627 }
628
629 jar = getJarFile(csu);
630 index = JarIndex.getJarIndex(jar, metaIndex);
631 if (index != null) {
632 String[] jarfiles = index.getJarFiles();
633 // Add all the dependent URLs to the lmap so that loaders
634 // will not be created for them by URLClassPath.getLoader(int)
635 // if the same URL occurs later on the main class path. We set
636 // Loader to null here to avoid creating a Loader for each
637 // URL until we actually need to try to load something from them.
638 for(int i = 0; i < jarfiles.length; i++) {
639 try {
640 URL jarURL = new URL(csu, jarfiles[i]);
641 // If a non-null loader already exists, leave it alone.
642 if (!lmap.containsKey(jarURL)) {
643 lmap.put(jarURL, null);
728 { return entry.getCertificates(); };
729 public CodeSigner[] getCodeSigners()
730 { return entry.getCodeSigners(); };
731 };
732 }
733
734
735 /*
736 * Returns true iff atleast one resource in the jar file has the same
737 * package name as that of the specified resource name.
738 */
739 boolean validIndex(final String name) {
740 String packageName = name;
741 int pos;
742 if((pos = name.lastIndexOf("/")) != -1) {
743 packageName = name.substring(0, pos);
744 }
745
746 String entryName;
747 ZipEntry entry;
748 Enumeration<JarEntry> enum_ = jar.entries();
749 while (enum_.hasMoreElements()) {
750 entry = enum_.nextElement();
751 entryName = entry.getName();
752 if((pos = entryName.lastIndexOf("/")) != -1)
753 entryName = entryName.substring(0, pos);
754 if (entryName.equals(packageName)) {
755 return true;
756 }
757 }
758 return false;
759 }
760
761 /*
762 * Returns the URL for a resource with the specified name
763 */
764 URL findResource(final String name, boolean check) {
765 Resource rsc = getResource(name, check);
766 if (rsc != null) {
767 return rsc.getURL();
768 }
769 return null;
770 }
774 */
775 Resource getResource(final String name, boolean check) {
776 if (metaIndex != null) {
777 if (!metaIndex.mayContain(name)) {
778 return null;
779 }
780 }
781
782 try {
783 ensureOpen();
784 } catch (IOException e) {
785 throw (InternalError) new InternalError().initCause(e);
786 }
787 final JarEntry entry = jar.getJarEntry(name);
788 if (entry != null)
789 return checkResource(name, check, entry);
790
791 if (index == null)
792 return null;
793
794 HashSet<URL> visited = new HashSet<URL>();
795 return getResource(name, check, visited);
796 }
797
798 /*
799 * Version of getResource() that tracks the jar files that have been
800 * visited by linking through the index files. This helper method uses
801 * a HashSet to store the URLs of jar files that have been searched and
802 * uses it to avoid going into an infinite loop, looking for a
803 * non-existent resource
804 */
805 Resource getResource(final String name, boolean check,
806 Set<URL> visited) {
807
808 Resource res;
809 Object[] jarFiles;
810 boolean done = false;
811 int count = 0;
812 LinkedList jarFilesList = null;
813
814 /* If there no jar files in the index that can potential contain
815 * this resource then return immediately.
816 */
817 if((jarFilesList = index.get(name)) == null)
818 return null;
819
820 do {
821 jarFiles = jarFilesList.toArray();
822 int size = jarFilesList.size();
823 /* loop through the mapped jar file list */
824 while(count < size) {
825 String jarName = (String)jarFiles[count++];
826 JarLoader newLoader;
827 final URL url;
828
829 try{
830 url = new URL(csu, jarName);
831 if ((newLoader = (JarLoader)lmap.get(url)) == null) {
832 /* no loader has been set up for this jar file
833 * before
834 */
835 newLoader = AccessController.doPrivileged(
836 new PrivilegedExceptionAction<JarLoader>() {
837 public JarLoader run() throws IOException {
838 return new JarLoader(url, handler,
839 lmap);
840 }
841 });
842
843 /* this newly opened jar file has its own index,
844 * merge it into the parent's index, taking into
845 * account the relative path.
846 */
847 JarIndex newIndex = newLoader.getIndex();
848 if(newIndex != null) {
849 int pos = jarName.lastIndexOf("/");
850 newIndex.merge(this.index, (pos == -1 ?
851 null : jarName.substring(0, pos + 1)));
852 }
853
854 /* put it in the global hashtable */
855 lmap.put(url, newLoader);
856 }
857 } catch (java.security.PrivilegedActionException pae) {
|