Lines 7-13
Link Here
|
7 |
* http://www.sun.com/ |
7 |
* http://www.sun.com/ |
8 |
* |
8 |
* |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun |
11 |
* Microsystems, Inc. All Rights Reserved. |
11 |
* Microsystems, Inc. All Rights Reserved. |
12 |
*/ |
12 |
*/ |
13 |
|
13 |
|
Lines 16-21
Link Here
|
16 |
import java.util.*; |
16 |
import java.util.*; |
17 |
import java.net.URL; |
17 |
import java.net.URL; |
18 |
import java.io.IOException; |
18 |
import java.io.IOException; |
|
|
19 |
import org.openide.ErrorManager; |
19 |
import org.openide.util.WeakSet; |
20 |
import org.openide.util.WeakSet; |
20 |
import org.openide.util.enum.RemoveDuplicatesEnumeration; |
21 |
import org.openide.util.enum.RemoveDuplicatesEnumeration; |
21 |
import org.openide.util.enum.SequenceEnumeration; |
22 |
import org.openide.util.enum.SequenceEnumeration; |
Lines 32-42
Link Here
|
32 |
*/ |
33 |
*/ |
33 |
public class ProxyClassLoader extends ClassLoader { |
34 |
public class ProxyClassLoader extends ClassLoader { |
34 |
|
35 |
|
35 |
/** <code>Set<ProxyClassLoader></code> of all live instancef of all |
|
|
36 |
* ProxyClassLoaders, usefull when we need to destroy a ProxyClassLoader |
37 |
* that is in other ProxyClassLoader's list of parents. |
38 |
*/ |
39 |
private static final Set instances = new WeakSet(); |
40 |
// Map<String,ClassLoader> |
36 |
// Map<String,ClassLoader> |
41 |
private final Map domainsByPackage = new HashMap(); |
37 |
private final Map domainsByPackage = new HashMap(); |
42 |
// Map<String,Package> |
38 |
// Map<String,Package> |
Lines 45-50
Link Here
|
45 |
// All parentf of this classloader, including their parents recursively |
41 |
// All parentf of this classloader, including their parents recursively |
46 |
private ClassLoader[] parents; |
42 |
private ClassLoader[] parents; |
47 |
|
43 |
|
|
|
44 |
/** if true, we have been destroyed */ |
45 |
private boolean dead = false; |
48 |
|
46 |
|
49 |
/** Create a multi-parented classloader. |
47 |
/** Create a multi-parented classloader. |
50 |
* @param parents list of parent classloaders. |
48 |
* @param parents list of parent classloaders. |
Lines 61-70
Link Here
|
61 |
if (check.contains(null)) throw new IllegalArgumentException("null parent"); // NOI18N |
59 |
if (check.contains(null)) throw new IllegalArgumentException("null parent"); // NOI18N |
62 |
|
60 |
|
63 |
this.parents = coalesceParents(parents); |
61 |
this.parents = coalesceParents(parents); |
64 |
|
|
|
65 |
synchronized (instances) { |
66 |
instances.add(this); |
67 |
} |
68 |
} |
62 |
} |
69 |
|
63 |
|
70 |
// this is used only by system classloader, maybe we can redesign it a bit |
64 |
// this is used only by system classloader, maybe we can redesign it a bit |
Lines 85-115
Link Here
|
85 |
|
79 |
|
86 |
|
80 |
|
87 |
|
81 |
|
88 |
// Is this needed? Before this classloader can go bye-bey, every childer |
|
|
89 |
// of it should be bye-bye too? Except SystemClassLoader |
90 |
/** Try to destroy this classloader. |
82 |
/** Try to destroy this classloader. |
91 |
* It will be removed from the parent lists of all existing ProxyClassLoaders. |
83 |
* Subsequent attempts to use it will log an error (at most one though). |
92 |
*/ |
84 |
*/ |
93 |
public void destroy() { |
85 |
public void destroy() { |
94 |
synchronized (instances) { |
86 |
dead = true; |
95 |
Iterator it = instances.iterator(); |
87 |
} |
96 |
while (it.hasNext()) { |
88 |
|
97 |
ProxyClassLoader pcl = (ProxyClassLoader)it.next(); |
89 |
private void zombieCheck() { |
98 |
synchronized (pcl) { |
90 |
if (dead) { |
99 |
ClassLoader[] p = pcl.parents; |
91 |
IllegalStateException ise = new IllegalStateException("Attempting to use a zombie classloader " + this); // NOI18N |
100 |
for (int i = 0; i < p.length; i++) { |
92 |
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ise); |
101 |
if (p[i] == this) { |
93 |
// don't warn again for same loader... this was enough |
102 |
ClassLoader[] p2 = new ClassLoader[p.length - 1]; |
94 |
dead = false; |
103 |
if (i > 0) System.arraycopy(p, 0, p2, 0, i); |
|
|
104 |
if (i < p.length - 1) System.arraycopy(p, i + 1, p2, i, p.length - i - 1); |
105 |
pcl.parents = p2; |
106 |
break; |
107 |
} |
108 |
} |
109 |
Collection c = pcl.domainsByPackage.values(); |
110 |
while (c.remove(this)) ; |
111 |
} |
112 |
} |
113 |
} |
95 |
} |
114 |
} |
96 |
} |
115 |
|
97 |
|
Lines 133-138
Link Here
|
133 |
*/ |
115 |
*/ |
134 |
protected synchronized final Class loadClass(String name, boolean resolve) |
116 |
protected synchronized final Class loadClass(String name, boolean resolve) |
135 |
throws ClassNotFoundException { |
117 |
throws ClassNotFoundException { |
|
|
118 |
zombieCheck(); |
136 |
final int dotIdx = name.lastIndexOf('.'); |
119 |
final int dotIdx = name.lastIndexOf('.'); |
137 |
if (dotIdx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N |
120 |
if (dotIdx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N |
138 |
Class c = smartLoadClass(name, dotIdx); |
121 |
Class c = smartLoadClass(name, dotIdx); |
Lines 175-180
Link Here
|
175 |
* @see #findResource(String) |
158 |
* @see #findResource(String) |
176 |
*/ |
159 |
*/ |
177 |
public final URL getResource(final String name) { |
160 |
public final URL getResource(final String name) { |
|
|
161 |
zombieCheck(); |
178 |
final int slashIdx = name.lastIndexOf('/'); |
162 |
final int slashIdx = name.lastIndexOf('/'); |
179 |
if (slashIdx == -1) return null; // won't load from the default package |
163 |
if (slashIdx == -1) return null; // won't load from the default package |
180 |
final String pkg = name.substring(0, slashIdx); |
164 |
final String pkg = name.substring(0, slashIdx); |
Lines 235-240
Link Here
|
235 |
* @throws IOException if I/O errors occur |
219 |
* @throws IOException if I/O errors occur |
236 |
*/ |
220 |
*/ |
237 |
protected final synchronized Enumeration findResources(String name) throws IOException { |
221 |
protected final synchronized Enumeration findResources(String name) throws IOException { |
|
|
222 |
zombieCheck(); |
238 |
// Don't bother optimizing this call by domains--it is practically unused. |
223 |
// Don't bother optimizing this call by domains--it is practically unused. |
239 |
Enumeration e = simpleFindResources(name); |
224 |
Enumeration e = simpleFindResources(name); |
240 |
for (int i = parents.length - 1; i >= 0; i--) { |
225 |
for (int i = parents.length - 1; i >= 0; i--) { |
Lines 265-270
Link Here
|
265 |
* @return the Package corresponding to the given name, or null if not found |
250 |
* @return the Package corresponding to the given name, or null if not found |
266 |
*/ |
251 |
*/ |
267 |
protected Package getPackage(String name) { |
252 |
protected Package getPackage(String name) { |
|
|
253 |
zombieCheck(); |
268 |
synchronized (packages) { |
254 |
synchronized (packages) { |
269 |
Package pkg = (Package)packages.get(name); |
255 |
Package pkg = (Package)packages.get(name); |
270 |
if (pkg != null) return pkg; |
256 |
if (pkg != null) return pkg; |
Lines 305-310
Link Here
|
305 |
* <code>ClassLoader</code> |
291 |
* <code>ClassLoader</code> |
306 |
*/ |
292 |
*/ |
307 |
protected synchronized Package[] getPackages() { |
293 |
protected synchronized Package[] getPackages() { |
|
|
294 |
zombieCheck(); |
308 |
Map all = new HashMap(); // Map<String,Package> |
295 |
Map all = new HashMap(); // Map<String,Package> |
309 |
addPackages(all, super.getPackages()); |
296 |
addPackages(all, super.getPackages()); |
310 |
for (int i = 0; i < parents.length; i++) { |
297 |
for (int i = 0; i < parents.length; i++) { |