1:
38:
39:
40: package ;
41:
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68:
69:
126: public class URLClassLoader extends SecureClassLoader
127: {
128:
129:
130:
136: private static HashMap urlloaders = new HashMap();
137:
138:
143: private static HashMap factoryCache = new HashMap(5);
144:
145:
146:
147:
148: private final Vector urls = new Vector();
149:
150:
156: private final Vector urlinfos = new Vector();
157:
158:
159: private final URLStreamHandlerFactory factory;
160:
161:
166: private final AccessControlContext securityContext;
167:
168:
169:
170:
174: abstract static class URLLoader
175: {
176:
179: final URLClassLoader classloader;
180:
181:
184: final URL baseURL;
185:
186:
193: final CodeSource noCertCodeSource;
194:
195: URLLoader(URLClassLoader classloader, URL baseURL)
196: {
197: this(classloader, baseURL, baseURL);
198: }
199:
200: URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
201: {
202: this.classloader = classloader;
203: this.baseURL = baseURL;
204: this.noCertCodeSource = new CodeSource(overrideURL, null);
205: }
206:
207:
213: Class getClass(String className)
214: {
215: return null;
216: }
217:
218:
223: abstract Resource getResource(String s);
224:
225:
230: Manifest getManifest()
231: {
232: return null;
233: }
234:
235: Vector getClassPath()
236: {
237: return null;
238: }
239: }
240:
241:
248: abstract static class Resource
249: {
250: final URLLoader loader;
251:
252: Resource(URLLoader loader)
253: {
254: this.loader = loader;
255: }
256:
257:
261: CodeSource getCodeSource()
262: {
263: Certificate[] certs = getCertificates();
264: if (certs == null)
265: return loader.noCertCodeSource;
266: else
267: return new CodeSource(loader.baseURL, certs);
268: }
269:
270:
274: Certificate[] getCertificates()
275: {
276: return null;
277: }
278:
279:
282: abstract URL getURL();
283:
284:
288: abstract int getLength();
289:
290:
294: abstract InputStream getInputStream() throws IOException;
295: }
296:
297:
301: static final class JarURLLoader extends URLLoader
302: {
303: final JarFile jarfile;
304: final URL baseJarURL;
305:
306: Vector classPath;
307:
308: public JarURLLoader(URLClassLoader classloader, URL baseURL,
309: URL absoluteUrl)
310: {
311: super(classloader, baseURL, absoluteUrl);
312:
313:
314: String external = baseURL.toExternalForm();
315: StringBuffer sb = new StringBuffer(external.length() + 6);
316: sb.append("jar:");
317: sb.append(external);
318: sb.append("!/");
319: String jarURL = sb.toString();
320:
321: this.classPath = null;
322: URL baseJarURL = null;
323: JarFile jarfile = null;
324: try
325: {
326: baseJarURL =
327: new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
328:
329: jarfile =
330: ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
331:
332: Manifest manifest;
333: Attributes attributes;
334: String classPathString;
335:
336: if ((manifest = jarfile.getManifest()) != null
337: && (attributes = manifest.getMainAttributes()) != null
338: && ((classPathString
339: = attributes.getValue(Attributes.Name.CLASS_PATH))
340: != null))
341: {
342: this.classPath = new Vector();
343:
344: StringTokenizer st = new StringTokenizer(classPathString, " ");
345: while (st.hasMoreElements ())
346: {
347: String e = st.nextToken ();
348: try
349: {
350: URL url = new URL(baseURL, e);
351: this.classPath.add(url);
352: }
353: catch (java.net.MalformedURLException xx)
354: {
355:
356: }
357: }
358: }
359: }
360: catch (IOException ioe)
361: {
362:
363: }
364:
365: this.baseJarURL = baseJarURL;
366: this.jarfile = jarfile;
367: }
368:
369:
370: Resource getResource(String name)
371: {
372: if (jarfile == null)
373: return null;
374:
375: if (name.startsWith("/"))
376: name = name.substring(1);
377:
378: JarEntry je = jarfile.getJarEntry(name);
379: if (je != null)
380: return new JarURLResource(this, name, je);
381: else
382: return null;
383: }
384:
385: Manifest getManifest()
386: {
387: try
388: {
389: return (jarfile == null) ? null : jarfile.getManifest();
390: }
391: catch (IOException ioe)
392: {
393: return null;
394: }
395: }
396:
397: Vector getClassPath()
398: {
399: return classPath;
400: }
401: }
402:
403: static final class JarURLResource extends Resource
404: {
405: private final JarEntry entry;
406: private final String name;
407:
408: JarURLResource(JarURLLoader loader, String name, JarEntry entry)
409: {
410: super(loader);
411: this.entry = entry;
412: this.name = name;
413: }
414:
415: InputStream getInputStream() throws IOException
416: {
417: return ((JarURLLoader) loader).jarfile.getInputStream(entry);
418: }
419:
420: int getLength()
421: {
422: return (int) entry.getSize();
423: }
424:
425: Certificate[] getCertificates()
426: {
427:
428:
429:
430: return ((JarEntry) ((JarURLLoader) loader).jarfile.getEntry(name))
431: .getCertificates();
432: }
433:
434: URL getURL()
435: {
436: try
437: {
438: return new URL(((JarURLLoader) loader).baseJarURL, name,
439: loader.classloader.getURLStreamHandler("jar"));
440: }
441: catch (MalformedURLException e)
442: {
443: InternalError ie = new InternalError();
444: ie.initCause(e);
445: throw ie;
446: }
447: }
448: }
449:
450:
453: static final class RemoteURLLoader extends URLLoader
454: {
455: private final String protocol;
456:
457: RemoteURLLoader(URLClassLoader classloader, URL url)
458: {
459: super(classloader, url);
460: protocol = url.getProtocol();
461: }
462:
463:
467: Resource getResource(String name)
468: {
469: try
470: {
471: URL url =
472: new URL(baseURL, name, classloader.getURLStreamHandler(protocol));
473: URLConnection connection = url.openConnection();
474:
475:
476:
477: int length = connection.getContentLength();
478: InputStream stream = connection.getInputStream();
479:
480:
481: if (connection instanceof HttpURLConnection)
482: {
483: int response =
484: ((HttpURLConnection) connection).getResponseCode();
485: if (response / 100 != 2)
486: return null;
487: }
488:
489: if (stream != null)
490: return new RemoteResource(this, name, url, stream, length);
491: else
492: return null;
493: }
494: catch (IOException ioe)
495: {
496: return null;
497: }
498: }
499: }
500:
501:
504: static final class RemoteResource extends Resource
505: {
506: private final URL url;
507: private final InputStream stream;
508: private final int length;
509:
510: RemoteResource(RemoteURLLoader loader, String name, URL url,
511: InputStream stream, int length)
512: {
513: super(loader);
514: this.url = url;
515: this.stream = stream;
516: this.length = length;
517: }
518:
519: InputStream getInputStream() throws IOException
520: {
521: return stream;
522: }
523:
524: public int getLength()
525: {
526: return length;
527: }
528:
529: public URL getURL()
530: {
531: return url;
532: }
533: }
534:
535:
539: final static class SoURLLoader extends URLLoader
540: {
541: SharedLibHelper helper;
542:
543: SoURLLoader(URLClassLoader classloader, URL url)
544: {
545: this(classloader, url, url);
546: }
547:
548: SoURLLoader(URLClassLoader classloader, URL url, URL overrideURL)
549: {
550: super(classloader, url, overrideURL);
551: helper = SharedLibHelper.findHelper(classloader, url.getFile(),
552: noCertCodeSource, true);
553: }
554:
555: Class getClass(String className)
556: {
557: return helper.findClass(className);
558: }
559:
560: Resource getResource(String name)
561: {
562: URL url = helper.findResource(name);
563: if (url == null)
564: return null;
565: return new SoResource(this, url);
566: }
567: }
568:
569: final static class SoResource extends Resource
570: {
571: SoResource(SoURLLoader loader, URL url)
572: {
573: super(loader);
574: this.url = url;
575: }
576:
577: InputStream getInputStream() throws IOException
578: {
579: URLConnection conn = url.openConnection();
580: return conn.getInputStream();
581: }
582:
583: public int getLength()
584: {
585:
586: return -1;
587: }
588:
589: public URL getURL ()
590: {
591: return url;
592: }
593:
594: final URL url;
595: }
596:
597:
601: static final class FileURLLoader extends URLLoader
602: {
603: File dir;
604:
605: FileURLLoader(URLClassLoader classloader, URL url, URL absoluteUrl)
606: {
607: super(classloader, url, absoluteUrl);
608: dir = new File(absoluteUrl.getFile());
609: }
610:
611:
612: Resource getResource(String name)
613: {
614: try
615: {
616: File file = new File(dir, name).getCanonicalFile();
617: if (file.exists() && !file.isDirectory())
618: return new FileResource(this, file);
619: }
620: catch (IOException e)
621: {
622:
623: }
624: return null;
625: }
626: }
627:
628: static final class FileResource extends Resource
629: {
630: final File file;
631:
632: FileResource(FileURLLoader loader, File file)
633: {
634: super(loader);
635: this.file = file;
636: }
637:
638: InputStream getInputStream() throws IOException
639: {
640:
641:
642: if (file.isDirectory())
643: {
644: URL url = getURL();
645: return url.openStream();
646: }
647:
648: return new FileInputStream(file);
649: }
650:
651: public int getLength()
652: {
653:
654:
655:
656: if (file.isDirectory())
657: {
658: URL url = getURL();
659: try
660: {
661: URLConnection connection = url.openConnection();
662: return connection.getContentLength();
663: }
664: catch (IOException e)
665: {
666: return -1;
667: }
668: }
669:
670: return (int) file.length();
671: }
672:
673: public URL getURL()
674: {
675: try
676: {
677: return file.toURL();
678: }
679: catch (MalformedURLException e)
680: {
681: InternalError ie = new InternalError();
682: ie.initCause(e);
683: throw ie;
684: }
685: }
686: }
687:
688:
692: static final class CoreURLLoader extends URLLoader
693: {
694: private String dir;
695:
696: CoreURLLoader(URLClassLoader classloader, URL url)
697: {
698: super(classloader, url);
699: dir = baseURL.getFile();
700: }
701:
702:
703: Resource getResource(String name)
704: {
705: Core core = Core.find (dir + name);
706: if (core != null)
707: return new CoreResource(this, name, core);
708: return null;
709: }
710: }
711:
712: static final class CoreResource extends Resource
713: {
714: private final Core core;
715: private final String name;
716:
717: CoreResource(CoreURLLoader loader, String name, Core core)
718: {
719: super(loader);
720: this.core = core;
721: this.name = name;
722: }
723:
724: InputStream getInputStream() throws IOException
725: {
726: return new CoreInputStream(core);
727: }
728:
729: public int getLength()
730: {
731: return core.length;
732: }
733:
734: public URL getURL()
735: {
736: try
737: {
738: return new URL(loader.baseURL, name,
739: loader.classloader.getURLStreamHandler("core"));
740: }
741: catch (MalformedURLException e)
742: {
743: InternalError ie = new InternalError();
744: ie.initCause(e);
745: throw ie;
746: }
747: }
748: }
749:
750:
751:
752:
766: public URLClassLoader(URL[] urls) throws SecurityException
767: {
768: super();
769: this.factory = null;
770: this.securityContext = null;
771: addURLs(urls);
772: }
773:
774:
791: public URLClassLoader(URL[] urls, ClassLoader parent)
792: throws SecurityException
793: {
794: super(parent);
795: this.factory = null;
796: this.securityContext = null;
797: addURLs(urls);
798: }
799:
800:
801:
814: URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
815: {
816: super(parent);
817: this.factory = null;
818: this.securityContext = securityContext;
819: }
820:
821:
840: public URLClassLoader(URL[] urls, ClassLoader parent,
841: URLStreamHandlerFactory factory)
842: throws SecurityException
843: {
844: super(parent);
845: this.securityContext = null;
846: this.factory = factory;
847: addURLs(urls);
848:
849:
850:
851:
852: synchronized (factoryCache)
853: {
854: if (factory != null && factoryCache.get(factory) == null)
855: factoryCache.put(factory, new HashMap(5));
856: }
857: }
858:
859:
860:
861:
865: protected void addURL(URL newUrl)
866: {
867: urls.add(newUrl);
868: addURLImpl(newUrl);
869: }
870:
871: private void addURLImpl(URL newUrl)
872: {
873: synchronized (this)
874: {
875: if (newUrl == null)
876: return;
877:
878:
879: thisString = null;
880:
881:
882:
883: URLLoader loader = (URLLoader) urlloaders.get(newUrl);
884: if (loader == null)
885: {
886: String file = newUrl.getFile();
887: String protocol = newUrl.getProtocol();
888:
889:
890:
891: URL absoluteURL;
892: if ("file".equals (protocol))
893: {
894: File dir = new File(file);
895: URL absUrl;
896: try
897: {
898: absoluteURL = dir.getCanonicalFile().toURL();
899: }
900: catch (IOException ignore)
901: {
902: try
903: {
904: absoluteURL = dir.getAbsoluteFile().toURL();
905: }
906: catch (MalformedURLException _)
907: {
908:
909: absoluteURL = newUrl;
910: }
911: }
912: }
913: else
914: {
915:
916:
917: absoluteURL = newUrl;
918: }
919:
920:
921: if ("gcjlib".equals(protocol))
922: loader = new SoURLLoader(this, newUrl);
923: else if (! (file.endsWith("/") || file.endsWith(File.separator)))
924: loader = new JarURLLoader(this, newUrl, absoluteURL);
925: else if ("file".equals(protocol))
926: loader = new FileURLLoader(this, newUrl, absoluteURL);
927: else if ("core".equals(protocol))
928: loader = new CoreURLLoader(this, newUrl);
929: else
930: loader = new RemoteURLLoader(this, newUrl);
931:
932:
933: urlloaders.put(newUrl, loader);
934: }
935:
936: urlinfos.add(loader);
937:
938: Vector extraUrls = loader.getClassPath();
939: if (extraUrls != null)
940: {
941: Iterator it = extraUrls.iterator();
942: while (it.hasNext())
943: {
944: URL url = (URL)it.next();
945: URLLoader extraLoader = (URLLoader) urlloaders.get(url);
946: if (! urlinfos.contains (extraLoader))
947: addURLImpl(url);
948: }
949: }
950:
951: }
952: }
953:
954:
963: private void addURLs(URL[] newUrls)
964: {
965: for (int i = 0; i < newUrls.length; i++)
966: {
967: urls.add(newUrls[i]);
968: addURLImpl(newUrls[i]);
969: }
970: }
971:
972:
976: private String getAttributeValue(Attributes.Name name, Attributes first,
977: Attributes second)
978: {
979: String result = null;
980: if (first != null)
981: result = first.getValue(name);
982: if (result == null)
983: result = second.getValue(name);
984: return result;
985: }
986:
987:
1002: protected Package definePackage(String name, Manifest manifest, URL url)
1003: throws IllegalArgumentException
1004: {
1005:
1006:
1007: StringBuffer xform = new StringBuffer(name);
1008: for (int i = xform.length () - 1; i >= 0; --i)
1009: if (xform.charAt(i) == '.')
1010: xform.setCharAt(i, '/');
1011: xform.append('/');
1012: String xformName = xform.toString();
1013:
1014: Attributes entryAttr = manifest.getAttributes(xformName);
1015: Attributes attr = manifest.getMainAttributes();
1016:
1017: String specTitle
1018: = getAttributeValue(Attributes.Name.SPECIFICATION_TITLE,
1019: entryAttr, attr);
1020: String specVersion
1021: = getAttributeValue(Attributes.Name.SPECIFICATION_VERSION,
1022: entryAttr, attr);
1023: String specVendor
1024: = getAttributeValue(Attributes.Name.SPECIFICATION_VENDOR,
1025: entryAttr, attr);
1026: String implTitle
1027: = getAttributeValue(Attributes.Name.IMPLEMENTATION_TITLE,
1028: entryAttr, attr);
1029: String implVersion
1030: = getAttributeValue(Attributes.Name.IMPLEMENTATION_VERSION,
1031: entryAttr, attr);
1032: String implVendor
1033: = getAttributeValue(Attributes.Name.IMPLEMENTATION_VENDOR,
1034: entryAttr, attr);
1035:
1036:
1037:
1038:
1039:
1040:
1041: String sealed = attr.getValue(Attributes.Name.SEALED);
1042: if ("false".equals(sealed))
1043:
1044: url = null;
1045:
1046: return definePackage(name,
1047: specTitle, specVendor, specVersion,
1048: implTitle, implVendor, implVersion,
1049: url);
1050: }
1051:
1052:
1061: protected Class findClass(final String className)
1062: throws ClassNotFoundException
1063: {
1064:
1065: String resourceName = className.replace('.', '/') + ".class";
1066: int max = urlinfos.size();
1067: Resource resource = null;
1068: for (int i = 0; i < max && resource == null; i++)
1069: {
1070: URLLoader loader = (URLLoader)urlinfos.elementAt(i);
1071: if (loader == null)
1072: continue;
1073:
1074: Class k = loader.getClass(className);
1075: if (k != null)
1076: return k;
1077:
1078: resource = loader.getResource(resourceName);
1079: }
1080: if (resource == null)
1081: throw new ClassNotFoundException(className + " not found in " + this);
1082:
1083:
1084:
1085: try
1086: {
1087: byte[] data;
1088: InputStream in = resource.getInputStream();
1089: try
1090: {
1091: int length = resource.getLength();
1092: if (length != -1)
1093: {
1094:
1095:
1096: data = new byte[length];
1097: int pos = 0;
1098: while (length - pos > 0)
1099: {
1100: int len = in.read(data, pos, length - pos);
1101: if (len == -1)
1102: throw new EOFException("Not enough data reading from: "
1103: + in);
1104: pos += len;
1105: }
1106: }
1107: else
1108: {
1109:
1110:
1111: ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
1112: byte[] b = new byte[4096];
1113: int l = 0;
1114: while (l != -1)
1115: {
1116: l = in.read(b);
1117: if (l != -1)
1118: out.write(b, 0, l);
1119: }
1120: data = out.toByteArray();
1121: }
1122: }
1123: finally
1124: {
1125: in.close();
1126: }
1127: final byte[] classData = data;
1128:
1129:
1130: final CodeSource source = resource.getCodeSource();
1131:
1132:
1133: String packageName = null;
1134: int lastDot = className.lastIndexOf('.');
1135: if (lastDot != -1)
1136: packageName = className.substring(0, lastDot);
1137:
1138: if (packageName != null && getPackage(packageName) == null)
1139: {
1140:
1141: Manifest manifest = resource.loader.getManifest();
1142: if (manifest == null)
1143: definePackage(packageName, null, null, null, null, null, null,
1144: null);
1145: else
1146: definePackage(packageName, manifest, resource.loader.baseURL);
1147: }
1148:
1149:
1150: SecurityManager sm = System.getSecurityManager();
1151: Class result = null;
1152: if (sm != null && securityContext != null)
1153: {
1154: result = (Class)AccessController.doPrivileged
1155: (new PrivilegedAction()
1156: {
1157: public Object run()
1158: {
1159: return defineClass(className, classData,
1160: 0, classData.length,
1161: source);
1162: }
1163: }, securityContext);
1164: }
1165: else
1166: result = defineClass(className, classData, 0, classData.length, source);
1167:
1168:
1169: Certificate[] resourceCertificates = resource.getCertificates();
1170: if(resourceCertificates != null)
1171: super.setSigners(result, resourceCertificates);
1172:
1173: return result;
1174: }
1175: catch (IOException ioe)
1176: {
1177: ClassNotFoundException cnfe;
1178: cnfe = new ClassNotFoundException(className + " not found in " + this);
1179: cnfe.initCause(ioe);
1180: throw cnfe;
1181: }
1182: }
1183:
1184:
1185: private String thisString;
1186:
1187:
1192: public String toString()
1193: {
1194: synchronized (this)
1195: {
1196: if (thisString == null)
1197: {
1198: StringBuffer sb = new StringBuffer();
1199: sb.append(this.getClass().getName());
1200: sb.append("{urls=[" );
1201: URL[] thisURLs = getURLs();
1202: for (int i = 0; i < thisURLs.length; i++)
1203: {
1204: sb.append(thisURLs[i]);
1205: if (i < thisURLs.length - 1)
1206: sb.append(',');
1207: }
1208: sb.append(']');
1209: sb.append(", parent=");
1210: sb.append(getParent());
1211: sb.append('}');
1212: thisString = sb.toString();
1213: }
1214: return thisString;
1215: }
1216: }
1217:
1218:
1225: private Resource findURLResource(String resourceName)
1226: {
1227: int max = urlinfos.size();
1228: for (int i = 0; i < max; i++)
1229: {
1230: URLLoader loader = (URLLoader) urlinfos.elementAt(i);
1231: if (loader == null)
1232: continue;
1233:
1234: Resource resource = loader.getResource(resourceName);
1235: if (resource != null)
1236: return resource;
1237: }
1238: return null;
1239: }
1240:
1241:
1247: public URL findResource(String resourceName)
1248: {
1249: Resource resource = findURLResource(resourceName);
1250: if (resource != null)
1251: return resource.getURL();
1252:
1253:
1254: return null;
1255: }
1256:
1257:
1264: URLStreamHandler getURLStreamHandler(String protocol)
1265: {
1266: if (factory == null)
1267: return null;
1268:
1269: URLStreamHandler handler;
1270: synchronized (factoryCache)
1271: {
1272:
1273: HashMap cache = (HashMap) factoryCache.get(factory);
1274: handler = (URLStreamHandler) cache.get(protocol);
1275: if (handler == null)
1276: {
1277:
1278: handler = factory.createURLStreamHandler(protocol);
1279: cache.put(protocol, handler);
1280: }
1281: }
1282: return handler;
1283: }
1284:
1285:
1294: public Enumeration findResources(String resourceName)
1295: throws IOException
1296: {
1297: Vector resources = new Vector();
1298: int max = urlinfos.size();
1299: for (int i = 0; i < max; i++)
1300: {
1301: URLLoader loader = (URLLoader) urlinfos.elementAt(i);
1302: Resource resource = loader.getResource(resourceName);
1303: if (resource != null)
1304: resources.add(resource.getURL());
1305: }
1306: return resources.elements();
1307: }
1308:
1309:
1329: protected PermissionCollection getPermissions(CodeSource source)
1330: {
1331:
1332:
1333:
1334: PermissionCollection permissions = super.getPermissions(source);
1335:
1336:
1337: URL url = source.getLocation();
1338: String protocol = url.getProtocol();
1339: if (protocol.equals("file"))
1340: {
1341: String file = url.getFile();
1342:
1343:
1344: if (file.endsWith("/") || file.endsWith(File.separator))
1345: {
1346:
1347:
1348: permissions.add(new FilePermission(file + "-", "read"));
1349: }
1350: else
1351: {
1352:
1353:
1354: permissions.add(new FilePermission(file, "read"));
1355: }
1356: }
1357: else
1358: {
1359:
1360: String host = url.getHost();
1361: if (host != null)
1362: permissions.add(new SocketPermission(host, "connect,accept"));
1363: }
1364:
1365: return permissions;
1366: }
1367:
1368:
1374: public URL[] getURLs()
1375: {
1376: return (URL[]) urls.toArray(new URL[urls.size()]);
1377: }
1378:
1379:
1392: public static URLClassLoader newInstance(URL[] urls)
1393: throws SecurityException
1394: {
1395: return newInstance(urls, null);
1396: }
1397:
1398:
1412: public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
1413: throws SecurityException
1414: {
1415: SecurityManager sm = System.getSecurityManager();
1416: if (sm == null)
1417: return new URLClassLoader(urls, parent);
1418: else
1419: {
1420: final Object securityContext = sm.getSecurityContext();
1421:
1422:
1423: if (! (securityContext instanceof AccessControlContext))
1424: throw new SecurityException("securityContext must be AccessControlContext: "
1425: + securityContext);
1426:
1427: URLClassLoader loader =
1428: (URLClassLoader) AccessController.doPrivileged(new PrivilegedAction()
1429: {
1430: public Object run()
1431: {
1432: return new URLClassLoader(parent,
1433: (AccessControlContext) securityContext);
1434: }
1435: });
1436: loader.addURLs(urls);
1437: return loader;
1438: }
1439: }
1440: }