001: /*
002: * @(#)Launcher.java 1.52 06/11/07
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.misc;
029:
030: import java.io.File;
031: import java.io.IOException;
032: import java.io.FilePermission;
033: import java.io.InputStream;
034: import java.io.FileInputStream;
035: import java.net.URL;
036: import java.net.URLClassLoader;
037: import java.net.MalformedURLException;
038: import java.net.URLStreamHandler;
039: import java.net.URLStreamHandlerFactory;
040: import java.util.StringTokenizer;
041: import java.util.Vector;
042: import java.util.jar.Attributes;
043: import java.util.jar.Attributes.Name;
044: import java.util.jar.JarEntry;
045: import java.util.jar.JarFile;
046: import java.util.jar.Manifest;
047: import java.security.AccessController;
048: import java.security.PrivilegedAction;
049: import java.security.PrivilegedExceptionAction;
050: import java.security.AccessControlContext;
051: import java.security.PermissionCollection;
052: import java.security.Permissions;
053: import java.security.Permission;
054: import java.security.ProtectionDomain;
055: import java.security.CodeSource;
056: import sun.security.action.GetPropertyAction;
057:
058: /**
059: * This class is used by the system to launch the main application.
060: Launcher */
061: public class Launcher {
062: private static Launcher launcher;
063: private static URLStreamHandlerFactory factory;
064:
065: static {
066: factory = new Factory();
067: launcher = (Launcher) AccessController
068: .doPrivileged(new PrivilegedAction() {
069: public Object run() {
070: // If property sun.boot.class.path is not defined, then
071: // we are running in the old-style launcher, in which
072: // case we just return null.
073:
074: String s = System
075: .getProperty("sun.boot.class.path");
076: if (s != null) {
077: return new Launcher();
078: } else {
079: return null;
080: }
081: }
082: });
083: }
084:
085: public static Launcher getLauncher() {
086: return launcher;
087: }
088:
089: //
090: // Private static to get to the application classloader instance
091: // of the singleton launcher
092: //
093: private static ClassLoader getAppClassLoader() {
094: return launcher.loader;
095: }
096:
097: // Utility to be shared between app class loader and extension class
098: // loader
099: static boolean inList(URL url, URL[] list) {
100: for (int i = 0; i < list.length; i++) {
101: if (url.equals(list[i])) {
102: return true;
103: }
104: }
105: return false;
106: }
107:
108: /*
109: * Update app class loader with a new java.class.path
110: * value.
111: */
112: public static void updateLauncher() throws IOException {
113: //
114: // Invalidate cached boot class path, so it can be recomputed
115: // the next time it is needed
116: //
117: bootstrapClassPath = null;
118:
119: // Handle new classpath for the app loader
120: AppClassLoader appLoader = (AppClassLoader) launcher.loader;
121: appLoader.updateWithNewClasspath();
122:
123: // Handle the ext loader if java.ext.dirs is specified.
124: ExtClassLoader extLoader = (ExtClassLoader) appLoader
125: .getParent();
126: extLoader.updateWithNewExtdirs();
127:
128: // Finally, handle any indication of a security manager request.
129: installSecurityManagerIfRequested(appLoader);
130: }
131:
132: private ClassLoader loader;
133:
134: public Launcher() {
135: // Create the extension class loader unconditionally.
136: ClassLoader extcl;
137: try {
138: extcl = ExtClassLoader.getExtClassLoader();
139: } catch (IOException e) {
140: throw new InternalError(
141: "Could not create extension class loader");
142: }
143:
144: // Now create the class loader to use to launch the application
145: try {
146: loader = AppClassLoader.getAppClassLoader(extcl);
147: } catch (IOException e) {
148: throw new InternalError(
149: "Could not create application class loader");
150: }
151:
152: // Set the loader as the systemClassLoader
153: CVM.setSystemClassLoader(loader);
154:
155: // Register in case application classes were ROMized
156: CVM.Preloader.registerClassLoader("sys", loader);
157:
158: // Also set the context class loader for the primordial thread.
159: Thread.currentThread().setContextClassLoader(loader);
160:
161: // Finally, create security manager if necessary.
162: installSecurityManagerIfRequested(loader);
163: }
164:
165: private static void installSecurityManagerIfRequested(
166: ClassLoader loader) {
167: // Finally, install a security manager if requested
168: String s = System.getProperty("java.security.manager");
169: if (s != null) {
170: SecurityManager sm = null;
171: if ("".equals(s) || "default".equals(s)) {
172: sm = new java.lang.SecurityManager();
173: } else {
174: try {
175: sm = (SecurityManager) loader.loadClass(s)
176: .newInstance();
177: } catch (IllegalAccessException e) {
178: } catch (InstantiationException e) {
179: } catch (ClassNotFoundException e) {
180: } catch (ClassCastException e) {
181: }
182: }
183: if (sm != null) {
184: System.setSecurityManager(sm);
185: } else {
186: throw new InternalError(
187: "Could not create SecurityManager: " + s);
188: }
189: }
190: }
191:
192: /*
193: * Returns the class loader used to launch the main application.
194: */
195: public ClassLoader getClassLoader() {
196: return loader;
197: }
198:
199: /*
200: * The class loader used for loading installed extensions.
201: */
202: static class ExtClassLoader extends URLClassLoader {
203: private File[] dirs;
204:
205: /**
206: * create an ExtClassLoader. The ExtClassLoader is created
207: * within a context that limits which files it can read
208: */
209: public static ExtClassLoader getExtClassLoader()
210: throws IOException {
211: final File[] dirs = getExtDirs();
212:
213: try {
214: // Prior implementations of this doPrivileged() block supplied
215: // aa synthesized ACC via a call to the private method
216: // ExtClassLoader.getContext().
217:
218: return (ExtClassLoader) AccessController
219: .doPrivileged(new PrivilegedExceptionAction() {
220: public Object run() throws IOException {
221: return new ExtClassLoader(dirs);
222: }
223: });
224: } catch (java.security.PrivilegedActionException e) {
225: throw (IOException) e.getException();
226: }
227: }
228:
229: void addExtURL(URL url) {
230: super .addURL(url);
231: }
232:
233: /*
234: * Creates a new ExtClassLoader for the specified directories.
235: */
236: public ExtClassLoader(File[] dirs) throws IOException {
237: super (getExtURLs(dirs), null, factory);
238: this .dirs = dirs;
239: // Register in case ext classes were ROMized
240: CVM.Preloader.registerClassLoader("ext", this );
241: }
242:
243: /*
244: * Adds to current java.ext.dirs
245: */
246: void updateWithNewExtdirs() throws IOException {
247: // This reflects any past and current installed extensions
248: URL[] origUrls = this .getURLs();
249:
250: // Now add those URL's we don't already know about.
251: URL[] urls = getExtURLs(getExtDirs());
252: for (int i = 0; i < urls.length; i++) {
253: URL url = urls[i];
254: if (!inList(url, origUrls)) {
255: this .addURL(url);
256: }
257: }
258: }
259:
260: private static File[] getExtDirs() {
261: String s = System.getProperty("java.ext.dirs");
262: File[] dirs;
263: if (s != null) {
264: StringTokenizer st = new StringTokenizer(s,
265: File.pathSeparator);
266: int count = st.countTokens();
267: dirs = new File[count];
268: for (int i = 0; i < count; i++) {
269: dirs[i] = new File(st.nextToken());
270: }
271: } else {
272: dirs = new File[0];
273: }
274: return dirs;
275: }
276:
277: private static URL[] getExtURLs(File[] dirs) throws IOException {
278: Vector urls = new Vector();
279: for (int i = 0; i < dirs.length; i++) {
280: String[] files = dirs[i].list();
281: if (files != null) {
282: for (int j = 0; j < files.length; j++) {
283: File f = new File(dirs[i], files[j]);
284: urls.add(getFileURL(f));
285: }
286: }
287: }
288: URL[] ua = new URL[urls.size()];
289: urls.copyInto(ua);
290: return ua;
291: }
292:
293: /*
294: * Searches the installed extension directories for the specified
295: * library name. For each extension directory, we first look for
296: * the native library in the subdirectory whose name is the value
297: * of the system property <code>os.arch</code>. Failing that, we
298: * look in the extension directory itself.
299: */
300: public String findLibrary(String name) {
301: name = System.mapLibraryName(name);
302: for (int i = 0; i < dirs.length; i++) {
303: // Look in architecture-specific subdirectory first
304: String arch = System.getProperty("os.arch");
305: if (arch != null) {
306: File file = new File(new File(dirs[i], arch), name);
307: if (file.exists()) {
308: return file.getAbsolutePath();
309: }
310: }
311: // Then check the extension directory
312: File file = new File(dirs[i], name);
313: if (file.exists()) {
314: return file.getAbsolutePath();
315: }
316: }
317: return null;
318: }
319: }
320:
321: /**
322: * This is the container object returned from the native side.
323: */
324: static class ClassContainer {
325: URL url; /* The URL of this path component */
326:
327: String entryname; /* The name of the class entry (.class name) */
328:
329: JarFile jfile;
330: Class clazz; /* The class that has been defined */
331:
332: ClassContainer(URL url, String entryname, JarFile jfile) {
333: this .url = url;
334: this .entryname = entryname;
335: this .jfile = jfile;
336: this .clazz = null;
337: }
338:
339: ClassContainer(URL url, Class clazz, String entryname,
340: JarFile jfile) {
341: this .url = url;
342: this .entryname = entryname;
343: this .jfile = jfile;
344: this .clazz = clazz;
345: }
346: }
347:
348: /**
349: * The class loader used for loading from java.class.path.
350: * runs in a restricted security context.
351: */
352: static class AppClassLoader extends URLClassLoader {
353: // Flag for extension information of JAR files
354: // from java.class.path.
355: private static boolean hasExtension = false;
356:
357: // Called by classPathInit() from classload.c if
358: // extension information is found in JAR manifests.
359: public static void setExtInfo() {
360: hasExtension = true;
361: }
362:
363: public static ClassLoader getAppClassLoader(
364: final ClassLoader extcl) throws IOException {
365: final String s = System.getProperty("java.class.path");
366: final File[] path = (s == null) ? new File[0]
367: : getClassPath(s);
368:
369: // Note: on bugid 4256530
370: // Prior implementations of this doPrivileged() block supplied
371: // a rather restrictive ACC via a call to the private method
372: // AppClassLoader.getContext(). This proved overly restrictive
373: // when loading classes. Specifically it prevent
374: // accessClassInPackage.sun.* grants from being honored.
375: //
376: return (AppClassLoader) AccessController
377: .doPrivileged(new PrivilegedAction() {
378: public Object run() {
379: URL[] urls = (s == null) ? new URL[0]
380: : pathToURLs(path);
381: return new AppClassLoader(urls, extcl);
382: }
383: });
384: }
385:
386: /*
387: * Creates a new AppClassLoader
388: */
389: AppClassLoader(URL[] urls, ClassLoader parent) {
390: super (urls, parent, factory);
391: }
392:
393: /*
394: * In case java.class.path has been updated, update the set of
395: * URL's that this class loader has been initialized with.
396: *
397: * Use URLClassLoader.{getURLs(), addURL()}
398: */
399: void updateWithNewClasspath() throws IOException {
400: final String s = System.getProperty("java.class.path");
401: final File[] path = (s == null) ? new File[0]
402: : getClassPath(s);
403: URL[] urls = pathToURLs(path);
404: URL[] origUrls = this .getURLs();
405:
406: /* Now add any new URL's not found in the original list */
407: for (int i = 0; i < urls.length; i++) {
408: URL url = urls[i];
409: if (!inList(url, origUrls)) {
410: this .addURL(url);
411: }
412: }
413: }
414:
415: /**
416: * Override loadClass so we can checkPackageAccess.
417: */
418: public synchronized Class loadClass(String name, boolean resolve)
419: throws ClassNotFoundException {
420: int i = name.lastIndexOf('.');
421: if (i != -1) {
422: SecurityManager sm = System.getSecurityManager();
423: if (sm != null) {
424: sm.checkPackageAccess(name.substring(0, i));
425: }
426: }
427: return (super .loadClass(name, resolve));
428: }
429:
430: /*
431: * Returns true if the specified package name is sealed according to the
432: * given manifest.
433: */
434: private boolean isSealedPrivate(String name, Manifest man) {
435: String path = name.replace('.', '/').concat("/");
436: Attributes attr = man.getAttributes(path);
437: String sealed = null;
438: if (attr != null) {
439: sealed = attr.getValue(Name.SEALED);
440: }
441: if (sealed == null) {
442: if ((attr = man.getMainAttributes()) != null) {
443: sealed = attr.getValue(Name.SEALED);
444: }
445: }
446: return "true".equalsIgnoreCase(sealed);
447: }
448:
449: private byte[] getBytesPrivate(InputStream in, int len)
450: throws IOException {
451: byte[] b;
452: try {
453: if (len != -1) {
454: // Read exactly len bytes from the input stream
455: b = new byte[len];
456: while (len > 0) {
457: int n = in.read(b, b.length - len, len);
458: if (n == -1) {
459: throw new IOException("unexpected EOF");
460: }
461: len -= n;
462: }
463: } else {
464: // Read until end of stream is reached
465: b = new byte[1024];
466: int total = 0;
467: while ((len = in.read(b, total, b.length - total)) != -1) {
468: total += len;
469: if (total >= b.length) {
470: byte[] tmp = new byte[total * 2];
471: System.arraycopy(b, 0, tmp, 0, total);
472: b = tmp;
473: }
474: }
475: // Trim array to correct size, if necessary
476: if (total != b.length) {
477: byte[] tmp = new byte[total];
478: System.arraycopy(b, 0, tmp, 0, total);
479: b = tmp;
480: }
481: }
482: } finally {
483: in.close();
484: }
485: return b;
486: }
487:
488: private void handlePackage(String name, Manifest man, URL url)
489: throws IOException
490:
491: {
492: int i = name.lastIndexOf('.');
493: if (i == -1) {
494: return;
495: }
496: String pkgname = name.substring(0, i);
497: if (name.startsWith("java.")) {
498: throw new SecurityException("Prohibited package name: "
499: + pkgname);
500: }
501:
502: // Check if package already loaded.
503: Package pkg = getPackage(pkgname);
504:
505: if (pkg != null) {
506: // Package found, so check package sealing.
507: boolean ok;
508: if (pkg.isSealed()) {
509: // Verify that code source URL is the same.
510: ok = pkg.isSealed(url);
511: } else {
512: // Make sure we are not attempting to seal the package
513: // at this code source URL.
514: ok = (man == null)
515: || !isSealedPrivate(pkgname, man);
516: }
517: if (!ok) {
518: throw new SecurityException("sealing violation");
519: }
520: } else {
521: if (man != null) {
522: definePackage(pkgname, man, url);
523: } else {
524: definePackage(pkgname, null, null, null, null,
525: null, null, null);
526: }
527: }
528: }
529:
530: private Class defineClassPrivate(String name, ClassContainer cc)
531: throws IOException {
532: URL url = cc.url;
533: JarFile jfile = cc.jfile;
534: Manifest man;
535:
536: if (jfile != null) { // Must be a ZIP/JAR
537: man = jfile.getManifest();
538: } else {
539: man = null;
540: }
541:
542: // See if there are any package operations to do
543: handlePackage(name, man, url);
544:
545: if (cc.clazz != null) {
546: /* load superclasses in a way that avoid C recursion */
547: sun.misc.CVM.executeLoadSuperClasses(cc.clazz);
548: return cc.clazz;
549: } else {
550: String path = cc.entryname;
551: JarEntry entry = jfile.getJarEntry(path);
552: InputStream in = jfile.getInputStream(entry);
553: int len = (int) entry.getSize();
554:
555: // Now get the class bytes and define the class
556: byte[] b = getBytesPrivate(in, len);
557: java.security.cert.Certificate[] certs = entry
558: .getCertificates();
559: CodeSource cs = new CodeSource(url, certs);
560: return defineClass(name, b, 0, b.length, cs);
561: }
562: }
563:
564: private Class doClassFind(final String name)
565: throws ClassNotFoundException,
566: java.security.PrivilegedActionException {
567: return (Class) AccessController
568: .doPrivileged(new PrivilegedExceptionAction() {
569: public Object run()
570: throws ClassNotFoundException {
571: ClassContainer cc = findContainer(name);
572: if (cc != null) {
573: try {
574: return defineClassPrivate(name, cc);
575: } catch (IOException e) {
576: throw new ClassNotFoundException(
577: name, e);
578: }
579: } else {
580: throw new ClassNotFoundException(name);
581: }
582: }
583: });
584: }
585:
586: /*
587: * Check syntax of name passed to defineClass() or findClass methods
588: * array syntax clasnames with /'s are not allowed
589: */
590: private boolean checkName(String name) {
591: if (name == null || name.length() == 0)
592: return true;
593: if (name.indexOf('/') != -1)
594: return false;
595: if (name.charAt(0) == '[')
596: return false;
597: return true;
598: }
599:
600: /**
601: * Override findClass
602: */
603: protected Class findClass(final String name)
604: throws ClassNotFoundException {
605: if (!checkName(name))
606: throw new ClassNotFoundException("Illegal name: "
607: + name);
608:
609: // If Extension Mechanism is supported
610: // we use URLClassLoader's implementation.
611: // Otherwise we use our own.
612: if (hasExtension) {
613: return super .findClass(name);
614: }
615: try {
616: return doClassFind(name);
617: } catch (java.security.PrivilegedActionException pae) {
618: throw (ClassNotFoundException) pae.getException();
619: }
620: }
621:
622: private native ClassContainer findContainer(String name)
623: throws ClassNotFoundException;
624:
625: /**
626: * allow any classes loaded from classpath to exit the VM.
627: */
628: protected PermissionCollection getPermissions(
629: CodeSource codesource) {
630: PermissionCollection perms = super
631: .getPermissions(codesource);
632: perms.add(new RuntimePermission("exitVM"));
633: return perms;
634: }
635: }
636:
637: //
638: // Cache the bootstrap class path so it does not have to be recreated
639: // from the sun.boot.class.path every time.
640: //
641: private static URLClassPath bootstrapClassPath = null;
642:
643: // Returns the URLClassPath that is used for finding system resources.
644: public static URLClassPath getBootstrapClassPath() {
645: if (bootstrapClassPath == null) {
646: bootstrapClassPath = getBootstrapClassPath0();
647: }
648: return bootstrapClassPath;
649: }
650:
651: // Compute a URLClassPath representing the boot classpath
652: private static URLClassPath getBootstrapClassPath0() {
653: String prop = (String) AccessController
654: .doPrivileged(new GetPropertyAction(
655: "sun.boot.class.path"));
656: if (prop == null) {
657: // Running old-style launcher, so use java.class.path instead
658: prop = (String) AccessController
659: .doPrivileged(new GetPropertyAction(
660: "java.class.path"));
661: }
662: URL[] urls;
663: if (prop != null) {
664: final String path = prop;
665: urls = (URL[]) AccessController
666: .doPrivileged(new PrivilegedAction() {
667: public Object run() {
668: return pathToURLs(getClassPath(path));
669: }
670: });
671: } else {
672: urls = new URL[0];
673: }
674: return new URLClassPath(urls, factory);
675: }
676:
677: private static URL[] pathToURLs(File[] path) {
678: URL[] urls = new URL[path.length];
679: for (int i = 0; i < path.length; i++) {
680: urls[i] = getFileURL(path[i]);
681: }
682: // DEBUG
683: //for (int i = 0; i < urls.length; i++) {
684: // System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"');
685: //}
686: return urls;
687: }
688:
689: private static File[] getClassPath(String cp) {
690: File[] path;
691: if (cp != null) {
692: int count = 0, maxCount = 1;
693: int pos = 0, lastPos = 0;
694: // Count the number of separators first
695: while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
696: maxCount++;
697: lastPos = pos + 1;
698: }
699: path = new File[maxCount];
700: lastPos = pos = 0;
701: // Now scan for each path component
702: while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
703: if (pos - lastPos > 0) {
704: path[count++] = new File(cp.substring(lastPos, pos));
705: } else {
706: // empty path component translates to "."
707: path[count++] = new File(".");
708: }
709: lastPos = pos + 1;
710: }
711: // Make sure we include the last path component
712: if (lastPos < cp.length()) {
713: path[count++] = new File(cp.substring(lastPos));
714: } else {
715: path[count++] = new File(".");
716: }
717: // Trim array to correct size
718: if (count != maxCount) {
719: File[] tmp = new File[count];
720: System.arraycopy(path, 0, tmp, 0, count);
721: path = tmp;
722: }
723: } else {
724: path = new File[0];
725: }
726: // DEBUG
727: //for (int i = 0; i < path.length; i++) {
728: // System.out.println("path[" + i + "] = " + '"' + path[i] + '"');
729: //}
730: return path;
731: }
732:
733: private static URLStreamHandler fileHandler;
734:
735: static URL getFileURL(File file) {
736: try {
737: file = file.getCanonicalFile();
738: } catch (IOException e) {
739: }
740: String path = file.getAbsolutePath();
741: if (File.separatorChar != '/') {
742: path = path.replace(File.separatorChar, '/');
743: }
744: if (!path.startsWith("/")) {
745: path = "/" + path;
746: }
747: if (!path.endsWith("/") && file.isDirectory()) {
748: path = path + "/";
749: }
750: if (fileHandler == null) {
751: fileHandler = factory.createURLStreamHandler("file");
752: }
753: try {
754: return new URL("file", "", -1, path, fileHandler);
755: } catch (MalformedURLException e) {
756: // Should never happen since we specify the protocol...
757: throw new InternalError();
758: }
759: }
760:
761: /*
762: * The stream handler factory for loading system protocol handlers.
763: */
764: private static class Factory implements URLStreamHandlerFactory {
765: private static String PREFIX = "sun.net.www.protocol";
766:
767: public URLStreamHandler createURLStreamHandler(String protocol) {
768: String name = PREFIX + "." + protocol + ".Handler";
769: try {
770: Class c = Class.forName(name);
771: return (URLStreamHandler) c.newInstance();
772: } catch (ClassNotFoundException e) {
773: e.printStackTrace();
774: } catch (InstantiationException e) {
775: e.printStackTrace();
776: } catch (IllegalAccessException e) {
777: e.printStackTrace();
778: }
779: throw new InternalError("could not load " + protocol
780: + "system protocol handler");
781: }
782: }
783: }
784:
785: class PathPermissions extends PermissionCollection {
786: // use serialVersionUID from JDK 1.2.2 for interoperability
787: private static final long serialVersionUID = 8133287259134945693L;
788:
789: private File path[];
790: private Permissions perms;
791:
792: URL codeBase;
793:
794: PathPermissions(File path[]) {
795: this .path = path;
796: this .perms = null;
797: this .codeBase = null;
798: }
799:
800: URL getCodeBase() {
801: return codeBase;
802: }
803:
804: public void add(java.security.Permission permission) {
805: throw new SecurityException("attempt to add a permission");
806: }
807:
808: private synchronized void init() {
809: if (perms != null)
810: return;
811:
812: perms = new Permissions();
813:
814: // this is needed to be able to create the classloader itself!
815: perms.add(new RuntimePermission("createClassLoader"));
816:
817: // add permission to read any "java.*" property
818: perms.add(new java.util.PropertyPermission("java.*", "read"));
819:
820: AccessController.doPrivileged(new PrivilegedAction() {
821: public Object run() {
822: for (int i = 0; i < path.length; i++) {
823: File f = path[i];
824: String path;
825: try {
826: path = f.getCanonicalPath();
827: } catch (IOException ioe) {
828: path = f.getAbsolutePath();
829: }
830: if (i == 0) {
831: codeBase = Launcher.getFileURL(new File(path));
832: }
833: if (f.isDirectory()) {
834: if (path.endsWith(File.separator)) {
835: perms.add(new FilePermission(path + "-",
836: "read"));
837: } else {
838: perms.add(new FilePermission(path
839: + File.separator + "-", "read"));
840: }
841: } else {
842: int endIndex = path
843: .lastIndexOf(File.separatorChar);
844: if (endIndex != -1) {
845: path = path.substring(0, endIndex + 1)
846: + "-";
847: perms.add(new FilePermission(path, "read"));
848: } else {
849: // ?
850: }
851: }
852: }
853: return null;
854: }
855: });
856: }
857:
858: public boolean implies(java.security.Permission permission) {
859: if (perms == null)
860: init();
861: return perms.implies(permission);
862: }
863:
864: public java.util.Enumeration elements() {
865: if (perms == null)
866: init();
867: return perms.elements();
868: }
869:
870: public String toString() {
871: if (perms == null)
872: init();
873: return perms.toString();
874: }
875: }
|