patch
to modify the superclass of this
+ * class.
+ *
+ * @param arr the bytecode to change
+ * @param superClass name of the new superclass like java/awt/Button
+ * @return new version of the bytecode if changed, otherwise null to signal that
+ * no change has been made
+ */
+ public static byte[] enhance (byte[] arr, String superClass) {
+ if (isPatched (arr)) {
+ // already patched
+ return null;
+ }
+
+ PatchByteCode pc = new PatchByteCode (arr);
+
+ if (superClass != null) {
+ int x = pc.addClass (superClass);
+
+
+ byte[] sup = new byte[2];
+ writeU2 (sup, 0, x);
+ pc.addAttribute (ATTR_SUPERCLASS, sup);
+
+ byte[] patch = {
+ 'n', 'b' // identification at the end of class file
+ };
+
+ pc.addAttribute ("org.netbeans.enhanced", patch);
+ }
+
+ // if we patch the class then it is supposed to be public
+ if (!pc.makePublic () && superClass == null) {
+ // if it already was public and no superclass change
+ return null;
+ }
+
+
+ // otherwise do the patching
+ return pc.getClassFile ();
+ }
+
+ /** Checks if the class has previously been enhanced by the
+ * change of superclass attribute and if so, changes the bytecode
+ * to reflect the change.
+ *
+ * @param arr the bytecode
+ * @return the enhanced bytecode
+ */
+ public static byte[] patch (byte[] arr) {
+ if (!isPatched (arr)) return arr;
+
+ PatchByteCode pc = new PatchByteCode (arr);
+ if (pc.superClassNameAttr > 0) {
+ // let's patch
+ int classindex = pc.readU2 (pc.superClassNameAttr + 6);
+
+ writeU2 (pc.getClassFile(), pc.cpEnd + 4, classindex);
+ }
+
+ return pc.getClassFile ();
+ }
+
+
+ /** Check if the byte code is patched.
+ * @param arr the bytecode
+ * @return true if patched
+ */
+ private static boolean isPatched (byte[] arr) {
+ if (arr == null || arr.length < 2) return false;
+
+ int base = arr.length - 2;
+ if (arr[base + 1] != 'b') return false;
+ if (arr[base + 0] != 'n') return false;
+
+ //
+ // ok, looks like enhanced byte code
+ //
+ return true;
+ }
+
+
+
+
+
+
+
+ /** Gets the current byte array of the actual class file.
+ * @return bytes of the class file
+ */
+ private byte[] getClassFile () {
+ return arr;
+ }
+
+ /** Creates new contant pool entry representing given class.
+ * @param c name of the class
+ * @return index of the entry
+ */
+ private int addClass (String s) {
+ int x = addConstant (s);
+
+ byte[] t = { 7, 0, 0 };
+ writeU2 (t, 1, x);
+
+ return addPool (t);
+ }
+
+ /** Adds a new string constant to the constant pool.
+ * @param s the string to add
+ * @return index of the constant
+ */
+ private int addConstant (String s) {
+ byte[] t;
+
+ try {
+ t = s.getBytes("utf-8"); // NOI18N
+ } catch (java.io.UnsupportedEncodingException ex) {
+ throw new IllegalStateException ("UTF-8 shall be always supported"); // NOI18N
+ }
+
+ byte[] add = new byte[t.length + 3];
+ System.arraycopy (t, 0, add, 3, t.length);
+ add[0] = 1; // UTF8 contant
+ writeU2 (add, 1, t.length);
+
+ return addPool (add);
+ }
+
+ /** Adds this array of bytes as another entry into the constant pool */
+ private int addPool (byte[] add) {
+ byte[] res = new byte[arr.length + add.length];
+
+ System.arraycopy (arr, 0, res, 0, cpEnd);
+ // increments number of objects in contant pool
+ int index = readU2 (cpCount);
+ writeU2 (res, cpCount, index + 1);
+
+ // adds the content
+ System.arraycopy (add, 0, res, cpEnd, add.length);
+
+ // and now add the rest of the original array
+ System.arraycopy (arr, cpEnd, res, cpEnd + add.length, arr.length - cpEnd);
+
+ arr = res;
+
+ cpEnd += add.length;
+ atCount += add.length;
+ atEnd += add.length;
+
+ // the index
+ return index;
+ }
+
+ /** Ensures that the class is public
+ * @return true if really patched, false if not
+ */
+ private boolean makePublic () {
+ int x = readU2 (cpEnd);
+
+ if ((x & 0x0001) != 0) {
+ return false;
+ }
+
+ x |= 0x0001; // adds public field
+ writeU2 (arr, cpEnd, x);
+
+ return true;
+ }
+
+ /** Adds an attribute to the class file.
+ * @param name name of the attribute to add
+ * @param b the bytes representing the attribute
+ */
+ private void addAttribute (String name, byte[] b) {
+ int index;
+ if (ATTR_SUPERCLASS.equals (name) && superClassNameIndex > 0) {
+ index = superClassNameIndex;
+ } else {
+ // register new attribute
+ index = addConstant (name);
+ }
+
+ byte[] res = new byte[arr.length + b.length + 6];
+
+ System.arraycopy(arr, 0, res, 0, arr.length);
+
+ writeU2 (res, arr.length, index);
+ writeU4 (res, arr.length + 2, b.length);
+
+ int begin = arr.length + 6;
+ System.arraycopy(b, 0, res, begin, b.length);
+
+ atEnd += b.length + 6;
+
+ writeU2 (res, atCount, readU2 (atCount) + 1);
+
+ arr = res;
+ }
+
+
+ /** Gets i-th element from the array.
+ */
+ private int get (int pos) {
+ if (pos >= arr.length) {
+ throw new ArrayIndexOutOfBoundsException ("Size: " + arr.length + " index: " + pos);
+ }
+
+ int x = arr[pos];
+ return x >= 0 ? x : 256 + x;
+ }
+
+ /** Scans the file to find out important possitions
+ * @return size of the bytecode
+ */
+ private void scan () {
+ if (get (0) != 0xCA && get (1) != 0xFE && get (2) != 0xBA && get (3) != 0xBE) {
+ throw new IllegalStateException ("Not a class file!"); // NOI18N
+ }
+
+ int pos = 10;
+ // count of items in CP is here
+ cpCount = 8;
+
+ int cp = readU2 (8);
+ for (int[] i = { 1 }; i[0] < cp; i[0]++) {
+ // i[0] can be incremented in constantPoolSize
+ int len = constantPoolSize (pos, i);
+ pos += len;
+ }
+
+ // list item in constant pool
+ cpEnd = pos;
+
+ pos += 6;
+ // now add interfaces
+ pos += 2 * readU2 (pos);
+ // to add also the integer with interfaces
+ pos += 2;
+
+ // fields
+ int fields = readU2 (pos);
+ pos += 2;
+ while (fields-- > 0) {
+ pos += fieldSize (pos);
+ }
+
+ int methods = readU2 (pos);
+ pos += 2;
+ while (methods-- > 0) {
+ pos += methodSize (pos);
+ }
+
+ // count of items in Attributes is here
+ atCount = pos;
+ int attrs = readU2 (pos);
+ pos += 2;
+ while (attrs-- > 0) {
+ pos += attributeSize (pos);
+ }
+
+ // end of attributes
+ atEnd = pos;
+ }
+
+ private int readU2 (int pos) {
+ int b1 = get (pos);
+ int b2 = get (pos + 1);
+
+ return b1 * 256 + b2;
+ }
+
+ private int readU4 (int pos) {
+ return readU2 (pos) * 256 * 256 + readU2 (pos + 2);
+ }
+
+ private static void writeU2 (byte[] arr, int pos, int value) {
+ int v1 = (value & 0xff00) >> 8;
+ int v2 = value & 0xff;
+
+ if (v1 < 0) v1 += 256;
+ if (v2 < 0) v2 += 256;
+
+ arr[pos] = (byte)v1;
+ arr[pos + 1] = (byte)v2;
+ }
+
+ private static void writeU4 (byte[] arr, int pos, int value) {
+ writeU2 (arr, pos, (value & 0xff00) >> 16);
+ writeU2 (arr, pos + 2, value & 0x00ff);
+ }
+
+ /** @param pos position to read from
+ * @param cnt[0] index in the pool that we are now reading
+ */
+ private int constantPoolSize (int pos, int[] cnt) {
+ switch (get (pos)) {
+ case 7: // CONSTANT_Class
+ case 8: // CONSTANT_String
+ return 3;
+ case 9: // CONSTANT_Fieldref
+ case 10: // CONSTANT_Methodref
+ case 11: // CONSTANT_InterfaceMethodref
+ case 3: // CONSTANT_Integer
+ case 4: // CONSTANT_Float
+ case 12: // CONSTANT_NameAndType
+ return 5;
+ case 5: // CONSTANT_Long
+ case 6: // CONSTANT_Double
+ // after long and double the next entry in CP is unusable
+ cnt[0]++;
+ return 9;
+ case 1: // CONSTANT_Utf8
+ int len = readU2 (pos + 1);
+
+ if (BYTE_SUPERCLASS.length == len) {
+ int base = pos + 3;
+ // we are searching for an attribute with given name
+ for (int i = 0; i < BYTE_SUPERCLASS.length; i++) {
+ if (BYTE_SUPERCLASS[i] != arr[base + i]) {
+ // regular exit
+ return len + 3;
+ }
+ }
+
+ // we have found the attribute
+ if (superClassNameIndex != 0) {
+ throw new IllegalStateException (ATTR_SUPERCLASS + " registered for the second time!"); // NOI18N
+ }
+
+ superClassNameIndex = cnt[0];
+ }
+
+ // ok, exit
+ return len + 3;
+ default:
+ throw new IllegalStateException ("Unknown pool type: " + get (pos)); // NOI18N
+ }
+ }
+
+ private int fieldSize (int pos) {
+ int s = 8;
+ int cnt = readU2 (pos + 6);
+ while (cnt-- > 0) {
+ s += attributeSize (pos + s);
+ }
+ return s;
+ }
+
+ private int methodSize (int pos) {
+ return fieldSize (pos);
+ }
+
+ private int attributeSize (int pos) {
+ if (superClassNameIndex > 0) {
+ // index to the name attr
+ int name = readU2 (pos);
+
+ if (name == superClassNameIndex) {
+ if (superClassNameAttr > 0) {
+ throw new IllegalStateException ("Two attributes with name " + ATTR_SUPERCLASS); // NOI18N
+ }
+
+ // we found the attribute
+ superClassNameAttr = pos;
+ }
+ }
+
+ int len = readU4 (pos + 2);
+ return len + 6;
+ }
+}
Index: nb_all/core/src/org/netbeans/ProxyClassLoader.java
===================================================================
RCS file: nb_all/core/src/org/netbeans/ProxyClassLoader.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ nb_all/core/src/org/netbeans/ProxyClassLoader.java 29 Jul 2002 19:26:34 -0000
@@ -0,0 +1,608 @@
+/*
+ * Sun Public License Notice
+ *
+ * The contents of this file are subject to the Sun Public License
+ * Version 1.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ * http://www.sun.com/
+ *
+ * The Original Code is NetBeans. The Initial Developer of the Original
+ * Code is Sun Microsystems, Inc. Portions Copyright 1997-2002 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ */
+
+package org.netbeans;
+
+import java.util.*;
+import java.net.URL;
+import java.io.IOException;
+
+/**
+ * A class loader that has multiple parents and uses them for loading
+ * classes and resources. It can be used in tree hierarchy, where it
+ * can exploit its capability to not throw ClassNotFoundException when
+ * communicating with other ProxyClassLoader.
+ * It itself doesn't load classes or resources, but allows subclasses
+ * to add such functionality.
+ *
+ * @author Petr Nejedly, Jesse Glick
+ */
+public class ProxyClassLoader extends ClassLoader {
+ /** empty enumeration */
+ private static final Enumeration EMPTY = new ArrayEnumeration (new Object[0]);
+
+
+ // Map+ *
true
then resolve the class
+ * @return the resulting Class
object
+ * @exception ClassNotFoundException if the class could not be found
+ */
+ protected synchronized final Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ zombieCheck(name);
+ // XXX this section is a candidate for local optimization:
+ String filename = name.replace('.', '/').concat(".class"); // NOI18N
+ int idx = filename.lastIndexOf('/'); // NOI18N
+ if (idx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N
+ String pkg = filename.substring(0, idx + 1); // "org/netbeans/modules/foo/"
+ Class c = smartLoadClass(name, filename, pkg);
+ if(c == null) throw new ClassNotFoundException(name);
+ if (resolve) resolveClass(c);
+ return c;
+ }
+
+ /** This ClassLoader can't load anything itself. Subclasses
+ * may override this method to do some class loading themselves. The
+ * implementation should not throw any exception, just return
+ * null
if it can't load required class.
+ *
+ * @param name the name of the class
+ * @param fileName the expected filename of the classfile, like
+ * java/lang/Object.class
for java.lang.Object
+ * The ClassLoader implementation may or may not use it, depending
+ * whether it is usefull to it.
+ * @return the resulting Class
object or null
+ */
+ protected Class simpleFindClass(String name, String fileName) {
+ return null;
+ }
+
+
+ /**
+ * Finds the resource with the given name. The implementation of
+ * this method searches for resources in the following order:+ *
null
if
+ * the resource could not be found.
+ * @see #findResource(String)
+ */
+ public final URL getResource(final String name) {
+ zombieCheck(name);
+
+ final int slashIdx = name.lastIndexOf('/');
+ if (slashIdx == -1) return null; // won't load from the default package
+ final String pkg = name.substring(0, slashIdx + 1);
+
+ if (isSpecialResource(pkg)) {
+ // Disable domain cache for this one, do a simple check.
+ for (int i = 0; i < parents.length; i++) {
+ if (!shouldDelegateResource(pkg, parents[i])) continue;
+ URL u;
+ if (parents[i] instanceof ProxyClassLoader) {
+ u = ((ProxyClassLoader)parents[i]).findResource(name);
+ } else {
+ u = parents[i].getResource(name);
+ }
+ if (u != null) return u;
+ }
+ return findResource(name);
+ }
+
+ ClassLoader owner = (ClassLoader)domainsByPackage.get(pkg);
+
+ if (owner != null) { // known package
+ // Note that shouldDelegateResource should already be true for this!
+ if (owner instanceof ProxyClassLoader) {
+ return ((ProxyClassLoader)owner).findResource(name); // we have its parents, skip them
+ } else {
+ return owner.getResource(name); // know nothing about this loader and his structure
+ }
+ }
+
+ // virgin package
+ URL retVal = null;
+ for (int i = 0; i < parents.length; i++) {
+ owner = parents[i];
+ if (!shouldDelegateResource(pkg, owner)) continue;
+ if (owner instanceof ProxyClassLoader) {
+ retVal = ((ProxyClassLoader)owner).findResource(name); // skip parents (checked already)
+ } else {
+ retVal = owner.getResource(name); // know nothing about this loader and his structure
+ }
+ if (retVal != null) {
+ domainsByPackage.put(pkg, owner);
+ return retVal;
+ }
+ }
+
+ // try it ourself
+ retVal = findResource(name);
+ if (retVal != null) {
+ domainsByPackage.put(pkg, this);
+ }
+ return retVal;
+ }
+
+ /** This ClassLoader can't load anything itself. Subclasses
+ * may override this method to do some resource loading themselves.
+ *
+ * @param name the resource name
+ * @return a URL for reading the resource, or null
+ * if the resource could not be found.
+ */
+ protected URL findResource(String name) {
+ return null;
+ }
+
+ /**
+ * Finds all the resource with the given name. The implementation of
+ * this method uses the {@link #simpleFindResources(String)} method to find
+ * all the resources available from this classloader and adds all the
+ * resources from all the parents.
+ *
+ * @param name the resource name
+ * @return an Enumeration of URLs for the resources
+ * @throws IOException if I/O errors occur
+ */
+ protected final synchronized Enumeration findResources(String name) throws IOException {
+ zombieCheck(name);
+ final int slashIdx = name.lastIndexOf('/');
+ if (slashIdx == -1) return EMPTY; // won't load from the default package
+ final String pkg = name.substring(0, slashIdx + 1);
+
+ // Don't bother optimizing this call by domains.
+ // It is mostly used for resources for which isSpecialResource would be true anyway.
+ Enumeration[] es = new Enumeration[parents.length + 1];
+ for (int i = 0; i < parents.length; i++) {
+ if (!shouldDelegateResource(pkg, parents[i])) {
+ es[i] = EMPTY;
+ continue;
+ }
+ if (parents[i] instanceof ProxyClassLoader) {
+ es[i] = ((ProxyClassLoader)parents[i]).simpleFindResources(name);
+ } else {
+ es[i] = parents[i].getResources(name);
+ }
+ }
+ es[parents.length] = simpleFindResources(name);
+ // Should not be duplicates, assuming the parent loaders are properly distinct
+ // from one another and do not overlap in JAR usage, which they ought not.
+ // Anyway MetaInfServicesLookup, the most important client of this method, does
+ // its own duplicate filtering already.
+ return new AAEnum (es);
+ }
+
+ /** This ClassLoader can't load anything itself. Subclasses
+ * may override this method to do some resource loading themselves, this
+ * implementation simply delegates to findResources method of the superclass
+ * that should return empty Enumeration.
+ *
+ * @param name the resource name
+ * @return an Enumeration of URLs for the resources
+ * @throws IOException if I/O errors occur
+ */
+ protected Enumeration simpleFindResources(String name) throws IOException {
+ return super.findResources(name);
+ }
+
+
+ /**
+ * Returns a Package that has been defined by this class loader or any
+ * of its parents.
+ *
+ * @param name the package name
+ * @return the Package corresponding to the given name, or null if not found
+ */
+ protected Package getPackage(String name) {
+ zombieCheck(name);
+
+ int idx = name.lastIndexOf('.');
+ if (idx == -1) return null;
+ String spkg = name.substring(0, idx + 1).replace('.', '/');
+
+ synchronized (packages) {
+ Package pkg = (Package)packages.get(name);
+ if (pkg != null) return pkg;
+
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader par = parents[i];
+ if (par instanceof ProxyClassLoader && shouldDelegateResource(spkg, par)) {
+ pkg = ((ProxyClassLoader)par).getPackage(name);
+ if(pkg != null) break;
+ }
+ }
+ // do our own lookup
+ if (pkg == null) pkg = super.getPackage(name);
+ // cache results
+ if (pkg != null) packages.put(name, pkg);
+
+ return pkg;
+ }
+ }
+
+ /** This is here just for locking serialization purposes.
+ * Delegates to super.definePackage with proper locking.
+ */
+ protected Package definePackage(String name, String specTitle,
+ String specVersion, String specVendor, String implTitle,
+ String implVersion, String implVendor, URL sealBase )
+ throws IllegalArgumentException {
+ synchronized (packages) {
+ return super.definePackage (name, specTitle, specVersion, specVendor, implTitle,
+ implVersion, implVendor, sealBase);
+ }
+ }
+
+ /**
+ * Returns all of the Packages defined by this class loader and its parents.
+ *
+ * @return the array of Package
objects defined by this
+ * ClassLoader
+ */
+ protected synchronized Package[] getPackages() {
+ zombieCheck(null);
+ Map all = new HashMap(); // Maptrue
if this enumeration contains more elements;
+ * false
otherwise.
+ */
+ public boolean hasMoreElements() {
+ return (index < array.length);
+ }
+
+ /** Returns the next element of this enumeration.
+ * @return the next element of this enumeration.
+ * @exception NoSuchElementException if no more elements exist.
+ */
+ public Object nextElement() {
+ try {
+ return array[index++];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+ }
+
+ private static final class AAEnum implements Enumeration {
+ /** The array */
+ private Enumeration[] array;
+ /** Current index in the array */
+ private int index = 0;
+
+ /** Constructs a new ArrayEnumeration for specified array */
+ public AAEnum (Enumeration[] array) {
+ this.array = array;
+ }
+
+ /** Tests if this enumeration contains more elements.
+ * @return true
if this enumeration contains more elements;
+ * false
otherwise.
+ */
+ public boolean hasMoreElements() {
+ for (;;) {
+ if (index == array.length) {
+ return false;
+ }
+
+ if (array[index].hasMoreElements ()) {
+ return true;
+ }
+
+ index++;
+ }
+ }
+
+ /** Returns the next element of this enumeration.
+ * @return the next element of this enumeration.
+ * @exception NoSuchElementException if no more elements exist.
+ */
+ public Object nextElement() {
+ try {
+ return array[index].nextElement ();
+ } catch (NoSuchElementException ex) {
+ if (hasMoreElements ()) {
+ // try once more
+ return nextElement ();
+ }
+ throw ex;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+ }
+
+}
Index: nb_all/core/src/org/netbeans/core/Main.java
===================================================================
RCS file: /cvs/core/src/org/netbeans/core/Main.java,v
--- nb_all/core/src/org/netbeans/core/Main.java 29 Jul 2002 10:11:14 -0000 1.147
+++ nb_all/core/src/org/netbeans/core/Main.java 29 Jul 2002 19:26:35 -0000
@@ -121,7 +121,7 @@
/** Starts TopThreadGroup which properly overrides uncaughtException
* Further - new thread in the group execs main
*/
- public static void start(String[] argv) {
+ public static void main (String[] argv) {
TopThreadGroup tg = new TopThreadGroup ("IDE Main", argv); // NOI18N - programatic name
tg.start ();
}
@@ -356,7 +356,7 @@
/**
* @exception SecurityException if it is called multiple times
*/
- public static void main(String[] args) throws SecurityException {
+ static void start (String[] args) throws SecurityException {
long time = System.currentTimeMillis();
StartLog.logEnd ("Forwarding to topThreadGroup"); // NOI18N
Index: nb_all/core/src/org/netbeans/core/TopThreadGroup.java
===================================================================
RCS file: /cvs/core/src/org/netbeans/core/TopThreadGroup.java,v
--- nb_all/core/src/org/netbeans/core/TopThreadGroup.java 29 Jul 2002 10:11:14 -0000 1.16
+++ nb_all/core/src/org/netbeans/core/TopThreadGroup.java 29 Jul 2002 19:26:35 -0000
@@ -78,7 +78,7 @@
public void run() {
try {
- Main.main(args);
+ Main.start (args);
} catch (Throwable t) {
// XXX is this not handled by uncaughtException?
ErrorManager.getDefault().notify(t);
Index: nb_all/core/src/org/netbeans/core/modules/JarClassLoader.java
===================================================================
RCS file: nb_all/core/src/org/netbeans/core/modules/JarClassLoader.java
--- nb_all/core/src/org/netbeans/core/modules/JarClassLoader.java 29 Jul 2002 10:11:15 -0000 1.14
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,401 +0,0 @@
-/*
- * Sun Public License Notice
- *
- * The contents of this file are subject to the Sun Public License
- * Version 1.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://www.sun.com/
- *
- * The Original Code is NetBeans. The Initial Developer of the Original
- * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
- * Microsystems, Inc. All Rights Reserved.
- */
-
-package org.netbeans.core.modules;
-
-import java.net.URL;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.util.zip.ZipEntry;
-import java.io.*;
-import java.net.MalformedURLException;
-import java.security.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-import org.openide.ErrorManager;
-
-/**
- * A ProxyClassLoader capable of loading classes from a set of jar files
- * and local directories.
- *
- * @author Petr Nejedly
- */
-public class JarClassLoader extends ProxyClassLoader {
- private Source[] sources;
- /** temp copy JARs which ought to be deleted */
- private Set deadJars = null; // Set- *
true
then resolve the class
- * @return the resulting Class
object
- * @exception ClassNotFoundException if the class could not be found
- */
- protected synchronized final Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- zombieCheck(name);
- // XXX this section is a candidate for local optimization:
- String filename = name.replace('.', '/').concat(".class"); // NOI18N
- int idx = filename.lastIndexOf('/'); // NOI18N
- if (idx == -1) throw new ClassNotFoundException("Will not load classes from default package"); // NOI18N
- String pkg = filename.substring(0, idx + 1); // "org/netbeans/modules/foo/"
- Class c = smartLoadClass(name, filename, pkg);
- if(c == null) throw new ClassNotFoundException(name);
- if (resolve) resolveClass(c);
- return c;
- }
-
- /** This ClassLoader can't load anything itself. Subclasses
- * may override this method to do some class loading themselves. The
- * implementation should not throw any exception, just return
- * null
if it can't load required class.
- *
- * @param name the name of the class
- * @param fileName the expected filename of the classfile, like
- * java/lang/Object.class
for java.lang.Object
- * The ClassLoader implementation may or may not use it, depending
- * whether it is usefull to it.
- * @return the resulting Class
object or null
- */
- protected Class simpleFindClass(String name, String fileName) {
- return null;
- }
-
-
- /**
- * Finds the resource with the given name. The implementation of
- * this method searches for resources in the following order:- *
null
if
- * the resource could not be found.
- * @see #findResource(String)
- */
- public final URL getResource(final String name) {
- zombieCheck(name);
-
- final int slashIdx = name.lastIndexOf('/');
- if (slashIdx == -1) return null; // won't load from the default package
- final String pkg = name.substring(0, slashIdx + 1);
-
- if (isSpecialResource(pkg)) {
- // Disable domain cache for this one, do a simple check.
- for (int i = 0; i < parents.length; i++) {
- if (!shouldDelegateResource(pkg, parents[i])) continue;
- URL u;
- if (parents[i] instanceof ProxyClassLoader) {
- u = ((ProxyClassLoader)parents[i]).findResource(name);
- } else {
- u = parents[i].getResource(name);
- }
- if (u != null) return u;
- }
- return findResource(name);
- }
-
- ClassLoader owner = (ClassLoader)domainsByPackage.get(pkg);
-
- if (owner != null) { // known package
- // Note that shouldDelegateResource should already be true for this!
- if (owner instanceof ProxyClassLoader) {
- return ((ProxyClassLoader)owner).findResource(name); // we have its parents, skip them
- } else {
- return owner.getResource(name); // know nothing about this loader and his structure
- }
- }
-
- // virgin package
- URL retVal = null;
- for (int i = 0; i < parents.length; i++) {
- owner = parents[i];
- if (!shouldDelegateResource(pkg, owner)) continue;
- if (owner instanceof ProxyClassLoader) {
- retVal = ((ProxyClassLoader)owner).findResource(name); // skip parents (checked already)
- } else {
- retVal = owner.getResource(name); // know nothing about this loader and his structure
- }
- if (retVal != null) {
- domainsByPackage.put(pkg, owner);
- return retVal;
- }
- }
-
- // try it ourself
- retVal = findResource(name);
- if (retVal != null) {
- domainsByPackage.put(pkg, this);
- }
- return retVal;
- }
-
- /** This ClassLoader can't load anything itself. Subclasses
- * may override this method to do some resource loading themselves.
- *
- * @param name the resource name
- * @return a URL for reading the resource, or null
- * if the resource could not be found.
- */
- protected URL findResource(String name) {
- return null;
- }
-
- /**
- * Finds all the resource with the given name. The implementation of
- * this method uses the {@link #simpleFindResources(String)} method to find
- * all the resources available from this classloader and adds all the
- * resources from all the parents.
- *
- * @param name the resource name
- * @return an Enumeration of URLs for the resources
- * @throws IOException if I/O errors occur
- */
- protected final synchronized Enumeration findResources(String name) throws IOException {
- zombieCheck(name);
- final int slashIdx = name.lastIndexOf('/');
- if (slashIdx == -1) return EmptyEnumeration.EMPTY; // won't load from the default package
- final String pkg = name.substring(0, slashIdx + 1);
-
- // Don't bother optimizing this call by domains.
- // It is mostly used for resources for which isSpecialResource would be true anyway.
- Enumeration[] es = new Enumeration[parents.length + 1];
- for (int i = 0; i < parents.length; i++) {
- if (!shouldDelegateResource(pkg, parents[i])) {
- es[i] = EmptyEnumeration.EMPTY;
- continue;
- }
- if (parents[i] instanceof ProxyClassLoader) {
- es[i] = ((ProxyClassLoader)parents[i]).simpleFindResources(name);
- } else {
- es[i] = parents[i].getResources(name);
- }
- }
- es[parents.length] = simpleFindResources(name);
- // Should not be duplicates, assuming the parent loaders are properly distinct
- // from one another and do not overlap in JAR usage, which they ought not.
- // Anyway MetaInfServicesLookup, the most important client of this method, does
- // its own duplicate filtering already.
- return new SequenceEnumeration(new ArrayEnumeration(es));
- }
-
- /** This ClassLoader can't load anything itself. Subclasses
- * may override this method to do some resource loading themselves, this
- * implementation simply delegates to findResources method of the superclass
- * that should return empty Enumeration.
- *
- * @param name the resource name
- * @return an Enumeration of URLs for the resources
- * @throws IOException if I/O errors occur
- */
- protected Enumeration simpleFindResources(String name) throws IOException {
- return super.findResources(name);
- }
-
-
- /**
- * Returns a Package that has been defined by this class loader or any
- * of its parents.
- *
- * @param name the package name
- * @return the Package corresponding to the given name, or null if not found
- */
- protected Package getPackage(String name) {
- zombieCheck(name);
-
- int idx = name.lastIndexOf('.');
- if (idx == -1) return null;
- String spkg = name.substring(0, idx + 1).replace('.', '/');
-
- synchronized (packages) {
- Package pkg = (Package)packages.get(name);
- if (pkg != null) return pkg;
-
- for (int i = 0; i < parents.length; i++) {
- ClassLoader par = parents[i];
- if (par instanceof ProxyClassLoader && shouldDelegateResource(spkg, par)) {
- pkg = ((ProxyClassLoader)par).getPackage(name);
- if(pkg != null) break;
- }
- }
- // do our own lookup
- if (pkg == null) pkg = super.getPackage(name);
- // cache results
- if (pkg != null) packages.put(name, pkg);
-
- return pkg;
- }
- }
-
- /** This is here just for locking serialization purposes.
- * Delegates to super.definePackage with proper locking.
- */
- protected Package definePackage(String name, String specTitle,
- String specVersion, String specVendor, String implTitle,
- String implVersion, String implVendor, URL sealBase )
- throws IllegalArgumentException {
- synchronized (packages) {
- return super.definePackage (name, specTitle, specVersion, specVendor, implTitle,
- implVersion, implVendor, sealBase);
- }
- }
-
- /**
- * Returns all of the Packages defined by this class loader and its parents.
- *
- * @return the array of Package
objects defined by this
- * ClassLoader
- */
- protected synchronized Package[] getPackages() {
- zombieCheck(null);
- Map all = new HashMap(); // MapaddCompilerListener
and removeCompilerListener
+ made not-final.
+ org.openide.awt.MenuBar
@@ -3925,6 +3959,8 @@
In most cases, when it is desirable from an architectural standpoint
to change an API in an incompatible way, the standard Java mechanism
of @deprecated
tags in Javadoc suffices as a compromise:
@@ -3987,6 +4023,17 @@
into an IDE installation that has had its
lib/patches/openide-compat.jar removed, to ensure that
they are not depending on the deprecated APIs.
+ In releases after 3.4 (expected 4.0), the system used is slightly + different, though the effect is similar. + lib/openide-compat.jar is now the compatibility JAR + location. It contains fake superclasses for some classes; the fake + superclasses will be inserted into the inheritance tree at runtime and + include methods and interfaces which are not available in source code. +