Index: openide/build.xml =================================================================== RCS file: /cvs/openide/build.xml,v retrieving revision 1.110 diff -c -r1.110 build.xml *** openide/build.xml 15 Aug 2002 22:15:17 -0000 1.110 --- openide/build.xml 29 Aug 2002 12:21:45 -0000 *************** *** 92,101 **** - - --- 92,105 ---- + + + + + + *************** *** 132,138 **** ! --- 136,144 ---- ! ! ! Index: openide/compat/src/org/openide/filesystems/$AbstractFileSystem$Patch$.java =================================================================== RCS file: openide/compat/src/org/openide/filesystems/$AbstractFileSystem$Patch$.java diff -N openide/compat/src/org/openide/filesystems/$AbstractFileSystem$Patch$.java *** openide/compat/src/org/openide/filesystems/$AbstractFileSystem$Patch$.java 20 Aug 2002 19:20:56 -0000 1.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 *************** *** 1,31 **** - /* - * 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.openide.filesystems; - - /** A fake class that holds methods that for compatibility reasons - * should be public even in the definition are not. - * - * @author Jaroslav Tulach - */ - public abstract class $AbstractFileSystem$Patch$ extends FileSystem { - - private static final long serialVersionUID = 2345763982756L; - - // implemented in AbstractFileSystem - abstract AbstractFileObject refreshRootImpl (); - - protected final AbstractFileObject refreshRoot () { - return refreshRootImpl (); - } - } --- 0 ---- Index: openide/compat/src/org/openide/util/actions/$SystemAction$Patch$.java =================================================================== RCS file: openide/compat/src/org/openide/util/actions/$SystemAction$Patch$.java diff -N openide/compat/src/org/openide/util/actions/$SystemAction$Patch$.java *** openide/compat/src/org/openide/util/actions/$SystemAction$Patch$.java 14 Aug 2002 14:16:09 -0000 1.2 --- /dev/null 1 Jan 1970 00:00:00 -0000 *************** *** 1,50 **** - /* - * 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.openide.util.actions; - - import javax.swing.Icon; - import javax.swing.ImageIcon; - import org.openide.util.Utilities; - - /** A fake class that holds methods that for compatibility reasons - * should be public even in the definition are not. - * - * @author Jaroslav Tulach - */ - public abstract class $SystemAction$Patch$ extends org.openide.util.SharedClassObject { - /** Constructor that delegates. - */ - public $SystemAction$Patch$ () { - } - - // Will be define by SystemAction - public abstract void setIcon (Icon icon); - public abstract Icon getIcon (boolean flag); - - // used to be define - public final void setIcon (ImageIcon icon) { - setIcon ((Icon) icon); - } - public final ImageIcon getIcon () { - Icon i = getIcon (false); - if (i instanceof ImageIcon) { - return ((ImageIcon) i); - } else { - // [PENDING] could try to translate Icon -> ImageIcon somehow, - // but I have no idea how to do this (paint it, take Component - // graphics, load the image data somehow??) - return new ImageIcon(Utilities.loadImage("org/openide/resources/actions/empty.gif")); // NOI18N - } - } - } --- 0 ---- Index: openide/src/org/openide/filesystems/AbstractFileSystem.java =================================================================== RCS file: /cvs/openide/src/org/openide/filesystems/AbstractFileSystem.java,v retrieving revision 1.47 diff -c -r1.47 AbstractFileSystem.java *** openide/src/org/openide/filesystems/AbstractFileSystem.java 14 Aug 2002 14:16:17 -0000 1.47 --- openide/src/org/openide/filesystems/AbstractFileSystem.java 29 Aug 2002 12:21:46 -0000 *************** *** 248,254 **** root = createFileObject (null, ""); // NOI18N return root; } ! /** Instruct the filesystem * that the root should change. * A fresh root is created. Subclasses that support root changes should use this. --- 248,254 ---- root = createFileObject (null, ""); // NOI18N return root; } ! /** Instruct the filesystem * that the root should change. * A fresh root is created. Subclasses that support root changes should use this. *************** *** 256,261 **** --- 256,268 ---- * @return the new root */ protected final FileObject refreshRoot () { + return refreshRootImpl (); + } + + /** @deprecated Just for backward compatibility, renamed during runtime to refreshRoot + * and made available publicly + */ + private AbstractFileObject r3fr3shRoot () { return refreshRootImpl (); } Index: openide/src/org/openide/util/actions/SystemAction.java =================================================================== RCS file: /cvs/openide/src/org/openide/util/actions/SystemAction.java,v retrieving revision 1.59 diff -c -r1.59 SystemAction.java *** openide/src/org/openide/util/actions/SystemAction.java 14 Aug 2002 14:16:28 -0000 1.59 --- openide/src/org/openide/util/actions/SystemAction.java 29 Aug 2002 12:21:46 -0000 *************** *** 239,244 **** --- 239,269 ---- return img; } } + + // + // Old deprecated methods - compatibility stuff - will be made public and renamed + // by NbEnhanceClass task + // + + private void s3tIcon (ImageIcon icon) { + setIcon ((Icon) icon); + } + + private ImageIcon g3tIcon () { + Icon i = getIcon (false); + if (i instanceof ImageIcon) { + return ((ImageIcon) i); + } else { + // [PENDING] could try to translate Icon -> ImageIcon somehow, + // but I have no idea how to do this (paint it, take Component + // graphics, load the image data somehow??) + return new ImageIcon(Utilities.loadImage("org/openide/resources/actions/empty.gif")); // NOI18N + } + } + + // + // End of compatibility stuff + // /** Specify the proper resource name for the action's icon. * May be overridden by subclasses; the default is to have no icon. Index: nbbuild/antsrc/org/netbeans/nbbuild/NbEnhanceClass.java =================================================================== RCS file: /cvs/nbbuild/antsrc/org/netbeans/nbbuild/NbEnhanceClass.java,v retrieving revision 1.2 diff -c -r1.2 NbEnhanceClass.java *** nbbuild/antsrc/org/netbeans/nbbuild/NbEnhanceClass.java 14 Aug 2002 14:16:29 -0000 1.2 --- nbbuild/antsrc/org/netbeans/nbbuild/NbEnhanceClass.java 29 Aug 2002 12:21:47 -0000 *************** *** 86,95 **** --- 86,100 ---- public static final class Member extends Object { String name; + String rename; public void setName (String s) { name = s; } + + public void setRename (String s) { + rename = s; + } } } private ArrayList patches = new ArrayList (); // List *************** *** 129,135 **** java.lang.reflect.Method m; try { Class c = cl.loadClass (patchClass); ! m = c.getMethod(enhanceMethod, new Class[] { byte[].class, String.class, String[].class }); if (m.getReturnType() != byte[].class) { throw new BuildException ("Method does not return byte[]: " + m); } --- 134,140 ---- java.lang.reflect.Method m; try { Class c = cl.loadClass (patchClass); ! m = c.getMethod(enhanceMethod, new Class[] { byte[].class, java.util.Map.class }); if (m.getReturnType() != byte[].class) { throw new BuildException ("Method does not return byte[]: " + m); } *************** *** 174,195 **** throw new BuildException ("Cannot read file " + f, ex); } ! String[] members; if (p.members != null) { ! members = new String[p.members.size ()]; Iterator myIt = p.members.iterator(); int i = 0; while (myIt.hasNext ()) { ! members[i++] = ((Patch.Member)myIt.next ()).name; } - } else { - members = null; } byte[] out; try { ! out = (byte[])m.invoke (null, new Object[] { arr, p.nbSuperClass, members }); if (out == null) { // no patching needed continue; --- 179,219 ---- throw new BuildException ("Cannot read file " + f, ex); } ! ArrayList members = null; ! ArrayList rename = null; if (p.members != null) { ! members = new ArrayList (); Iterator myIt = p.members.iterator(); int i = 0; while (myIt.hasNext ()) { ! Patch.Member mem = (Patch.Member)myIt.next (); ! members.add (mem.name); ! ! if (mem.rename != null) { ! if (rename == null) { ! rename = new ArrayList (); ! } ! rename.add (mem.name); ! rename.add (mem.rename); ! } } } byte[] out; try { ! java.util.Map args = new java.util.HashMap (); ! if (p.nbSuperClass != null) { ! args.put ("netbeans.superclass", p.nbSuperClass); ! } ! if (members != null) { ! args.put ("netbeans.public", members.toArray (new String[0])); ! } ! if (rename != null) { ! args.put ("netbeans.rename", rename.toArray (new String[0])); ! } ! ! out = (byte[])m.invoke (null, new Object[] { arr, args }); if (out == null) { // no patching needed continue; Index: core/src/org/netbeans/PatchByteCode.java =================================================================== RCS file: /cvs/core/src/org/netbeans/PatchByteCode.java,v retrieving revision 1.8 diff -c -r1.8 PatchByteCode.java *** core/src/org/netbeans/PatchByteCode.java 14 Aug 2002 14:15:51 -0000 1.8 --- core/src/org/netbeans/PatchByteCode.java 29 Aug 2002 12:21:47 -0000 *************** *** 64,69 **** --- 64,78 ---- throw new IllegalStateException (ex.getMessage()); } } + private static final String ATTR_NAME = "org.netbeans.name"; // NOI18N + private static final byte[] BYTE_NAME; + static { + try { + BYTE_NAME = ATTR_NAME.getBytes("utf-8"); // NOI18N + } catch (java.io.UnsupportedEncodingException ex) { + throw new IllegalStateException (ex.getMessage()); + } + } private static final String ATTR_INIT = ""; // NOI18N private static final byte[] BYTE_INIT; *************** *** 108,113 **** --- 117,124 ---- private int initNameTypeIndex = -1; /** position of the method */ private int initAttr = -1; + /** index of string that identifies the rename of a member */ + private int renameNameIndex = -1; /** map that maps names of fields to their position in constant pool (String, int[1]) */ private HashMap nameIndexes; *************** *** 125,165 **** scan (); } - - /** Generates patch attribute into the classfile to - * allow method 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) { - return enhance (arr, superClass, null); - } - /** Generates patch attribute into the classfile to * allow method 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 ! * @param methods array of names of methods to make public * @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, String[] methods) { if (isPatched (arr)) { // already patched return null; } HashMap m; ! if (methods != null) { m = new HashMap (); ! for (int i = 0; i < methods.length; i++) { ! m.put (methods[i], new int[1]); } } else { m = null; --- 136,175 ---- scan (); } /** Generates patch attribute into the classfile to * allow method patch to modify the superclass of this * class. * * @param arr the bytecode to change ! * @param args map with arguments. * @return new version of the bytecode if changed, otherwise null to signal that * no change has been made */ ! public static byte[] enhance (byte[] arr, java.util.Map args) { if (isPatched (arr)) { // already patched return null; } + String superClass = (String)args.get ("netbeans.superclass"); + String[] methods = (String[])args.get ("netbeans.public"); + String[] rename = (String[])args.get ("netbeans.rename"); + + HashMap m; ! if (methods != null || rename != null) { m = new HashMap (); ! ! if (methods != null) { ! for (int i = 0; i < methods.length; i++) { ! m.put (methods[i], new int[1]); ! } ! } ! ! if (rename != null) { ! for (int i = 0; i < rename.length; i++) { ! m.put (rename[i], new int[1]); ! } } } else { m = null; *************** *** 191,196 **** --- 201,212 ---- } } + if (rename != null) { + for (int i = 0; i < rename.length; i += 2) { + patched |= pc.renameMember(rename[i], rename[i + 1]); + } + } + if (patched) { byte[] patch = { 'n', 'b' // identification at the end of class file *************** *** 245,253 **** } ! if (pc.memberNameIndex > 0) { // change access rights of fields ! pc.applyMemberAccessChanges (); } return pc.getClassFile (); --- 261,269 ---- } ! if (pc.memberNameIndex > 0 || pc.renameNameIndex > 0) { // change access rights of fields ! pc.applyMemberAccessAndNameChanges (); } return pc.getClassFile (); *************** *** 457,468 **** return modified; } /** Checks all members of the class to find out whether they need patching * of access rights. If so, patches them. */ ! private void applyMemberAccessChanges () { ! int[] result = new int[1]; int pos = cpEnd; --- 473,574 ---- return modified; } + /** Marks a field or method as one that should be renamed. + * @param name name of the member + * @param rename new name of the member + * @return true if really changed, false if it already was renamed + */ + private boolean renameMember (String name, String rename) { + int constantPoolIndex = ((int[])nameIndexes.get (name))[0]; + int newPoolIndex; + { + int[] arr = (int[])nameIndexes.get (rename); + if (arr != null && arr[0] > 0) { + newPoolIndex = arr[0]; + } else { + newPoolIndex = addConstant (rename); + nameIndexes.put (rename, new int[] { newPoolIndex }); + } + } + int patchCount = 0; + boolean modified = false; + + // make sure ATTR_MEMBER is in constant pool + if (renameNameIndex == -1) { + renameNameIndex = addConstant (ATTR_NAME); + } + + int pos = cpEnd; + + pos += 6; + // now add interfaces + pos += 2 * readU2 (pos); + // to add also the integer with interfaces + pos += 2; + + for (int fieldsAndMethods = 0; fieldsAndMethods < 2; fieldsAndMethods++) { + // fields and then methods + int fieldsOrMethods = readU2 (pos); + pos += 2; + + while (fieldsOrMethods-- > 0) { + // check the name + int nameIndex = readU2 (pos + 2); + if (nameIndex == constantPoolIndex) { + // check whether the rename attribute is not there yet + int[] attributes = { -1, -1 }; + + memberSize (pos, attributes); + if (attributes[1] == -1) { + // let's patch attribute is not there yet + + // increment the attributes count + int cnt = readU2 (pos + 6) + 1; + + // + byte[] res = new byte[arr.length + 2 + 6]; + + // copy the array before + System.arraycopy(arr, 0, res, 0, pos + 6); + // write the new count of attributes + writeU2 (res, pos + 6, cnt); + + // write the attribute itself + writeU2 (res, pos + 8, renameNameIndex); // name of attribute + writeU4 (res, pos + 10, 2); // length + writeU2 (res, pos + 14, newPoolIndex); // index to the new name + + // copy the rest + System.arraycopy(arr, pos + 8, res, pos + 8 + 6 + 2, arr.length - pos - 8); + + atEnd += 2 + 6; + atCount += 2 + 6; + + + arr = res; + + modified = true; + } + + patchCount++; + } + + pos += memberSize (pos, null); + } + } + + if (patchCount == 0) { + throw new IllegalArgumentException ("Member " + name + " not found!"); + } + + return modified; + } /** Checks all members of the class to find out whether they need patching * of access rights. If so, patches them. */ ! private void applyMemberAccessAndNameChanges () { ! int[] result = new int[2]; int pos = cpEnd; *************** *** 479,484 **** --- 585,591 ---- while (fieldsOrMethods-- > 0) { result[0] = -1; + result[1] = -1; int size = memberSize(pos, result); if (result[0] != -1) { // we will do patching *************** *** 492,497 **** --- 599,616 ---- writeU2 (arr, pos, access); } + if (result[1] != -1) { + // we will do patching + + if (readU4 (result[1] + 2) != 2) { + throw new IllegalArgumentException ("Size of a attribute " + ATTR_NAME + " should be 2"); // NOI18N + } + + // alternate name of the member + int newName = readU2 (result[1] + 6); + writeU2 (arr, pos + 2, newName); + } + pos += size; } } *************** *** 588,594 **** // count of items in Attributes is here ! int[] memberAccess = { -1 }; atCount = pos; int attrs = readU2 (pos); --- 707,713 ---- // count of items in Attributes is here ! int[] memberAccess = { -1, -1 }; atCount = pos; int attrs = readU2 (pos); *************** *** 719,724 **** --- 838,851 ---- memberNameIndex = cnt[0]; } + if (compareUtfEntry (BYTE_NAME, pos)) { + // we have found the attribute + if (renameNameIndex > 0 && renameNameIndex != cnt[0]) { + throw new IllegalStateException (ATTR_NAME + " registered for the second time!"); // NOI18N + } + + renameNameIndex = cnt[0]; + } if (nameIndexes != null) { // check the name in the table *************** *** 742,755 **** } } ! private int memberSize (int pos, int[] containsPatchAttribute) { int s = 8; int name = readU2 (pos + 2); int cnt = readU2 (pos + 6); while (cnt-- > 0) { ! s += attributeSize (pos + s, containsPatchAttribute); } return s; } --- 869,882 ---- } } ! private int memberSize (int pos, int[] containsPatchAttributeAndRename) { int s = 8; int name = readU2 (pos + 2); int cnt = readU2 (pos + 6); while (cnt-- > 0) { ! s += attributeSize (pos + s, containsPatchAttributeAndRename); } return s; } *************** *** 757,763 **** /** Into the containsPatchAttribute (if not null) it adds the * index of structure of attribute ATTR_MEMBER. */ ! private int attributeSize (int pos, int[] containsPatchAttribute) { // index to the name attr int name = readU2 (pos); --- 884,890 ---- /** Into the containsPatchAttribute (if not null) it adds the * index of structure of attribute ATTR_MEMBER. */ ! private int attributeSize (int pos, int[] containsPatchAttributeAndRename) { // index to the name attr int name = readU2 (pos); *************** *** 770,780 **** superClassNameAttr = pos; } ! if (name == memberNameIndex && containsPatchAttribute != null) { ! if (containsPatchAttribute[0] != -1) { throw new IllegalStateException ("Second attribute " + ATTR_MEMBER); // NOI18N } ! containsPatchAttribute[0] = pos; } int len = readU4 (pos + 2); --- 897,914 ---- superClassNameAttr = pos; } ! if (name == memberNameIndex && containsPatchAttributeAndRename != null) { ! if (containsPatchAttributeAndRename[0] != -1) { throw new IllegalStateException ("Second attribute " + ATTR_MEMBER); // NOI18N } ! containsPatchAttributeAndRename[0] = pos; ! } ! ! if (name == renameNameIndex && containsPatchAttributeAndRename != null) { ! if (containsPatchAttributeAndRename[1] != -1) { ! throw new IllegalStateException ("Second attribute " + ATTR_NAME); // NOI18N ! } ! containsPatchAttributeAndRename[1] = pos; } int len = readU4 (pos + 2); Index: core/test/unit/src/org/netbeans/PatchByteCodeTest.java =================================================================== RCS file: /cvs/core/test/unit/src/org/netbeans/PatchByteCodeTest.java,v retrieving revision 1.6 diff -c -r1.6 PatchByteCodeTest.java *** core/test/unit/src/org/netbeans/PatchByteCodeTest.java 14 Aug 2002 14:15:59 -0000 1.6 --- core/test/unit/src/org/netbeans/PatchByteCodeTest.java 29 Aug 2002 12:21:47 -0000 *************** *** 18,23 **** --- 18,24 ---- import org.netbeans.junit.*; import java.io.InputStream; import java.lang.reflect.*; + import java.util.HashMap; /** Test patching of openide.jar byte code for compatibility. * @author Jaroslav Tulach *************** *** 58,65 **** int l = is.read (arr); assertEquals ("Read exactly as much as expected", l, arr.length); ! ! byte[] res = PatchByteCode.enhance(arr, null, new String[] { "addCompilerListener", "removeCompilerListener" } ); PatchClassLoader loader = new PatchClassLoader ("org.openide.compiler.CompilerGroup", res, ClassLoader.getSystemClassLoader()); Class c = loader.loadClass ("org.openide.compiler.CompilerGroup"); --- 59,68 ---- int l = is.read (arr); assertEquals ("Read exactly as much as expected", l, arr.length); ! ! HashMap args = new HashMap (); ! args.put ("netbeans.public", new String[] { "addCompilerListener", "removeCompilerListener" } ); ! byte[] res = PatchByteCode.enhance(arr, args); PatchClassLoader loader = new PatchClassLoader ("org.openide.compiler.CompilerGroup", res, ClassLoader.getSystemClassLoader()); Class c = loader.loadClass ("org.openide.compiler.CompilerGroup"); *************** *** 91,97 **** ! byte[] res = PatchByteCode.enhance(arr, null, new String[] { "member", "field", "method", "staticmethod" } ); PatchClassLoader loader = new PatchClassLoader (Sample.class.getName (), res, ClassLoader.getSystemClassLoader()); Class c = loader.loadClass (Sample.class.getName ()); --- 94,102 ---- ! HashMap args = new HashMap (); ! args.put ("netbeans.public", new String[] { "member", "field", "method", "staticmethod" } ); ! byte[] res = PatchByteCode.enhance(arr, args); PatchClassLoader loader = new PatchClassLoader (Sample.class.getName (), res, ClassLoader.getSystemClassLoader()); Class c = loader.loadClass (Sample.class.getName ()); *************** *** 134,140 **** assertTrue ("Is static", !Modifier.isStatic (f.getModifiers ())); } ! private Class checkPatching ( String className, String resource, String superclass --- 139,173 ---- assertTrue ("Is static", !Modifier.isStatic (f.getModifiers ())); } ! ! public void testRenameOfAMember () throws Exception { ! InputStream is = getClass ().getResourceAsStream ("Sample.class"); ! assertNotNull ("Class has not been found", is); ! ! byte[] arr = new byte[is.available ()]; ! int l = is.read (arr); ! assertEquals ("Read exactly as much as expected", l, arr.length); ! ! ! ! HashMap args = new HashMap (); ! args.put ("netbeans.rename", new String[] { "staticmethod", "StaticMethod" } ); ! byte[] res = PatchByteCode.enhance(arr, args); ! ! PatchClassLoader loader = new PatchClassLoader (Sample.class.getName (), res, ClassLoader.getSystemClassLoader()); ! ! Class c = loader.loadClass (Sample.class.getName ()); ! ! try { ! c.getDeclaredMethod("staticmethod", new Class[] { }); ! fail ("The old method is still present"); ! } catch (NoSuchMethodException ex) { ! // ok, should not be there ! } ! ! java.lang.reflect.Method m = c.getDeclaredMethod("StaticMethod", new Class[] { }); ! assertNotNull ("Renamed method found", m); ! } private Class checkPatching ( String className, String resource, String superclass *************** *** 150,156 **** int l = is.read (arr); assertEquals ("Read exactly as much as expected", l, arr.length); ! byte[] res = PatchByteCode.enhance(arr, superclass.replace ('.', '/')); PatchClassLoader loader = new PatchClassLoader (className, res); Class c = loader.loadClass (className); --- 183,191 ---- int l = is.read (arr); assertEquals ("Read exactly as much as expected", l, arr.length); ! HashMap args = new HashMap (); ! args.put ("netbeans.superclass", superclass.replace ('.', '/')); ! byte[] res = PatchByteCode.enhance(arr, args); PatchClassLoader loader = new PatchClassLoader (className, res); Class c = loader.loadClass (className);