1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 package com.explosion.utilities.classes;
66
67 import java.io.File;
68 import java.io.FilePermission;
69 import java.io.IOException;
70 import java.io.InputStream;
71 import java.net.JarURLConnection;
72 import java.net.MalformedURLException;
73 import java.net.URL;
74 import java.net.URLClassLoader;
75 import java.net.URLConnection;
76 import java.net.URLStreamHandler;
77 import java.net.URLStreamHandlerFactory;
78 import java.security.AccessControlException;
79 import java.security.CodeSource;
80 import java.security.Permission;
81 import java.security.PermissionCollection;
82 import java.security.Policy;
83 import java.util.ArrayList;
84 import java.util.Enumeration;
85 import java.util.HashMap;
86 import java.util.Iterator;
87 import java.util.jar.JarFile;
88 import java.util.jar.JarInputStream;
89 import java.util.jar.Manifest;
90
91
92 /***
93 * Subclass implementation of <b>java.net.URLClassLoader</b> that knows how
94 * to load classes from disk directories, as well as local and remote JAR
95 * files. It also implements the <code>Reloader</code> interface, to provide
96 * automatic reloading support to the associated loader.
97 * <p>
98 * In all cases, URLs must conform to the contract specified by
99 * <code>URLClassLoader</code> - any URL that ends with a "/" character is
100 * assumed to represent a directory; all other URLs are assumed to be the
101 * address of a JAR file.
102 * <p>
103 * <strong>IMPLEMENTATION NOTE</strong> - Local repositories are searched in
104 * the order they are added via the initial constructor and/or any subsequent
105 * calls to <code>addRepository()</code>.
106 * <p>
107 * <strong>IMPLEMENTATION NOTE</strong> - At present, there are no dependencies
108 * from this class to any other Catalina class, so that it could be used
109 * independently.
110 *
111 * @author Craig R. McClanahan
112 * @author Remy Maucherat
113 * @version $Revision: 1.3 $ $Date: 2005/07/06 10:13:42 $
114 */
115
116 public class StandardClassLoader
117 extends URLClassLoader {
118
119
120
121
122
123 /***
124 * Construct a new ClassLoader with no defined repositories and no
125 * parent ClassLoader.
126 */
127 public StandardClassLoader() {
128
129 super(new URL[0]);
130 this.parent = getParent();
131 this.system = getSystemClassLoader();
132 securityManager = System.getSecurityManager();
133 }
134
135
136 /***
137 * Construct a new ClassLoader with no defined repositories and no
138 * parent ClassLoader, but with a stream handler factory.
139 *
140 * @param factory the URLStreamHandlerFactory to use when creating URLs
141 */
142 public StandardClassLoader(URLStreamHandlerFactory factory) {
143
144 super(new URL[0], null, factory);
145 this.factory = factory;
146
147 }
148
149
150 /***
151 * Construct a new ClassLoader with no defined repositories and the
152 * specified parent ClassLoader.
153 *
154 * @param parent The parent ClassLoader
155 */
156 public StandardClassLoader(ClassLoader parent) {
157
158 super((new URL[0]), parent);
159 this.parent = parent;
160 this.system = getSystemClassLoader();
161 securityManager = System.getSecurityManager();
162
163 }
164
165
166 /***
167 * Construct a new ClassLoader with no defined repositories and the
168 * specified parent ClassLoader.
169 *
170 * @param parent The parent ClassLoader
171 * @param factory the URLStreamHandlerFactory to use when creating URLs
172 */
173 public StandardClassLoader(ClassLoader parent,
174 URLStreamHandlerFactory factory) {
175
176 super((new URL[0]), parent, factory);
177 this.factory = factory;
178
179 }
180
181
182 /***
183 * Construct a new ClassLoader with the specified repositories and
184 * no parent ClassLoader.
185 *
186 * @param repositories The initial set of repositories
187 */
188 public StandardClassLoader(String repositories[]) {
189
190 super(convert(repositories));
191 this.parent = getParent();
192 this.system = getSystemClassLoader();
193 securityManager = System.getSecurityManager();
194 if (repositories != null) {
195 for (int i = 0; i < repositories.length; i++)
196 addRepositoryInternal(repositories[i]);
197 }
198
199 }
200
201
202 /***
203 * Construct a new ClassLoader with the specified repositories and
204 * parent ClassLoader.
205 *
206 * @param repositories The initial set of repositories
207 * @param parent The parent ClassLoader
208 */
209 public StandardClassLoader(String repositories[], ClassLoader parent) {
210
211 super(convert(repositories), parent);
212 this.parent = parent;
213 this.system = getSystemClassLoader();
214 securityManager = System.getSecurityManager();
215 if (repositories != null) {
216 for (int i = 0; i < repositories.length; i++)
217 addRepositoryInternal(repositories[i]);
218 }
219
220 }
221
222
223 /***
224 * Construct a new ClassLoader with the specified repositories and
225 * parent ClassLoader.
226 *
227 * @param repositories The initial set of repositories
228 * @param parent The parent ClassLoader
229 */
230 public StandardClassLoader(URL repositories[], ClassLoader parent) {
231
232 super(repositories, parent);
233 this.parent = parent;
234 this.system = getSystemClassLoader();
235 securityManager = System.getSecurityManager();
236 if (repositories != null) {
237 for (int i = 0; i < repositories.length; i++)
238 addRepositoryInternal(repositories[i].toString());
239 }
240
241 }
242
243
244
245
246
247 /***
248 * The set of optional packages (formerly standard extensions) that
249 * are available in the repositories associated with this class loader.
250 * Each object in this list is of type
251 * <code>org.apache.catalina.loader.Extension</code>.
252 */
253 protected ArrayList available = new ArrayList();
254
255
256 /***
257 * The debugging detail level of this component.
258 */
259 protected int debug = 0;
260
261
262 /***
263 * Should this class loader delegate to the parent class loader
264 * <strong>before</strong> searching its own repositories (i.e. the
265 * usual Java2 delegation model)? If set to <code>false</code>,
266 * this class loader will search its own repositories first, and
267 * delegate to the parent only if the class or resource is not
268 * found locally.
269 */
270 protected boolean delegate = false;
271
272
273 /***
274 * The list of local repositories, in the order they should be searched
275 * for locally loaded classes or resources.
276 */
277 protected String repositories[] = new String[0];
278
279
280 /***
281 * The set of optional packages (formerly standard extensions) that
282 * are required in the repositories associated with this class loader.
283 * Each object in this list is of type
284 * <code>org.apache.catalina.loader.Extension</code>.
285 */
286 protected ArrayList required = new ArrayList();
287
288
289 /***
290 * A list of read File and Jndi Permission's required if this loader
291 * is for a web application context.
292 */
293 private ArrayList permissionList = new ArrayList();
294
295
296 /***
297 * The PermissionCollection for each CodeSource for a web
298 * application context.
299 */
300 private HashMap loaderPC = new HashMap();
301
302
303 /***
304 * Instance of the SecurityManager installed.
305 */
306 private SecurityManager securityManager = null;
307
308
309 /***
310 * Flag that the security policy has been refreshed from file.
311 */
312 private boolean policy_refresh = false;
313
314 /***
315 * The parent class loader.
316 */
317 private ClassLoader parent = null;
318
319
320 /***
321 * The system class loader.
322 */
323 private ClassLoader system = null;
324
325
326 /***
327 * URL stream handler for additional protocols.
328 */
329 protected URLStreamHandlerFactory factory = null;
330
331
332
333
334
335 /***
336 * Return the debugging detail level for this component.
337 */
338 public int getDebug() {
339
340 return (this.debug);
341
342 }
343
344
345 /***
346 * Set the debugging detail level for this component.
347 *
348 * @param debug The new debugging detail level
349 */
350 public void setDebug(int debug) {
351
352 this.debug = debug;
353
354 }
355
356
357 /***
358 * Return the "delegate first" flag for this class loader.
359 */
360 public boolean getDelegate() {
361
362 return (this.delegate);
363
364 }
365
366
367 /***
368 * Set the "delegate first" flag for this class loader.
369 *
370 * @param delegate The new "delegate first" flag
371 */
372 public void setDelegate(boolean delegate) {
373
374 this.delegate = delegate;
375
376 }
377
378
379 /***
380 * If there is a Java SecurityManager create a read FilePermission
381 * or JndiPermission for the file directory path.
382 *
383 * @param path file directory path
384 */
385 public void setPermissions(String path) {
386 if( securityManager != null ) {
387 if( path.startsWith("jndi:") || path.startsWith("jar:jndi:") ) {
388 permissionList.add(new JndiPermission(path + "*"));
389 } else {
390 permissionList.add(new FilePermission(path + "-","read"));
391 }
392 }
393 }
394
395
396 /***
397 * If there is a Java SecurityManager add a read FilePermission
398 * or JndiPermission for URL.
399 *
400 * @param url URL for a file or directory on local system
401 */
402 public void setPermissions(URL url) {
403 setPermissions(url.toString());
404 }
405
406
407
408
409
410 /***
411 * Add a new repository to the set of places this ClassLoader can look for
412 * classes to be loaded.
413 *
414 * @param repository Name of a source of classes to be loaded, such as a
415 * directory pathname, a JAR file pathname, or a ZIP file pathname
416 *
417 * @exception IllegalArgumentException if the specified repository is
418 * invalid or does not exist
419 */
420 public void addRepository(String repository) {
421
422 if (debug >= 1)
423 log("addRepository(" + repository + ")");
424
425
426 try {
427 URLStreamHandler streamHandler = null;
428 String protocol = parseProtocol(repository);
429 if (factory != null)
430 streamHandler = factory.createURLStreamHandler(protocol);
431 URL url = new URL(null, repository, streamHandler);
432 super.addURL(url);
433 } catch (MalformedURLException e) {
434 throw new IllegalArgumentException(e.toString());
435 }
436
437
438 addRepositoryInternal(repository);
439
440 }
441
442
443 /***
444 * Return a list of "optional packages" (formerly "standard extensions")
445 * that have been declared to be available in the repositories associated
446 * with this class loader, plus any parent class loader implemented with
447 * the same class.
448 */
449 public Extension[] findAvailable() {
450
451
452 ArrayList results = new ArrayList();
453 Iterator available = this.available.iterator();
454 while (available.hasNext())
455 results.add(available.next());
456
457
458 ClassLoader loader = this;
459 while (true) {
460 loader = loader.getParent();
461 if (loader == null)
462 break;
463 if (!(loader instanceof StandardClassLoader))
464 continue;
465 Extension extensions[] =
466 ((StandardClassLoader) loader).findAvailable();
467 for (int i = 0; i < extensions.length; i++)
468 results.add(extensions[i]);
469 }
470
471
472 Extension extensions[] = new Extension[results.size()];
473 return ((Extension[]) results.toArray(extensions));
474
475 }
476
477
478 /***
479 * Return a String array of the current repositories for this class
480 * loader. If there are no repositories, a zero-length array is
481 * returned.
482 */
483 public String[] findRepositories() {
484
485 return (repositories);
486
487 }
488
489
490 /***
491 * Return a list of "optional packages" (formerly "standard extensions")
492 * that have been declared to be required in the repositories associated
493 * with this class loader, plus any parent class loader implemented with
494 * the same class.
495 */
496 public Extension[] findRequired() {
497
498
499 ArrayList results = new ArrayList();
500 Iterator required = this.required.iterator();
501 while (required.hasNext())
502 results.add(required.next());
503
504
505 ClassLoader loader = this;
506 while (true) {
507 loader = loader.getParent();
508 if (loader == null)
509 break;
510 if (!(loader instanceof StandardClassLoader))
511 continue;
512 Extension extensions[] =
513 ((StandardClassLoader) loader).findRequired();
514 for (int i = 0; i < extensions.length; i++)
515 results.add(extensions[i]);
516 }
517
518
519 Extension extensions[] = new Extension[results.size()];
520 return ((Extension[]) results.toArray(extensions));
521
522 }
523
524
525 /***
526 * This class loader doesn't check for reloading.
527 */
528 public boolean modified() {
529
530 return (false);
531
532 }
533
534
535 /***
536 * Render a String representation of this object.
537 */
538 public String toString() {
539
540 StringBuffer sb = new StringBuffer("StandardClassLoader\r\n");
541 sb.append(" available:\r\n");
542 Iterator available = this.available.iterator();
543 while (available.hasNext()) {
544 sb.append(" ");
545 sb.append(available.next().toString());
546 sb.append("\r\n");
547 }
548 sb.append(" delegate: ");
549 sb.append(delegate);
550 sb.append("\r\n");
551 sb.append(" repositories:\r\n");
552 for (int i = 0; i < repositories.length; i++) {
553 sb.append(" ");
554 sb.append(repositories[i]);
555 sb.append("\r\n");
556 }
557 sb.append(" required:\r\n");
558 Iterator required = this.required.iterator();
559 while (required.hasNext()) {
560 sb.append(" ");
561 sb.append(required.next().toString());
562 sb.append("\r\n");
563 }
564 if (this.parent != null) {
565 sb.append("----------> Parent Classloader:\r\n");
566 sb.append(this.parent.toString());
567 sb.append("\r\n");
568 }
569 return (sb.toString());
570
571 }
572
573
574
575
576
577 /***
578 * Find the specified class in our local repositories, if possible. If
579 * not found, throw <code>ClassNotFoundException</code>.
580 *
581 * @param name Name of the class to be loaded
582 *
583 * @exception ClassNotFoundException if the class was not found
584 */
585 public Class findClass(String name) throws ClassNotFoundException {
586
587 if (debug >= 3)
588 log(" findClass(" + name + ")");
589
590
591 if (securityManager != null) {
592 int i = name.lastIndexOf('.');
593 if (i >= 0) {
594 try {
595 if (debug >= 4)
596 log(" securityManager.checkPackageDefinition");
597 securityManager.checkPackageDefinition(name.substring(0,i));
598 } catch (Exception se) {
599 if (debug >= 4)
600 log(" -->Exception-->ClassNotFoundException", se);
601 throw new ClassNotFoundException(name);
602 }
603 }
604 }
605
606
607
608 Class clazz = null;
609 try {
610 if (debug >= 4)
611 log(" super.findClass(" + name + ")");
612 try {
613 synchronized (this) {
614 clazz = findLoadedClass(name);
615 if (clazz != null)
616 return clazz;
617 clazz = super.findClass(name);
618 }
619 } catch(AccessControlException ace) {
620 throw new ClassNotFoundException(name);
621 } catch (RuntimeException e) {
622 if (debug >= 4)
623 log(" -->RuntimeException Rethrown", e);
624 throw e;
625 }
626 if (clazz == null) {
627 if (debug >= 3)
628 log(" --> Returning ClassNotFoundException");
629 throw new ClassNotFoundException(name);
630 }
631 } catch (ClassNotFoundException e) {
632 if (debug >= 3)
633 log(" --> Passing on ClassNotFoundException", e);
634 throw e;
635 }
636
637
638 if (debug >= 4)
639 log(" Returning class " + clazz);
640 if ((debug >= 4) && (clazz != null))
641 log(" Loaded by " + clazz.getClassLoader());
642 return (clazz);
643
644 }
645
646
647 /***
648 * Find the specified resource in our local repository, and return a
649 * <code>URL</code> refering to it, or <code>null</code> if this resource
650 * cannot be found.
651 *
652 * @param name Name of the resource to be found
653 */
654 public URL findResource(String name) {
655
656 if (debug >= 3)
657 log(" findResource(" + name + ")");
658
659 URL url = super.findResource(name);
660 if (debug >= 3) {
661 if (url != null)
662 log(" --> Returning '" + url.toString() + "'");
663 else
664 log(" --> Resource not found, returning null");
665 }
666 return (url);
667
668 }
669
670
671 /***
672 * Return an eneration of <code>URLs</code> representing all of the
673 * resources with the given name. If no resources with this name are
674 * found, return an empty eneration.
675 *
676 * @param name Name of the resources to be found
677 *
678 * @exception IOException if an input/output error occurs
679 */
680 public Enumeration findResources(String name) throws IOException {
681
682 if (debug >= 3)
683 log(" findResources(" + name + ")");
684 return (super.findResources(name));
685
686 }
687
688
689 /***
690 * Find the resource with the given name. A resource is some data
691 * (images, audio, text, etc.) that can be accessed by class code in a
692 * way that is independent of the location of the code. The name of a
693 * resource is a "/"-separated path name that identifies the resource.
694 * If the resource cannot be found, return <code>null</code>.
695 * <p>
696 * This method searches according to the following algorithm, returning
697 * as soon as it finds the appropriate URL. If the resource cannot be
698 * found, returns <code>null</code>.
699 * <ul>
700 * <li>If the <code>delegate</code> property is set to <code>true</code>,
701 * call the <code>getResource()</code> method of the parent class
702 * loader, if any.</li>
703 * <li>Call <code>findResource()</code> to find this resource in our
704 * locally defined repositories.</li>
705 * <li>Call the <code>getResource()</code> method of the parent class
706 * loader, if any.</li>
707 * </ul>
708 *
709 * @param name Name of the resource to return a URL for
710 */
711 public URL getResource(String name) {
712
713 if (debug >= 2)
714 log("getResource(" + name + ")");
715 URL url = null;
716
717
718 if (delegate) {
719 if (debug >= 3)
720 log(" Delegating to parent classloader");
721 ClassLoader loader = parent;
722 if (loader == null)
723 loader = system;
724 url = loader.getResource(name);
725 if (url != null) {
726 if (debug >= 2)
727 log(" --> Returning '" + url.toString() + "'");
728 return (url);
729 }
730 }
731
732
733 if (debug >= 3)
734 log(" Searching local repositories");
735 url = findResource(name);
736 if (url != null) {
737 if (debug >= 2)
738 log(" --> Returning '" + url.toString() + "'");
739 return (url);
740 }
741
742
743 if( !delegate ) {
744 ClassLoader loader = parent;
745 if (loader == null)
746 loader = system;
747 url = loader.getResource(name);
748 if (url != null) {
749 if (debug >= 2)
750 log(" --> Returning '" + url.toString() + "'");
751 return (url);
752 }
753 }
754
755
756 if (debug >= 2)
757 log(" --> Resource not found, returning null");
758 return (null);
759
760 }
761
762
763 /***
764 * Find the resource with the given name, and return an input stream
765 * that can be used for reading it. The search order is as described
766 * for <code>getResource()</code>, after checking to see if the resource
767 * data has been previously cached. If the resource cannot be found,
768 * return <code>null</code>.
769 *
770 * @param name Name of the resource to return an input stream for
771 */
772 public InputStream getResourceAsStream(String name) {
773
774 if (debug >= 2)
775 log("getResourceAsStream(" + name + ")");
776 InputStream stream = null;
777
778
779 stream = findLoadedResource(name);
780 if (stream != null) {
781 if (debug >= 2)
782 log(" --> Returning stream from cache");
783 return (stream);
784 }
785
786
787 if (delegate) {
788 if (debug >= 3)
789 log(" Delegating to parent classloader");
790 ClassLoader loader = parent;
791 if (loader == null)
792 loader = system;
793 stream = loader.getResourceAsStream(name);
794 if (stream != null) {
795
796 if (debug >= 2)
797 log(" --> Returning stream from parent");
798 return (stream);
799 }
800 }
801
802
803 if (debug >= 3)
804 log(" Searching local repositories");
805 URL url = findResource(name);
806 if (url != null) {
807
808 if (debug >= 2)
809 log(" --> Returning stream from local");
810 try {
811 return (url.openStream());
812 } catch (IOException e) {
813 log("url.openStream(" + url.toString() + ")", e);
814 return (null);
815 }
816 }
817
818
819 if (!delegate) {
820 if (debug >= 3)
821 log(" Delegating to parent classloader");
822 ClassLoader loader = parent;
823 if (loader == null)
824 loader = system;
825 stream = loader.getResourceAsStream(name);
826 if (stream != null) {
827
828 if (debug >= 2)
829 log(" --> Returning stream from parent");
830 return (stream);
831 }
832 }
833
834
835 if (debug >= 2)
836 log(" --> Resource not found, returning null");
837 return (null);
838
839 }
840
841
842 /***
843 * Load the class with the specified name. This method searches for
844 * classes in the same manner as <code>loadClass(String, boolean)</code>
845 * with <code>false</code> as the second argument.
846 *
847 * @param name Name of the class to be loaded
848 *
849 * @exception ClassNotFoundException if the class was not found
850 */
851 public Class loadClass(String name) throws ClassNotFoundException {
852
853 return (loadClass(name, false));
854
855 }
856
857
858 /***
859 * Load the class with the specified name, searching using the following
860 * algorithm until it finds and returns the class. If the class cannot
861 * be found, returns <code>ClassNotFoundException</code>.
862 * <ul>
863 * <li>Call <code>findLoadedClass(String)</code> to check if the
864 * class has already been loaded. If it has, the same
865 * <code>Class</code> object is returned.</li>
866 * <li>If the <code>delegate</code> property is set to <code>true</code>,
867 * call the <code>loadClass()</code> method of the parent class
868 * loader, if any.</li>
869 * <li>Call <code>findClass()</code> to find this class in our locally
870 * defined repositories.</li>
871 * <li>Call the <code>loadClass()</code> method of our parent
872 * class loader, if any.</li>
873 * </ul>
874 * If the class was found using the above steps, and the
875 * <code>resolve</code> flag is <code>true</code>, this method will then
876 * call <code>resolveClass(Class)</code> on the resulting Class object.
877 *
878 * @param name Name of the class to be loaded
879 * @param resolve If <code>true</code> then resolve the class
880 *
881 * @exception ClassNotFoundException if the class was not found
882 */
883 public Class loadClass(String name, boolean resolve)
884 throws ClassNotFoundException {
885
886 if (debug >= 2)
887 log("loadClass(" + name + ", " + resolve + ")");
888 Class clazz = null;
889
890
891 clazz = findLoadedClass(name);
892 if (clazz != null) {
893 if (debug >= 3)
894 log(" Returning class from cache");
895 if (resolve)
896 resolveClass(clazz);
897 return (clazz);
898 }
899
900
901 if( name.startsWith("java.") ) {
902 ClassLoader loader = system;
903 clazz = loader.loadClass(name);
904 if (clazz != null) {
905 if (resolve)
906 resolveClass(clazz);
907 return (clazz);
908 }
909 throw new ClassNotFoundException(name);
910 }
911
912
913 if (securityManager != null) {
914 int i = name.lastIndexOf('.');
915 if (i >= 0) {
916 try {
917 securityManager.checkPackageAccess(name.substring(0,i));
918 } catch (SecurityException se) {
919 String error = "Security Violation, attempt to use " +
920 "Restricted Class: " + name;
921 System.out.println(error);
922 se.printStackTrace();
923 log(error);
924 throw new ClassNotFoundException(error);
925 }
926 }
927 }
928
929
930 if (delegate) {
931 if (debug >= 3)
932 log(" Delegating to parent classloader");
933 ClassLoader loader = parent;
934 if (loader == null)
935 loader = system;
936 try {
937 clazz = loader.loadClass(name);
938 if (clazz != null) {
939 if (debug >= 3)
940 log(" Loading class from parent");
941 if (resolve)
942 resolveClass(clazz);
943 return (clazz);
944 }
945 } catch (ClassNotFoundException e) {
946 ;
947 }
948 }
949
950
951 if (debug >= 3)
952 log(" Searching local repositories");
953 try {
954 clazz = findClass(name);
955 if (clazz != null) {
956 if (debug >= 3)
957 log(" Loading class from local repository");
958 if (resolve)
959 resolveClass(clazz);
960 return (clazz);
961 }
962 } catch (ClassNotFoundException e) {
963 ;
964 }
965
966
967 if (!delegate) {
968 if (debug >= 3)
969 log(" Delegating to parent classloader");
970 ClassLoader loader = parent;
971 if (loader == null)
972 loader = system;
973 try {
974 clazz = loader.loadClass(name);
975 if (clazz != null) {
976 if (debug >= 3)
977 log(" Loading class from parent");
978 if (resolve)
979 resolveClass(clazz);
980 return (clazz);
981 }
982 } catch (ClassNotFoundException e) {
983 ;
984 }
985 }
986
987
988 throw new ClassNotFoundException(name);
989
990 }
991
992
993 /***
994 * Get the Permissions for a CodeSource. If this instance
995 * of StandardClassLoader is for a web application context,
996 * add read FilePermissions for the base directory (if unpacked),
997 * the context URL, and jar file resources.
998 *
999 * @param CodeSource where the code was loaded from
1000 * @return PermissionCollection for CodeSource
1001 */
1002 protected final PermissionCollection getPermissions(CodeSource codeSource) {
1003 if (!policy_refresh) {
1004
1005 Policy policy = Policy.getPolicy();
1006 policy.refresh();
1007 policy_refresh = true;
1008 }
1009 String codeUrl = codeSource.getLocation().toString();
1010 PermissionCollection pc;
1011 if ((pc = (PermissionCollection)loaderPC.get(codeUrl)) == null) {
1012 pc = super.getPermissions(codeSource);
1013 if (pc != null) {
1014 Iterator perms = permissionList.iterator();
1015 while (perms.hasNext()) {
1016 Permission p = (Permission)perms.next();
1017 pc.add(p);
1018 }
1019 loaderPC.put(codeUrl,pc);
1020 }
1021 }
1022 return (pc);
1023
1024 }
1025
1026
1027
1028
1029
1030 /***
1031 * Parse URL protocol.
1032 *
1033 * @return String protocol
1034 */
1035 protected static String parseProtocol(String spec) {
1036 if (spec == null)
1037 return "";
1038 int pos = spec.indexOf(':');
1039 if (pos <= 0)
1040 return "";
1041 return spec.substring(0, pos).trim();
1042 }
1043
1044
1045 /***
1046 * Add a repository to our internal array only.
1047 *
1048 * @param repository The new repository
1049 *
1050 * @exception IllegalArgumentException if the manifest of a JAR file
1051 * cannot be processed correctly
1052 */
1053 protected void addRepositoryInternal(String repository) {
1054
1055 URLStreamHandler streamHandler = null;
1056 String protocol = parseProtocol(repository);
1057 if (factory != null)
1058 streamHandler = factory.createURLStreamHandler(protocol);
1059
1060
1061 if (!repository.endsWith(File.separator) &&
1062 !repository.endsWith("/")) {
1063 JarFile jarFile = null;
1064 try {
1065 Manifest manifest = null;
1066 if (repository.startsWith("jar:")) {
1067 URL url = new URL(null, repository, streamHandler);
1068 JarURLConnection conn =
1069 (JarURLConnection) url.openConnection();
1070 conn.setAllowUserInteraction(false);
1071 conn.setDoInput(true);
1072 conn.setDoOutput(false);
1073 conn.connect();
1074 jarFile = conn.getJarFile();
1075 } else if (repository.startsWith("file://")) {
1076 jarFile = new JarFile(repository.substring(7));
1077 } else if (repository.startsWith("file:")) {
1078 jarFile = new JarFile(repository.substring(5));
1079 } else if (repository.endsWith(".jar")) {
1080 URL url = new URL(null, repository, streamHandler);
1081 URLConnection conn = url.openConnection();
1082 JarInputStream jis =
1083 new JarInputStream(conn.getInputStream());
1084 manifest = jis.getManifest();
1085 } else {
1086 throw new IllegalArgumentException
1087 ("addRepositoryInternal: Invalid URL '" +
1088 repository + "'");
1089 }
1090 if (!((manifest == null) && (jarFile == null))) {
1091 if ((manifest == null) && (jarFile != null))
1092 manifest = jarFile.getManifest();
1093 if (manifest != null) {
1094 Iterator extensions =
1095 Extension.getAvailable(manifest).iterator();
1096 while (extensions.hasNext())
1097 available.add(extensions.next());
1098 extensions =
1099 Extension.getRequired(manifest).iterator();
1100 while (extensions.hasNext())
1101 required.add(extensions.next());
1102 }
1103 }
1104 } catch (Throwable t) {
1105 t.printStackTrace();
1106 throw new IllegalArgumentException
1107 ("addRepositoryInternal: " + t);
1108 } finally {
1109 if (jarFile != null) {
1110 try {
1111 jarFile.close();
1112 } catch (Throwable t) {}
1113 }
1114 }
1115 }
1116
1117
1118 synchronized (repositories) {
1119 String results[] = new String[repositories.length + 1];
1120 System.arraycopy(repositories, 0, results, 0, repositories.length);
1121 results[repositories.length] = repository;
1122 repositories = results;
1123 }
1124
1125 }
1126
1127
1128 /***
1129 * Convert an array of String to an array of URL and return it.
1130 *
1131 * @param input The array of String to be converted
1132 */
1133 protected static URL[] convert(String input[]) {
1134 return convert(input, null);
1135 }
1136
1137
1138 /***
1139 * Convert an array of String to an array of URL and return it.
1140 *
1141 * @param input The array of String to be converted
1142 * @param factory Handler factory to use to generate the URLs
1143 */
1144 protected static URL[] convert(String input[],
1145 URLStreamHandlerFactory factory) {
1146
1147 URLStreamHandler streamHandler = null;
1148
1149 URL url[] = new URL[input.length];
1150 for (int i = 0; i < url.length; i++) {
1151 try {
1152 String protocol = parseProtocol(input[i]);
1153 if (factory != null)
1154 streamHandler = factory.createURLStreamHandler(protocol);
1155 else
1156 streamHandler = null;
1157 url[i] = new URL(null, input[i], streamHandler);
1158 } catch (MalformedURLException e) {
1159 url[i] = null;
1160 }
1161 }
1162 return (url);
1163
1164 }
1165
1166
1167 /***
1168 * Finds the resource with the given name if it has previously been
1169 * loaded and cached by this class loader, and return an input stream
1170 * to the resource data. If this resource has not been cached, return
1171 * <code>null</code>.
1172 *
1173 * @param name Name of the resource to return
1174 */
1175 protected InputStream findLoadedResource(String name) {
1176
1177 return (null);
1178
1179 }
1180
1181
1182 /***
1183 * Log a debugging output message.
1184 *
1185 * @param message Message to be logged
1186 */
1187 private void log(String message) {
1188
1189
1190 System.out.println(message);
1191 }
1192
1193
1194 /***
1195 * Log a debugging output message with an exception.
1196 *
1197 * @param message Message to be logged
1198 * @param throwable Exception to be logged
1199 */
1200 private void log(String message, Throwable throwable) {
1201
1202 System.out.println("StandardClassLoader: " + message);
1203 throwable.printStackTrace(System.out);
1204
1205 }
1206
1207
1208 }
1209