114 |
public abstract class ClassLoader |
public abstract class ClassLoader |
115 |
{ |
{ |
116 |
/** All classes loaded by this classloader. */ |
/** All classes loaded by this classloader. */ |
117 |
private Hashtable loadedClasses = new Hashtable(); |
private final Map loadedClasses = new HashMap(); |
118 |
|
|
119 |
/** All packages defined by this classloader. */ |
/** All packages defined by this classloader. */ |
120 |
private Hashtable definedPackages = new Hashtable(); |
private final Map definedPackages = new HashMap(); |
121 |
|
|
122 |
/** |
/** |
123 |
* The classloader that is consulted before this classloader. |
* The classloader that is consulted before this classloader. |
126 |
private final ClassLoader parent; |
private final ClassLoader parent; |
127 |
|
|
128 |
/** |
/** |
129 |
* System/Application classloader gnu.java.lang.SystemClassLoader. |
* System/Application classloader: defaults to an instance of |
130 |
* Due to bootstrapping issues, the VM must modify this field. |
* gnu.java.lang.SystemClassLoader, unless the first invocation of |
131 |
|
* getSystemClassLoader loads another class loader because of the |
132 |
|
* java.system.class.loader property. |
133 |
|
* |
134 |
|
* XXX - The VM may needs to modify this field or set it to something |
135 |
|
* else, until gnu.java.lang.SystemClassLoader is correctly implemented. |
136 |
|
*/ |
137 |
|
static final ClassLoader systemClassLoader = getSystemClassLoader(); |
138 |
|
|
139 |
|
/** |
140 |
|
* The default protection domain, used when defining a class with a null |
141 |
|
* paramter for the domain. |
142 |
*/ |
*/ |
143 |
static final ClassLoader systemClassLoader |
static final ProtectionDomain defaultProtectionDomain; |
144 |
= null; // XXX = SystemClassLoader.getInstance(); |
static |
145 |
|
{ |
146 |
|
CodeSource cs = new CodeSource(null, null); |
147 |
|
PermissionCollection perm = Policy.getPolicy().getPermissions(cs); |
148 |
|
defaultProtectionDomain = new ProtectionDomain(cs, perm); |
149 |
|
} |
150 |
|
|
151 |
/** |
/** |
152 |
* The desired assertion status of classes loaded by this loader, if not |
* The desired assertion status of classes loaded by this loader, if not |
153 |
* overridden by package or class instructions. |
* overridden by package or class instructions. |
154 |
* @XXX Implement for 1.4 compatibility. |
*/ |
155 |
// Package visible for use by Class. |
// Package visible for use by Class. |
156 |
boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); |
boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); |
|
*/ |
|
157 |
|
|
158 |
/** |
/** |
159 |
* The command-line state of the package assertion status overrides. This |
* The command-line state of the package assertion status overrides. This |
160 |
* map is never modified, so it does not need to be synchronized. |
* map is never modified, so it does not need to be synchronized. |
161 |
* @XXX Implement for 1.4 compatibility. |
*/ |
162 |
// Package visible for use by Class. |
// Package visible for use by Class. |
163 |
static final Map systemPackageAssertionStatus |
static final Map systemPackageAssertionStatus |
164 |
= VMClassLoader.packageAssertionStatus(); |
= VMClassLoader.packageAssertionStatus(); |
|
*/ |
|
165 |
|
|
166 |
/** |
/** |
167 |
* The map of package assertion status overrides, or null if no package |
* The map of package assertion status overrides, or null if no package |
168 |
* overrides have been specified yet. The values of the map should be |
* overrides have been specified yet. The values of the map should be |
169 |
* Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented |
* Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented |
170 |
* by the null key. This map must be synchronized on this instance. |
* by the null key. This map must be synchronized on this instance. |
171 |
* @XXX Implement for 1.4 compatibility. |
*/ |
172 |
// Package visible for use by Class. |
// Package visible for use by Class. |
173 |
Map packageAssertionStatus; |
Map packageAssertionStatus; |
|
*/ |
|
174 |
|
|
175 |
/** |
/** |
176 |
* The command-line state of the class assertion status overrides. This |
* The command-line state of the class assertion status overrides. This |
177 |
* map is never modified, so it does not need to be synchronized. |
* map is never modified, so it does not need to be synchronized. |
178 |
* @XXX Implement for 1.4 compatibility. |
*/ |
179 |
// Package visible for use by Class. |
// Package visible for use by Class. |
180 |
static final Map systemClassAssertionStatus |
static final Map systemClassAssertionStatus |
181 |
= VMClassLoader.classAssertionStatus(); |
= VMClassLoader.classAssertionStatus(); |
|
*/ |
|
182 |
|
|
183 |
/** |
/** |
184 |
* The map of class assertion status overrides, or null if no class |
* The map of class assertion status overrides, or null if no class |
185 |
* overrides have been specified yet. The values of the map should be |
* overrides have been specified yet. The values of the map should be |
186 |
* Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this |
* Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this |
187 |
* instance. |
* instance. |
188 |
* @XXX Implement for 1.4 compatibility. |
*/ |
189 |
// Package visible for use by Class. |
// Package visible for use by Class. |
190 |
Map classAssertionStatus; |
Map classAssertionStatus; |
|
*/ |
|
191 |
|
|
192 |
/** |
/** |
193 |
* Create a new ClassLoader with as parent the system classloader. There |
* Create a new ClassLoader with as parent the system classloader. There |
197 |
*/ |
*/ |
198 |
protected ClassLoader() throws SecurityException |
protected ClassLoader() throws SecurityException |
199 |
{ |
{ |
200 |
//XXX This should be this(getSystemClassLoader()); |
this(getSystemClassLoader()); |
|
this(systemClassLoader); |
|
201 |
} |
} |
202 |
|
|
203 |
/** |
/** |
267 |
if (c != null) |
if (c != null) |
268 |
return c; |
return c; |
269 |
|
|
270 |
// Can the class be loaded by one of our parent? |
// Can the class been loaded by a parent? |
271 |
try |
try |
272 |
{ |
{ |
273 |
if (parent == null) |
if (parent == null) |
274 |
// XXX - use the bootstrap classloader |
return VMClassLoader.loadClass(name, resolve); |
|
// return VMClassLoader.loadClass(name, resolve); |
|
|
return findSystemClass(name); |
|
275 |
return parent.loadClass(name, resolve); |
return parent.loadClass(name, resolve); |
276 |
} |
} |
277 |
catch (ClassNotFoundException e) |
catch (ClassNotFoundException e) |
278 |
{ |
{ |
279 |
// Ignore, use findClass(). |
// Still not found, we have to do it ourself. |
280 |
|
c = findClass(name); |
281 |
|
if (resolve) |
282 |
|
resolveClass(c); |
283 |
|
return c; |
284 |
} |
} |
|
|
|
|
// Still not found, we have to do it ourself. |
|
|
c = findClass(name); |
|
|
if (resolve) |
|
|
resolveClass(c); |
|
|
return c; |
|
285 |
} |
} |
286 |
|
|
287 |
/** |
/** |
355 |
* ProtectionDomain. Subclasses should call this method from their |
* ProtectionDomain. Subclasses should call this method from their |
356 |
* <code>findClass()</code> implementation. The name should use '.' |
* <code>findClass()</code> implementation. The name should use '.' |
357 |
* separators, and discard the trailing ".class". The default protection |
* separators, and discard the trailing ".class". The default protection |
358 |
* domain is <code>Policy.getPolicy().getPermissions(null, null)<code>. |
* domain has the permissions of |
359 |
|
* <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code>. |
360 |
* |
* |
361 |
* @param name the name to give the class, or null if unknown |
* @param name the name to give the class, or null if unknown |
362 |
* @param data the data representing the classfile, in classfile format |
* @param data the data representing the classfile, in classfile format |
372 |
protected final Class defineClass(String name, byte[] data, int offset, |
protected final Class defineClass(String name, byte[] data, int offset, |
373 |
int len) throws ClassFormatError |
int len) throws ClassFormatError |
374 |
{ |
{ |
375 |
// XXX - return defineClass(name, data, offset, len, null); |
return defineClass(name, data, offset, len, null); |
|
Class retval = VMClassLoader.defineClass(this, name, data, offset, len); |
|
|
loadedClasses.put(retval.getName(), retval); |
|
|
return retval; |
|
376 |
} |
} |
377 |
|
|
378 |
/** |
/** |
379 |
* Helper to define a class using a string of bytes. Subclasses should call |
* Helper to define a class using a string of bytes. Subclasses should call |
380 |
* this method from their <code>findClass()</code> implementation. If the |
* this method from their <code>findClass()</code> implementation. If the |
381 |
* domain is null, the default of |
* domain is null, the default of |
382 |
* <code>Policy.getPolicy().getPermissions(null, null)<code> is used. |
* <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code> |
383 |
* Once a class has been defined in a package, all further classes in that |
* is used. Once a class has been defined in a package, all further classes |
384 |
* package must have the same set of certificates or a SecurityException is |
* in that package must have the same set of certificates or a |
385 |
* thrown |
* SecurityException is thrown. |
386 |
* |
* |
387 |
* XXX - not implemented yet. Needs native support. |
* XXX - protection domain is not implemented yet; it needs native support. |
388 |
* |
* |
389 |
* @param name the name to give the class. null if unknown |
* @param name the name to give the class. null if unknown |
390 |
* @param data the data representing the classfile, in classfile format |
* @param data the data representing the classfile, in classfile format |
404 |
int len, ProtectionDomain domain) |
int len, ProtectionDomain domain) |
405 |
throws ClassFormatError |
throws ClassFormatError |
406 |
{ |
{ |
407 |
/* XXX - needs native support. |
if (domain == null) |
408 |
Class retval |
domain = defaultProtectionDomain; |
409 |
= VMClassLoader.defineClass(this, name, data, offset, len, domain); |
Class retval = VMClassLoader.defineClass(this, name, data, |
410 |
|
offset, len, domain); |
411 |
loadedClasses.put(retval.getName(), retval); |
loadedClasses.put(retval.getName(), retval); |
412 |
return retval; |
return retval; |
|
*/ |
|
|
return defineClass(name, data, offset, len); |
|
413 |
} |
} |
414 |
|
|
415 |
/** |
/** |
437 |
protected final Class findSystemClass(String name) |
protected final Class findSystemClass(String name) |
438 |
throws ClassNotFoundException |
throws ClassNotFoundException |
439 |
{ |
{ |
440 |
// XXX This should be: |
return Class.forName(name, false, getSystemClassLoader()); |
|
// return Class.forName(name, false, getSystemClassLoader()); |
|
|
return Class.forName(name); |
|
441 |
} |
} |
442 |
|
|
443 |
/** |
/** |
507 |
URL result; |
URL result; |
508 |
|
|
509 |
if (parent == null) |
if (parent == null) |
510 |
// XXX - try bootstrap classloader; |
result = VMClassLoader.getResource(name); |
511 |
// result = VMClassLoader.getResource(name); |
else |
512 |
return ClassLoader.getSystemResource(name); |
result = parent.getResource(name); |
|
result = parent.getResource(name); |
|
513 |
|
|
514 |
if (result == null) |
if (result == null) |
515 |
result = findResource(name); |
result = findResource(name); |
540 |
{ |
{ |
541 |
Enumeration parentResources; |
Enumeration parentResources; |
542 |
if (parent == null) |
if (parent == null) |
543 |
// XXX - Should use the bootstrap classloader |
parentResources = VMClassLoader.getResources(name); |
|
parentResources = EmptyEnumeration.getInstance(); |
|
544 |
else |
else |
545 |
parentResources = parent.getResources(name); |
parentResources = parent.getResources(name); |
546 |
return new DoubleEnumeration(parentResources, findResources(name)); |
return new DoubleEnumeration(parentResources, findResources(name)); |
643 |
*/ |
*/ |
644 |
public static Enumeration getSystemResources(String name) throws IOException |
public static Enumeration getSystemResources(String name) throws IOException |
645 |
{ |
{ |
646 |
// XXX should be |
return getSystemClassLoader().getResources(name); |
|
// return getSystemClassLoader().getResources(name); |
|
|
return systemClassLoader.getResources(name); |
|
647 |
} |
} |
648 |
|
|
649 |
/** |
/** |
661 |
*/ |
*/ |
662 |
public InputStream getResourceAsStream(String name) |
public InputStream getResourceAsStream(String name) |
663 |
{ |
{ |
|
URL url = getResource(name); |
|
|
if (url == null) |
|
|
return null; |
|
664 |
try |
try |
665 |
{ |
{ |
666 |
|
URL url = getResource(name); |
667 |
|
if (url == null) |
668 |
|
return null; |
669 |
return url.openStream(); |
return url.openStream(); |
670 |
} |
} |
671 |
catch(IOException e) |
catch (IOException e) |
672 |
{ |
{ |
673 |
return null; |
return null; |
674 |
} |
} |
690 |
return null; |
return null; |
691 |
return url.openStream(); |
return url.openStream(); |
692 |
} |
} |
693 |
catch(IOException e) |
catch (IOException e) |
694 |
{ |
{ |
695 |
return null; |
return null; |
696 |
} |
} |
706 |
* name of the class to use as the system class loader, otherwise this |
* name of the class to use as the system class loader, otherwise this |
707 |
* uses gnu.java.lang.SystemClassLoader. |
* uses gnu.java.lang.SystemClassLoader. |
708 |
* |
* |
709 |
|
* XXX - overriding the class loader does not currently work |
710 |
|
* |
711 |
* <p>Note that this is different from the bootstrap classloader that |
* <p>Note that this is different from the bootstrap classloader that |
712 |
* actually loads all the real "system" classes (the bootstrap classloader |
* actually loads all the real "system" classes (the bootstrap classloader |
713 |
* is the parent of the returned system classloader). |
* is the parent of the returned system classloader). |
724 |
*/ |
*/ |
725 |
public static ClassLoader getSystemClassLoader() |
public static ClassLoader getSystemClassLoader() |
726 |
{ |
{ |
727 |
//XXX This needs to check for java.system.class.loader. |
// This method is called as the initialization of systemClassLoader, |
728 |
|
// so if there is a null value, this is the first call and we must check |
729 |
|
// for java.system.class.loader. |
730 |
|
if (systemClassLoader == null) |
731 |
|
{ |
732 |
|
// XXX return SystemClassLoader.getInstance(); |
733 |
|
} |
734 |
// Check if we may return the system classloader |
// Check if we may return the system classloader |
735 |
SecurityManager sm = System.getSecurityManager(); |
SecurityManager sm = System.getSecurityManager(); |
736 |
if (sm != null) |
if (sm != null) |
781 |
+ " already defined"); |
+ " already defined"); |
782 |
Package p = new Package(name, specTitle, specVendor, specVersion, |
Package p = new Package(name, specTitle, specVendor, specVersion, |
783 |
implTitle, implVendor, implVersion, sealed); |
implTitle, implVendor, implVersion, sealed); |
784 |
definedPackages.put(name, p); |
synchronized (definedPackages) |
785 |
|
{ |
786 |
|
definedPackages.put(name, p); |
787 |
|
} |
788 |
return p; |
return p; |
789 |
} |
} |
790 |
|
|
801 |
{ |
{ |
802 |
Package p; |
Package p; |
803 |
if (parent == null) |
if (parent == null) |
804 |
// XXX - Should we use the bootstrap classloader? |
p = VMClassLoader.getPackage(name); |
|
p = null; |
|
805 |
else |
else |
806 |
p = parent.getPackage(name); |
p = parent.getPackage(name); |
807 |
|
|
808 |
if (p == null) |
if (p == null) |
809 |
p = (Package)definedPackages.get(name); |
synchronized (definedPackages) |
810 |
|
{ |
811 |
|
p = (Package) definedPackages.get(name); |
812 |
|
} |
813 |
return p; |
return p; |
814 |
} |
} |
815 |
|
|
821 |
*/ |
*/ |
822 |
protected Package[] getPackages() |
protected Package[] getPackages() |
823 |
{ |
{ |
|
Package[] allPackages; |
|
|
|
|
824 |
// Get all our packages. |
// Get all our packages. |
825 |
Package[] packages; |
Package[] packages; |
826 |
synchronized(definedPackages) |
synchronized(definedPackages) |
827 |
{ |
{ |
828 |
packages = new Package[definedPackages.size()]; |
packages = new Package[definedPackages.size()]; |
829 |
Enumeration e = definedPackages.elements(); |
definedPackages.values().toArray(packages); |
|
int i = 0; |
|
|
while (e.hasMoreElements()) |
|
|
{ |
|
|
packages[i] = (Package)e.nextElement(); |
|
|
i++; |
|
|
} |
|
830 |
} |
} |
831 |
|
|
832 |
// If we have a parent get all packages defined by our parents. |
// If we have a parent get all packages defined by our parents. |
833 |
if (parent != null) |
Package[] parentPackages; |
834 |
{ |
if (parent == null) |
835 |
Package[] parentPackages = parent.getPackages(); |
parentPackages = VMClassLoader.getPackages(); |
836 |
allPackages = new Package[parentPackages.length + packages.length]; |
else |
837 |
System.arraycopy(parentPackages, 0, allPackages, 0, |
parentPackages = parent.getPackages(); |
|
parentPackages.length); |
|
|
System.arraycopy(packages, 0, allPackages, parentPackages.length, |
|
|
packages.length); |
|
|
} else |
|
|
// XXX - Should we use the bootstrap classloader? |
|
|
allPackages = packages; |
|
838 |
|
|
839 |
|
Package[] allPackages = new Package[parentPackages.length |
840 |
|
+ packages.length]; |
841 |
|
System.arraycopy(parentPackages, 0, allPackages, 0, |
842 |
|
parentPackages.length); |
843 |
|
System.arraycopy(packages, 0, allPackages, parentPackages.length, |
844 |
|
packages.length); |
845 |
return allPackages; |
return allPackages; |
846 |
} |
} |
847 |
|
|
874 |
* @see #setPackageAssertionStatus(String, boolean) |
* @see #setPackageAssertionStatus(String, boolean) |
875 |
* @see #clearAssertionStatus() |
* @see #clearAssertionStatus() |
876 |
* @since 1.4 |
* @since 1.4 |
877 |
* @XXX Implement for 1.4 compatibility. |
*/ |
878 |
public void setDefaultAssertionStatus(boolean enabled) |
public void setDefaultAssertionStatus(boolean enabled) |
879 |
{ |
{ |
880 |
defaultAssertionStatus = enabled; |
defaultAssertionStatus = enabled; |
881 |
} |
} |
|
*/ |
|
882 |
|
|
883 |
/** |
/** |
884 |
* Set the default assertion status for packages, used unless overridden |
* Set the default assertion status for packages, used unless overridden |
891 |
* @see #setClassAssertionStatus(String, boolean) |
* @see #setClassAssertionStatus(String, boolean) |
892 |
* @see #clearAssertionStatus() |
* @see #clearAssertionStatus() |
893 |
* @since 1.4 |
* @since 1.4 |
894 |
* @XXX Implement for 1.4 compatibility. |
*/ |
895 |
public synchronized void setPackageAssertionStatus(String name, |
public synchronized void setPackageAssertionStatus(String name, |
896 |
boolean enabled) |
boolean enabled) |
897 |
{ |
{ |
900 |
= new HashMap(systemPackageAssertionStatus); |
= new HashMap(systemPackageAssertionStatus); |
901 |
packageAssertionStatus.put(name, Boolean.valueOf(enabled)); |
packageAssertionStatus.put(name, Boolean.valueOf(enabled)); |
902 |
} |
} |
|
*/ |
|
903 |
|
|
904 |
/** |
/** |
905 |
* Set the default assertion status for a class. This only affects the |
* Set the default assertion status for a class. This only affects the |
912 |
* @see #setPackageAssertionStatus(String, boolean) |
* @see #setPackageAssertionStatus(String, boolean) |
913 |
* @see #clearAssertionStatus() |
* @see #clearAssertionStatus() |
914 |
* @since 1.4 |
* @since 1.4 |
915 |
* @XXX Implement for 1.4 compatibility. |
*/ |
916 |
public synchronized void setClassAssertionStatus(String name, |
public synchronized void setClassAssertionStatus(String name, |
917 |
boolean enabled) |
boolean enabled) |
918 |
{ |
{ |
921 |
// The toString() hack catches null, as required. |
// The toString() hack catches null, as required. |
922 |
classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); |
classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); |
923 |
} |
} |
|
*/ |
|
924 |
|
|
925 |
/** |
/** |
926 |
* Resets the default assertion status of this classloader, its packages |
* Resets the default assertion status of this classloader, its packages |
931 |
* @see #setClassAssertionStatus(String, boolean) |
* @see #setClassAssertionStatus(String, boolean) |
932 |
* @see #setPackageAssertionStatus(String, boolean) |
* @see #setPackageAssertionStatus(String, boolean) |
933 |
* @since 1.4 |
* @since 1.4 |
934 |
* @XXX Implement for 1.4 compatibility. |
*/ |
935 |
public synchronized void clearAssertionStatus() |
public synchronized void clearAssertionStatus() |
936 |
{ |
{ |
937 |
defaultAssertionStatus = false; |
defaultAssertionStatus = false; |
938 |
packageAssertionStatus = new HashMap(); |
packageAssertionStatus = new HashMap(); |
939 |
classAssertionStatus = new HashMap(); |
classAssertionStatus = new HashMap(); |
940 |
} |
} |
|
*/ |
|
|
|
|
941 |
} |
} |
|
|
|