0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package java.lang;
0018:
0019: import java.io.File;
0020: import java.io.IOException;
0021: import java.io.InputStream;
0022: import java.lang.reflect.Constructor;
0023: import java.net.MalformedURLException;
0024: import java.net.URL;
0025: import java.nio.ByteBuffer;
0026: import java.net.URLClassLoader;
0027: import java.security.AccessController;
0028: import java.security.CodeSource;
0029: import java.security.PrivilegedActionException;
0030: import java.security.PrivilegedExceptionAction;
0031: import java.security.ProtectionDomain;
0032: import java.security.cert.Certificate;
0033: import java.util.ArrayList;
0034: import java.util.Collection;
0035: import java.util.Enumeration;
0036: import java.util.HashMap;
0037: import java.util.Hashtable;
0038: import java.util.NoSuchElementException;
0039:
0040: import org.apache.harmony.lang.RuntimePermissionCollection;
0041: import org.apache.harmony.misc.EmptyEnum;
0042: import org.apache.harmony.lang.ClassLoaderInfo;
0043: import org.apache.harmony.vm.VMStack;
0044:
0045: /**
0046: * @com.intel.drl.spec_ref
0047: *
0048: * @author Evgueni Brevnov
0049: * @version $Revision: 1.1.2.2.4.4 $
0050: */
0051: public abstract class ClassLoader {
0052:
0053: /**
0054: * default protection domain.
0055: */
0056: private ProtectionDomain defaultDomain;
0057:
0058: /**
0059: * system default class loader. It is initialized while
0060: * getSystemClassLoader(..) method is executing.
0061: */
0062: private static ClassLoader systemClassLoader = null;
0063:
0064: /**
0065: * empty set of sertificates
0066: */
0067: private static final Certificate[] EMPTY_CERTIFICATES = new Certificate[0];
0068:
0069: /**
0070: * this field has false as default value, it becomes true if system class
0071: * loader is initialized.
0072: */
0073: private static boolean initialized = false;
0074:
0075: /**
0076: * package private to access from the java.lang.Class class. The following
0077: * mapping is used <String name, Boolean flag>, where name - class name,
0078: * flag - true if assertion is enabled, false if disabled.
0079: */
0080: Hashtable<String, Boolean> classAssertionStatus;
0081:
0082: /**
0083: * package private to access from the java.lang.Class class. The following
0084: * mapping is used <String name, Object[] signers>, where name - class name,
0085: * signers - array of signers.
0086: */
0087: Hashtable<String, Object[]> classSigners;
0088:
0089: /**
0090: * package private to access from the java.lang.Class class.
0091: */
0092: int defaultAssertionStatus;
0093: boolean clearAssertionStatus;
0094:
0095: /**
0096: * package private to access from the java.lang.Class class. The following
0097: * mapping is used <String name, Boolean flag>, where name - package name,
0098: * flag - true if assertion is enabled, false if disabled.
0099: */
0100: Hashtable<String, Boolean> packageAssertionStatus;
0101:
0102: /**
0103: * packages defined by this class loader are stored in this hash. The
0104: * following mapping is used <String name, Package pkg>, where name -
0105: * package name, pkg - corresponding package.
0106: */
0107: private final HashMap<String, Package> definedPackages;
0108:
0109: /**
0110: * The class registry, provides strong referencing between the classloader
0111: * and it's defined classes. Intended for class unloading implementation.
0112: * @see java.lang.Class#definingLoader
0113: * @see #registerLoadedClass()
0114: */
0115: private ArrayList<Class> loadedClasses = new ArrayList<Class>();
0116:
0117: /**
0118: * package private to access from the java.lang.Class class. The following
0119: * mapping is used <String name, Certificate[] certificates>, where name -
0120: * the name of a package, certificates - array of certificates.
0121: */
0122: private final Hashtable<String, Certificate[]> packageCertificates = new Hashtable<String, Certificate[]>();
0123:
0124: /**
0125: * parent class loader
0126: */
0127: private final ClassLoader parentClassLoader;
0128:
0129: /**
0130: * @com.intel.drl.spec_ref
0131: */
0132: protected ClassLoader() {
0133: //assert systemClassLoader != null
0134: // TODO XXX: use systemClassLoader field instead of
0135: // getSystemClassLoader() method.
0136: this (getSystemClassLoader());
0137: }
0138:
0139: /**
0140: * @com.intel.drl.spec_ref
0141: */
0142: protected ClassLoader(ClassLoader parent) {
0143: SecurityManager sc = System.getSecurityManager();
0144: if (sc != null) {
0145: sc.checkCreateClassLoader();
0146: }
0147: parentClassLoader = parent;
0148: // this field is used to determine whether class loader was initialized
0149: // properly.
0150: definedPackages = new HashMap<String, Package>();
0151: }
0152:
0153: /**
0154: * @com.intel.drl.spec_ref
0155: */
0156: public static ClassLoader getSystemClassLoader() {
0157: if (!initialized) {
0158: // we assume only one thread will initialize system class loader. So
0159: // we don't synchronize initSystemClassLoader() method.
0160: initSystemClassLoader();
0161: // system class loader is initialized properly.
0162: initialized = true;
0163: // setContextClassLoader(...) method throws SecurityException if
0164: // current thread isn't allowed to set systemClassLoader as a
0165: // context class loader. Actually, it is abnormal situation if
0166: // thread can not change his own context class loader.
0167: // Thread.currentThread().setContextClassLoader(systemClassLoader);
0168: }
0169: //assert initialized;
0170: SecurityManager sc = System.getSecurityManager();
0171: if (sc != null) {
0172: // we use VMClassRegistry.getClassLoader(...) method instead of
0173: // Class.getClassLoader() due to avoid redundant security
0174: // checking
0175: ClassLoader callerLoader = VMClassRegistry
0176: .getClassLoader(VMStack.getCallerClass(0));
0177: if (callerLoader != null
0178: && callerLoader != systemClassLoader) {
0179: sc
0180: .checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
0181: }
0182: }
0183: return systemClassLoader;
0184: }
0185:
0186: /**
0187: * @com.intel.drl.spec_ref
0188: */
0189: public static URL getSystemResource(String name) {
0190: //assert systemClassLoader != null;
0191: // TODO XXX: use systemClassLoader field instead of
0192: // getSystemClassLoader() method.
0193: return getSystemClassLoader().getResource(name);
0194: }
0195:
0196: /**
0197: * @com.intel.drl.spec_ref
0198: */
0199: public static InputStream getSystemResourceAsStream(String name) {
0200: //assert systemClassLoader != null;
0201: // TODO XXX: use systemClassLoader field instead of
0202: // getSystemClassLoader() method.
0203: return getSystemClassLoader().getResourceAsStream(name);
0204: }
0205:
0206: /**
0207: * @com.intel.drl.spec_ref
0208: */
0209: public static Enumeration<URL> getSystemResources(String name)
0210: throws IOException {
0211: //assert systemClassLoader != null;
0212: // TODO XXX: use systemClassLoader field instead of
0213: // getSystemClassLoader() method.
0214: return getSystemClassLoader().getResources(name);
0215: }
0216:
0217: /**
0218: * @com.intel.drl.spec_ref
0219: */
0220: public void clearAssertionStatus() {
0221: clearAssertionStatus = true;
0222: defaultAssertionStatus = -1;
0223: packageAssertionStatus = null;
0224: classAssertionStatus = null;
0225: }
0226:
0227: /**
0228: * @com.intel.drl.spec_ref
0229: */
0230: public final ClassLoader getParent() {
0231: SecurityManager sc = System.getSecurityManager();
0232: if (sc != null) {
0233: ClassLoader callerLoader = VMClassRegistry
0234: .getClassLoader(VMStack.getCallerClass(0));
0235: if (callerLoader != null
0236: && !callerLoader.isSameOrAncestor(this )) {
0237: sc
0238: .checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
0239: }
0240: }
0241: return parentClassLoader;
0242: }
0243:
0244: /**
0245: * @com.intel.drl.spec_ref
0246: */
0247: public URL getResource(String name) {
0248: String nm = name.toString();
0249: checkInitialized();
0250: URL foundResource = (parentClassLoader == null) ? BootstrapLoader
0251: .findResource(nm)
0252: : parentClassLoader.getResource(nm);
0253: return foundResource == null ? findResource(nm) : foundResource;
0254: }
0255:
0256: /**
0257: * @com.intel.drl.spec_ref
0258: */
0259: public InputStream getResourceAsStream(String name) {
0260: URL foundResource = getResource(name);
0261: if (foundResource != null) {
0262: try {
0263: return foundResource.openStream();
0264: } catch (IOException e) {
0265: }
0266: }
0267: return null;
0268: }
0269:
0270: /**
0271: * @com.intel.drl.spec_ref
0272: */
0273: public Enumeration<URL> getResources(String name)
0274: throws IOException {
0275: checkInitialized();
0276: ClassLoader cl = this ;
0277: final ArrayList<Enumeration<URL>> foundResources = new ArrayList<Enumeration<URL>>();
0278: Enumeration<URL> resourcesEnum;
0279: do {
0280: resourcesEnum = cl.findResources(name);
0281: if (resourcesEnum != null
0282: && resourcesEnum.hasMoreElements()) {
0283: foundResources.add(resourcesEnum);
0284: }
0285: } while ((cl = cl.parentClassLoader) != null);
0286: resourcesEnum = BootstrapLoader.findResources(name);
0287: if (resourcesEnum != null && resourcesEnum.hasMoreElements()) {
0288: foundResources.add(resourcesEnum);
0289: }
0290: return new Enumeration<URL>() {
0291:
0292: private int position = foundResources.size() - 1;
0293:
0294: public boolean hasMoreElements() {
0295: while (position >= 0) {
0296: if (((Enumeration) foundResources.get(position))
0297: .hasMoreElements()) {
0298: return true;
0299: }
0300: position--;
0301: }
0302: return false;
0303: }
0304:
0305: public URL nextElement() {
0306: while (position >= 0) {
0307: try {
0308: return (foundResources.get(position))
0309: .nextElement();
0310: } catch (NoSuchElementException e) {
0311: }
0312: position--;
0313: }
0314: throw new NoSuchElementException();
0315: }
0316: };
0317: }
0318:
0319: /**
0320: * @com.intel.drl.spec_ref
0321: */
0322: public Class<?> loadClass(String name)
0323: throws ClassNotFoundException {
0324: return loadClass(name, false);
0325: }
0326:
0327: /**
0328: * @com.intel.drl.spec_ref
0329: */
0330: public void setClassAssertionStatus(String name, boolean flag) {
0331: if (name != null) {
0332: Class.disableAssertions = false;
0333: synchronized (definedPackages) {
0334: if (classAssertionStatus == null) {
0335: classAssertionStatus = new Hashtable<String, Boolean>();
0336: }
0337: }
0338: classAssertionStatus.put(name, Boolean.valueOf(flag));
0339: }
0340: }
0341:
0342: /**
0343: * @com.intel.drl.spec_ref
0344: */
0345: public void setDefaultAssertionStatus(boolean flag) {
0346: if (flag) {
0347: Class.disableAssertions = false;
0348: }
0349: defaultAssertionStatus = flag ? 1 : -1;
0350: }
0351:
0352: /**
0353: * @com.intel.drl.spec_ref
0354: *
0355: * Empty string is used to denote default package.
0356: */
0357: public void setPackageAssertionStatus(String name, boolean flag) {
0358: if (name == null) {
0359: name = "";
0360: }
0361: Class.disableAssertions = false;
0362: synchronized (definedPackages) {
0363: if (packageAssertionStatus == null) {
0364: packageAssertionStatus = new Hashtable<String, Boolean>();
0365: }
0366: }
0367: packageAssertionStatus.put(name, Boolean.valueOf(flag));
0368: }
0369:
0370: /**
0371: * @com.intel.drl.spec_ref
0372: * @deprecated
0373: */
0374: protected final Class<?> defineClass(byte[] data, int offset,
0375: int len) throws ClassFormatError {
0376: return defineClass(null, data, offset, len);
0377: }
0378:
0379: /**
0380: * @com.intel.drl.spec_ref
0381: */
0382: protected final Class<?> defineClass(String name, byte[] data,
0383: int offset, int len) throws ClassFormatError {
0384: return defineClass(name, data, offset, len, null);
0385: }
0386:
0387: /**
0388: * Registers the defined class, invoked by VM.
0389: * Intended for class unloading implementation.
0390: */
0391: @SuppressWarnings("unused")
0392: private void registerLoadedClass(Class<?> clazz) {
0393: synchronized (loadedClasses) {
0394: loadedClasses.add(clazz);
0395: }
0396: clazz.definingLoader = this ;
0397: }
0398:
0399: /**
0400: * @com.intel.drl.spec_ref
0401: */
0402: protected final Class<?> defineClass(String name, ByteBuffer b,
0403: ProtectionDomain protectionDomain) throws ClassFormatError {
0404: byte[] data = b.array();
0405: return defineClass(name, data, 0, data.length, protectionDomain);
0406: }
0407:
0408: /**
0409: * @com.intel.drl.spec_ref
0410: */
0411: protected final synchronized Class<?> defineClass(String name,
0412: byte[] data, int offset, int len, ProtectionDomain domain)
0413: throws ClassFormatError {
0414: checkInitialized();
0415: if (name != null && name.indexOf('/') != -1) {
0416: throw new NoClassDefFoundError(
0417: "The name is expected in binary (canonical) form,"
0418: + " therefore '/' symbols are not allowed: "
0419: + name);
0420: }
0421: if (offset < 0 || len < 0 || offset + len > data.length) {
0422: throw new IndexOutOfBoundsException(
0423: "Either offset or len is outside of the data array");
0424: }
0425: if (domain == null) {
0426: if (defaultDomain == null) {
0427: defaultDomain = new ProtectionDomain(new CodeSource(
0428: null, (Certificate[]) null), null, this , null);
0429: }
0430: domain = defaultDomain;
0431: }
0432: Certificate[] certs = null;
0433: String packageName = null;
0434: if (name != null) {
0435: if (name.startsWith("java.")) {
0436: throw new SecurityException(
0437: "It is not allowed to define classes inside the java.* package: "
0438: + name);
0439: }
0440: int lastDot = name.lastIndexOf('.');
0441: packageName = lastDot == -1 ? "" : name.substring(0,
0442: lastDot);
0443: certs = getCertificates(packageName, domain.getCodeSource());
0444: }
0445: Class<?> clazz = defineClass0(name, data, offset, len);
0446: clazz.setProtectionDomain(domain);
0447: if (certs != null) {
0448: packageCertificates.put(packageName, certs);
0449: }
0450: return clazz;
0451: }
0452:
0453: /**
0454: * Loads new type into the classloader name space.
0455: * The class loader is marked as defining class loader.
0456: * @api2vm
0457: */
0458: private native Class<?> defineClass0(String name, byte[] data,
0459: int off, int len) throws ClassFormatError;
0460:
0461: /**
0462: * @com.intel.drl.spec_ref
0463: */
0464: protected Package definePackage(String name, String specTitle,
0465: String specVersion, String specVendor, String implTitle,
0466: String implVersion, String implVendor, URL sealBase)
0467: throws IllegalArgumentException {
0468: synchronized (definedPackages) {
0469: if (getPackage(name) != null) {
0470: throw new IllegalArgumentException("Package " + name
0471: + "has been already defined.");
0472: }
0473: Package pkg = new Package(this , name, specTitle,
0474: specVersion, specVendor, implTitle, implVersion,
0475: implVendor, sealBase);
0476: definedPackages.put(name, pkg);
0477: return pkg;
0478: }
0479: }
0480:
0481: /**
0482: * @com.intel.drl.spec_ref
0483: */
0484: protected Class<?> findClass(String name)
0485: throws ClassNotFoundException {
0486: throw new ClassNotFoundException("Can not find class " + name);
0487: }
0488:
0489: /**
0490: * @com.intel.drl.spec_ref
0491: */
0492: protected String findLibrary(String name) {
0493: return null;
0494: }
0495:
0496: /**
0497: * @com.intel.drl.spec_ref
0498: */
0499: protected final native Class<?> findLoadedClass(String name);
0500:
0501: /**
0502: * @com.intel.drl.spec_ref
0503: */
0504: protected URL findResource(String name) {
0505: return null;
0506: }
0507:
0508: /**
0509: * @com.intel.drl.spec_ref
0510: */
0511: protected Enumeration<URL> findResources(String name)
0512: throws IOException {
0513: return EmptyEnum.getInstance();
0514: }
0515:
0516: /**
0517: * @com.intel.drl.spec_ref
0518: */
0519: protected final Class<?> findSystemClass(String name)
0520: throws ClassNotFoundException {
0521: // assert systemClassLoader != null;
0522: // TODO XXX: use systemClassLoader field instead of
0523: // getSystemClassLoader() method.
0524: return getSystemClassLoader().loadClass(name, false);
0525: }
0526:
0527: /**
0528: * @com.intel.drl.spec_ref
0529: */
0530: protected Package getPackage(String name) {
0531: checkInitialized();
0532: Package pkg = null;
0533: if (name == null) {
0534: throw new NullPointerException();
0535: }
0536: synchronized (definedPackages) {
0537: pkg = (Package) definedPackages.get(name);
0538: }
0539: if (pkg == null) {
0540: if (parentClassLoader == null) {
0541: pkg = BootstrapLoader.getPackage(name);
0542: } else {
0543: pkg = parentClassLoader.getPackage(name);
0544: }
0545: }
0546: return pkg;
0547: }
0548:
0549: /**
0550: * @com.intel.drl.spec_ref
0551: */
0552: protected Package[] getPackages() {
0553: checkInitialized();
0554: ArrayList<Package> packages = new ArrayList<Package>();
0555: fillPackages(packages);
0556: return packages.toArray(new Package[packages.size()]);
0557: }
0558:
0559: /**
0560: * Registers this class loader as initiating for a class
0561: * Declared as package private to use it from java.lang.Class.forName
0562: */
0563: native void registerInitiatedClass(Class clazz);
0564:
0565: /**
0566: * @com.intel.drl.spec_ref
0567: */
0568: protected synchronized Class<?> loadClass(String name,
0569: boolean resolve) throws ClassNotFoundException {
0570: checkInitialized();
0571: if (name == null) {
0572: throw new NullPointerException();
0573: }
0574: if (name.indexOf("/") != -1) {
0575: throw new ClassNotFoundException(name);
0576: }
0577:
0578: Class<?> clazz = findLoadedClass(name);
0579: if (clazz == null) {
0580: if (parentClassLoader == null) {
0581: clazz = VMClassRegistry.loadBootstrapClass(name);
0582: } else {
0583: try {
0584: clazz = parentClassLoader.loadClass(name);
0585: if (clazz != null) {
0586: try {
0587: VMStack.getCallerClass(0).asSubclass(
0588: ClassLoader.class);
0589: } catch (ClassCastException ex) {
0590: // caller class is not a subclass of
0591: // java/lang/ClassLoader so register as
0592: // initiating loader as we are called from
0593: // outside of ClassLoader delegation chain
0594: registerInitiatedClass(clazz);
0595: }
0596: }
0597: } catch (ClassNotFoundException e) {
0598: }
0599: }
0600: if (clazz == null) {
0601: clazz = findClass(name);
0602: if (clazz == null) {
0603: throw new ClassNotFoundException(name);
0604: }
0605: }
0606: }
0607: if (resolve) {
0608: resolveClass(clazz);
0609: }
0610: return clazz;
0611: }
0612:
0613: /**
0614: * @com.intel.drl.spec_ref
0615: */
0616: protected final void resolveClass(Class<?> clazz) {
0617: if (clazz == null) {
0618: throw new NullPointerException();
0619: }
0620: VMClassRegistry.linkClass(clazz);
0621: }
0622:
0623: /**
0624: * @com.intel.drl.spec_ref
0625: */
0626: protected final void setSigners(Class<?> clazz, Object[] signers) {
0627: checkInitialized();
0628: String name = clazz.getName();
0629: ClassLoader classLoader = clazz.getClassLoaderImpl();
0630: if (classLoader != null) {
0631: if (classLoader.classSigners == null) {
0632: classLoader.classSigners = new Hashtable<String, Object[]>();
0633: }
0634: classLoader.classSigners.put(name, signers);
0635: }
0636: }
0637:
0638: /*
0639: * NON API SECTION
0640: */
0641:
0642: final boolean isSameOrAncestor(ClassLoader loader) {
0643: while (loader != null) {
0644: if (this == loader) {
0645: return true;
0646: }
0647: loader = loader.parentClassLoader;
0648: }
0649: return false;
0650: }
0651:
0652: /**
0653: * This method should be called from each method that performs unsafe
0654: * actions.
0655: */
0656: private void checkInitialized() {
0657: if (definedPackages == null) {
0658: throw new SecurityException(
0659: "Class loader was not initialized properly.");
0660: }
0661: }
0662:
0663: /**
0664: * Neither certs1 nor certs2 cann't be equal to null.
0665: */
0666: private boolean compareAsSet(Certificate[] certs1,
0667: Certificate[] certs2) {
0668: // TODO Is it possible to have multiple instances of same
0669: // certificate in array? This implementation assumes that it is
0670: // not possible.
0671: if (certs1.length != certs1.length) {
0672: return false;
0673: }
0674: if (certs1.length == 0) {
0675: return true;
0676: }
0677: boolean[] hasEqual = new boolean[certs1.length];
0678: for (int i = 0; i < certs1.length; i++) {
0679: boolean isMatch = false;
0680: for (int j = 0; j < certs2.length; j++) {
0681: if (!hasEqual[j] && certs1[i].equals(certs2[j])) {
0682: hasEqual[j] = isMatch = true;
0683: break;
0684: }
0685: }
0686: if (!isMatch) {
0687: return false;
0688: }
0689: }
0690: return true;
0691: }
0692:
0693: /**
0694: * Initializes the system class loader.
0695: */
0696: @SuppressWarnings("unchecked")
0697: private static void initSystemClassLoader() {
0698: if (systemClassLoader != null) {
0699: throw new IllegalStateException(
0700: "Recursive invocation while initializing system class loader");
0701: }
0702: systemClassLoader = SystemClassLoader.getInstance();
0703:
0704: String smName = System
0705: .getPropertyUnsecure("java.security.manager");
0706: if (smName != null) {
0707: try {
0708: final Class<SecurityManager> smClass;
0709: if ("".equals(smName)
0710: || "default".equalsIgnoreCase(smName)) {
0711: smClass = java.lang.SecurityManager.class;
0712: } else {
0713: smClass = (Class<SecurityManager>) systemClassLoader
0714: .loadClass(smName);
0715: if (!SecurityManager.class
0716: .isAssignableFrom(smClass)) {
0717: throw new Error(
0718: smClass
0719: + " must inherit java.lang.SecurityManager");
0720: }
0721: }
0722: AccessController
0723: .doPrivileged(new PrivilegedExceptionAction<Object>() {
0724: public Object run() throws Exception {
0725: System.setSecurityManager(smClass
0726: .newInstance());
0727: return null;
0728: }
0729: });
0730: } catch (Exception e) {
0731: throw (Error) new InternalError().initCause(e);
0732: }
0733: }
0734:
0735: String className = System
0736: .getPropertyUnsecure("java.system.class.loader");
0737: if (className != null) {
0738: try {
0739: final Class<?> userClassLoader = systemClassLoader
0740: .loadClass(className);
0741: if (!ClassLoader.class
0742: .isAssignableFrom(userClassLoader)) {
0743: throw new Error(userClassLoader.toString()
0744: + " must inherit java.lang.ClassLoader");
0745: }
0746: systemClassLoader = AccessController
0747: .doPrivileged(new PrivilegedExceptionAction<ClassLoader>() {
0748: public ClassLoader run() throws Exception {
0749: Constructor c = userClassLoader
0750: .getConstructor(ClassLoader.class);
0751: return (ClassLoader) c
0752: .newInstance(systemClassLoader);
0753: }
0754: });
0755: } catch (ClassNotFoundException e) {
0756: throw new Error(e);
0757: } catch (PrivilegedActionException e) {
0758: throw new Error(e.getCause());
0759: }
0760: }
0761: }
0762:
0763: /**
0764: * Helper method for the getPackages() method.
0765: */
0766: private void fillPackages(ArrayList<Package> packages) {
0767: if (parentClassLoader == null) {
0768: packages.addAll(BootstrapLoader.getPackages());
0769: } else {
0770: parentClassLoader.fillPackages(packages);
0771: }
0772: synchronized (definedPackages) {
0773: packages.addAll(definedPackages.values());
0774: }
0775: }
0776:
0777: /**
0778: * Helper method for defineClass(...)
0779: *
0780: * @return null if the package already has the same set of certificates, if
0781: * first class in the package is being defined then array of
0782: * certificates extracted from codeSource is returned.
0783: * @throws SecurityException if the package has different set of
0784: * certificates than codeSource
0785: */
0786: private Certificate[] getCertificates(String packageName,
0787: CodeSource codeSource) {
0788: Certificate[] definedCerts = (Certificate[]) packageCertificates
0789: .get(packageName);
0790: Certificate[] classCerts = codeSource != null ? codeSource
0791: .getCertificates() : EMPTY_CERTIFICATES;
0792: classCerts = classCerts != null ? classCerts
0793: : EMPTY_CERTIFICATES;
0794: // not first class in the package
0795: if (definedCerts != null) {
0796: if (!compareAsSet(definedCerts, classCerts)) {
0797: throw new SecurityException(
0798: "It is prohobited to define a "
0799: + "class which has different set of signers than "
0800: + "other classes in this package");
0801: }
0802: return null;
0803: }
0804: return classCerts;
0805: }
0806:
0807: /**
0808: * Helper method to avoid StringTokenizer using.
0809: */
0810: private static String[] fracture(String str, String sep) {
0811: if (str.length() == 0) {
0812: return new String[0];
0813: }
0814: ArrayList<String> res = new ArrayList<String>();
0815: int in = 0;
0816: int curPos = 0;
0817: int i = str.indexOf(sep);
0818: int len = sep.length();
0819: while (i != -1) {
0820: String s = str.substring(curPos, i);
0821: res.add(s);
0822: in++;
0823: curPos = i + len;
0824: i = str.indexOf(sep, curPos);
0825: }
0826:
0827: len = str.length();
0828: if (curPos <= len) {
0829: String s = str.substring(curPos, len);
0830: in++;
0831: res.add(s);
0832: }
0833:
0834: return res.toArray(new String[in]);
0835: }
0836:
0837: /* IBM SPECIFIC PART */
0838:
0839: static final ClassLoader getStackClassLoader(int depth) {
0840: Class<?> clazz = VMStack.getCallerClass(depth);
0841: return clazz != null ? clazz.getClassLoaderImpl() : null;
0842: }
0843:
0844: final boolean isSystemClassLoader() {
0845: return ClassLoaderInfo.isSystemClassLoader(this );
0846: }
0847:
0848: static final void loadLibraryWithClassLoader(String libName,
0849: ClassLoader loader) {
0850: SecurityManager sc = System.getSecurityManager();
0851: if (sc != null) {
0852: sc.checkLink(libName);
0853: }
0854: if (loader != null) {
0855: String fullLibName = loader.findLibrary(libName);
0856: if (fullLibName != null) {
0857: loadLibrary(fullLibName, loader, null);
0858: return;
0859: }
0860: }
0861: String path = System.getProperty("java.library.path", "");
0862: path += System.getProperty("vm.boot.library.path", "");
0863: loadLibrary(libName, loader, path);
0864: }
0865:
0866: static final void loadLibrary(String libName, ClassLoader loader,
0867: String libraryPath) {
0868: SecurityManager sc = System.getSecurityManager();
0869: if (sc != null) {
0870: sc.checkLink(libName);
0871: }
0872: String pathSeparator = System.getProperty("path.separator");
0873: String fileSeparator = System.getProperty("file.separator");
0874: String st[] = fracture(libraryPath, pathSeparator);
0875: int l = st.length;
0876: for (int i = 0; i < l; i++) {
0877: try {
0878: VMClassRegistry.loadLibrary(st[i] + fileSeparator
0879: + libName, loader);
0880: return;
0881: } catch (UnsatisfiedLinkError e) {
0882: }
0883: }
0884: throw new UnsatisfiedLinkError(libName);
0885: }
0886:
0887: /* END OF IBM SPECIFIC PART */
0888:
0889: static final class BootstrapLoader {
0890:
0891: // TODO avoid security checking
0892: private static final String bootstrapPath = System.getProperty(
0893: "vm.boot.class.path", "");
0894:
0895: private static URLClassLoader resourceFinder = null;
0896:
0897: private static final HashMap<String, Package> systemPackages = new HashMap<String, Package>();
0898:
0899: /**
0900: * This class contains static methods only. So it should not be
0901: * instantiated.
0902: */
0903: private BootstrapLoader() {
0904: }
0905:
0906: public static URL findResource(String name) {
0907: if (resourceFinder == null) {
0908: initResourceFinder();
0909: }
0910: return resourceFinder.findResource(name);
0911: }
0912:
0913: public static Enumeration<URL> findResources(String name)
0914: throws IOException {
0915: if (resourceFinder == null) {
0916: initResourceFinder();
0917: }
0918: return resourceFinder.findResources(name);
0919: }
0920:
0921: public static Package getPackage(String name) {
0922: synchronized (systemPackages) {
0923: updatePackages();
0924: return (Package) systemPackages.get(name.toString());
0925: }
0926: }
0927:
0928: public static Collection<Package> getPackages() {
0929: synchronized (systemPackages) {
0930: updatePackages();
0931: return systemPackages.values();
0932: }
0933: }
0934:
0935: private static void initResourceFinder() {
0936: synchronized (bootstrapPath) {
0937: if (resourceFinder != null) {
0938: return;
0939: }
0940: // -Xbootclasspath:"" should be interpreted as nothing defined,
0941: // like we do below:
0942: String st[] = fracture(bootstrapPath,
0943: File.pathSeparator);
0944: int l = st.length;
0945: ArrayList<URL> urlList = new ArrayList<URL>();
0946: for (int i = 0; i < l; i++) {
0947: try {
0948: urlList.add(new File(st[i]).toURI().toURL());
0949: } catch (MalformedURLException e) {
0950: }
0951: }
0952: URL[] urls = new URL[urlList.size()];
0953: resourceFinder = new URLClassLoader((URL[]) urlList
0954: .toArray(urls), null);
0955: }
0956: }
0957:
0958: private static void updatePackages() {
0959: String[][] packages = VMClassRegistry
0960: .getSystemPackages(systemPackages.size());
0961: if (null == packages) {
0962: return;
0963: }
0964: for (int i = 0; i < packages.length; i++) {
0965:
0966: String name = packages[i][0];
0967: if (systemPackages.containsKey(name)) {
0968: continue;
0969: }
0970:
0971: String jarURL = packages[i][1];
0972: systemPackages.put(name,
0973: new Package(null, name, jarURL));
0974: }
0975: }
0976: }
0977:
0978: private static final class SystemClassLoader extends URLClassLoader {
0979:
0980: private boolean checkingPackageAccess = false;
0981:
0982: private SystemClassLoader(URL[] urls, ClassLoader parent) {
0983: super (urls, parent);
0984: }
0985:
0986: @Override
0987: protected java.security.PermissionCollection getPermissions(
0988: CodeSource codesource) {
0989: java.security.PermissionCollection pc = super
0990: .getPermissions(codesource);
0991: pc
0992: .add(org.apache.harmony.lang.RuntimePermissionCollection.EXIT_VM_PERMISSION);
0993: return pc;
0994: }
0995:
0996: @Override
0997: protected synchronized Class<?> loadClass(String className,
0998: boolean resolveClass) throws ClassNotFoundException {
0999: SecurityManager sm = System.getSecurityManager();
1000: if (sm != null && !checkingPackageAccess) {
1001: int index = className.lastIndexOf('.');
1002: if (index > 0) { // skip if class is from a default package
1003: try {
1004: checkingPackageAccess = true;
1005: sm.checkPackageAccess(className.substring(0,
1006: index));
1007: } finally {
1008: checkingPackageAccess = false;
1009: }
1010: }
1011: }
1012: return super .loadClass(className, resolveClass);
1013: }
1014:
1015: private static URLClassLoader instance;
1016:
1017: static {
1018: ArrayList<URL> urlList = new ArrayList<URL>();
1019: // TODO avoid security checking?
1020: String extDirs = System.getProperty("java.ext.dirs", "");
1021:
1022: // -Djava.ext.dirs="" should be interpreted as nothing defined,
1023: // like we do below:
1024: String st[] = fracture(extDirs, File.pathSeparator);
1025: int l = st.length;
1026: for (int i = 0; i < l; i++) {
1027: try {
1028: File dir = new File(st[i]).getAbsoluteFile();
1029: File[] files = dir.listFiles();
1030: for (int j = 0; j < files.length; j++) {
1031: urlList.add(files[j].toURI().toURL());
1032: }
1033: } catch (Exception e) {
1034: }
1035: }
1036: // TODO avoid security checking?
1037: String classPath = System.getProperty("java.class.path",
1038: File.pathSeparator);
1039: st = fracture(classPath, File.pathSeparator);
1040: l = st.length;
1041: for (int i = 0; i < l; i++) {
1042: try {
1043: if (st[i].length() == 0) {
1044: st[i] = ".";
1045: }
1046: urlList.add(new File(st[i]).toURI().toURL());
1047: } catch (MalformedURLException e) {
1048: assert false : e.toString();
1049: }
1050: }
1051: instance = new SystemClassLoader((URL[]) urlList
1052: .toArray(new URL[urlList.size()]), null);
1053: }
1054:
1055: public static ClassLoader getInstance() {
1056: return instance;
1057: }
1058: }
1059: }
|