diff options
-rw-r--r-- | Readme.html | 14 | ||||
-rw-r--r-- | src/main/javassist/ClassPool.java | 14 | ||||
-rw-r--r-- | src/main/javassist/CtClass.java | 16 | ||||
-rw-r--r-- | src/main/javassist/CtClassType.java | 21 | ||||
-rw-r--r-- | src/main/javassist/CtNewNestedClass.java | 31 | ||||
-rw-r--r-- | src/main/javassist/bytecode/InnerClassesAttribute.java | 83 |
6 files changed, 171 insertions, 8 deletions
diff --git a/Readme.html b/Readme.html index 3c3129c7..7c0a4cfb 100644 --- a/Readme.html +++ b/Readme.html @@ -255,22 +255,19 @@ see javassist.Dump. <h2>Changes</h2> -<p>- version 3.0 +<p>- version 3.0 RC1 <ul> - <li>ClassPool has been largely modified. - <ul><li>write(), writeFile(), .. in ClassPool were moved to CtClass. - <li>The host of javassist.Translator was changed from ClassPool - to javassist.Loader. - </ul> - - <li>javassist.bytecode.annotation has been added. <li>The ClassPool framework has been redesigned. <ul> <li>writeFile(), write(), ... in ClassPool have been moved to CtClass. <li>The design of javassist.Translator has been changed. </ul> + <li>javassist.bytecode.annotation has been added for meta tags. + <li>CtClass.makeNestedClass() has been added. + <li>The methods declared in javassist.bytecode.InnerClassesAttribute + have been renamed a bit. <li>Now local variables were made available in the source text passed to CtBehavior.insertBefore(), MethodCall.replace(), etc. <li>CtClass.main(), which prints the version number, has been added. @@ -279,6 +276,7 @@ see javassist.Dump. <li>javassist.bytecode.LocalVariableAttribute has been added. <li>CtClass.getURL() and javassist.ClassPath.find() has been added. <li>CtBehavior.insertAt() has been added. + <li>CtClass.detach() has been added. </ul> <p>- version 2.6 in August, 2003. diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java index 8067940e..58a68f27 100644 --- a/src/main/javassist/ClassPool.java +++ b/src/main/javassist/ClassPool.java @@ -578,6 +578,20 @@ public class ClassPool { } /** + * Creates a new nested class. + * This method is called by CtClassType.makeNestedClass(). + * + * @param classname a fully-qualified class name. + * @return the nested class. + */ + synchronized CtClass makeNestedClass(String classname) { + checkNotFrozen(classname); + CtClass clazz = new CtNewNestedClass(classname, this, false, null); + cacheCtClass(classname, clazz); + return clazz; + } + + /** * Creates a new public interface. * If there already exists a class/interface with the same name, * the new interface overwrites that previous one. diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java index 68f63031..98775f47 100644 --- a/src/main/javassist/CtClass.java +++ b/src/main/javassist/CtClass.java @@ -498,6 +498,20 @@ public abstract class CtClass { } /** + * Makes a new nested class. Making a nested class modifies the + * data in this <code>CtClass</code>. + * + * <p>The current implementation only supports a static nested class. + * <code>isStatic</code> must be true. + * + * @param name the simple name of the nested class. + * @param isStatic true if the nested class is static. + */ + public CtClass makeNestedClass(String name, boolean isStatic) { + throw new RuntimeException(getName() + " is not a class"); + } + + /** * Returns an array containing <code>CtField</code> objects * representing all the public fields of the class. * That array includes public fields inherited from the @@ -884,6 +898,8 @@ public abstract class CtClass { /** * Removes this <code>CtClass</code> from the <code>ClassPool</code>. + * After this method is called, any method cannot be called on the + * removed <code>CtClass</code> object. * * <p>If needed, * the <code>ClassPool</code> will read the class file again diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java index de88c855..4834ae8a 100644 --- a/src/main/javassist/CtClassType.java +++ b/src/main/javassist/CtClassType.java @@ -343,6 +343,27 @@ class CtClassType extends CtClass { return null; } + public CtClass makeNestedClass(String name, boolean isStatic) { + if (!isStatic) + throw new RuntimeException( + "sorry, only nested static class is supported"); + + checkModify(); + CtClass c = classPool.makeNestedClass(getName() + "$" + name); + ClassFile cf = getClassFile2(); + InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute( + InnerClassesAttribute.tag); + if (ica == null) { + ica = new InnerClassesAttribute(cf.getConstPool()); + cf.addAttribute(ica); + } + + ica.append(c.getName(), this.getName(), name, AccessFlag.STATIC); + ClassFile cf2 = c.getClassFile2(); + cf2.addAttribute(ica.copy(cf2.getConstPool(), null)); + return c; + } + public CtField[] getFields() { ArrayList alist = new ArrayList(); getFields(alist, this); diff --git a/src/main/javassist/CtNewNestedClass.java b/src/main/javassist/CtNewNestedClass.java new file mode 100644 index 00000000..d79485cd --- /dev/null +++ b/src/main/javassist/CtNewNestedClass.java @@ -0,0 +1,31 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist; + +/** + * A newly created nested class. + */ +class CtNewNestedClass extends CtNewClass { + CtNewNestedClass(String realName, ClassPool cp, boolean isInterface, + CtClass superclass) { + super(realName, cp, isInterface, superclass); + } + + public void setModifiers(int mod) { + super.setModifiers(Modifier.clear(mod, + Modifier.STATIC | Modifier.PRIVATE)); + } +} diff --git a/src/main/javassist/bytecode/InnerClassesAttribute.java b/src/main/javassist/bytecode/InnerClassesAttribute.java index 400a53ca..f071f6d1 100644 --- a/src/main/javassist/bytecode/InnerClassesAttribute.java +++ b/src/main/javassist/bytecode/InnerClassesAttribute.java @@ -39,6 +39,16 @@ public class InnerClassesAttribute extends AttributeInfo { } /** + * Constructs an empty InnerClasses attribute. + * + * @see #append(String, String, String, int) + */ + public InnerClassesAttribute(ConstPool cp) { + super(cp, tag, new byte[2]); + ByteArray.write16bit(0, get(), 0); + } + + /** * Returns <code>number_of_classes</code>. */ public int tableLength() { return ByteArray.readU16bit(get(), 0); } @@ -65,6 +75,14 @@ public class InnerClassesAttribute extends AttributeInfo { } /** + * Sets <code>classes[nth].inner_class_info_index</code> to + * the given index. + */ + public void setInnerClassIndex(int nth, int index) { + ByteArray.write16bit(index, get(), nth * 8 + 2); + } + + /** * Returns <code>classes[nth].outer_class_info_index</code>. */ public int outerClassIndex(int nth) { @@ -86,6 +104,14 @@ public class InnerClassesAttribute extends AttributeInfo { } /** + * Sets <code>classes[nth].outer_class_info_index</code> to + * the given index. + */ + public void setOuterClassIndex(int nth, int index) { + ByteArray.write16bit(index, get(), nth * 8 + 4); + } + + /** * Returns <code>classes[nth].inner_name_index</code>. */ public int innerNameIndex(int nth) { @@ -107,6 +133,14 @@ public class InnerClassesAttribute extends AttributeInfo { } /** + * Sets <code>classes[nth].inner_name_index</code> to + * the given index. + */ + public void setInnerNameIndex(int nth, int index) { + ByteArray.write16bit(index, get(), nth * 8 + 6); + } + + /** * Returns <code>classes[nth].inner_class_access_flags</code>. */ public int accessFlags(int nth) { @@ -114,6 +148,55 @@ public class InnerClassesAttribute extends AttributeInfo { } /** + * Sets <code>classes[nth].inner_class_access_flags</code> to + * the given index. + */ + public void setAccessFlags(int nth, int flags) { + ByteArray.write16bit(flags, get(), nth * 8 + 8); + } + + /** + * Appends a new entry. + * + * @param inner <code>inner_class_info_index</code> + * @param outer <code>outer_class_info_index</code> + * @param name <code>inner_name_index</code> + * @param flags <code>inner_class_access_flags</code> + */ + public void append(String inner, String outer, String name, int flags) { + int i = constPool.addClassInfo(inner); + int o = constPool.addClassInfo(outer); + int n = constPool.addUtf8Info(name); + append(i, o, n, flags); + } + + /** + * Appends a new entry. + * + * @param inner <code>inner_class_info_index</code> + * @param outer <code>outer_class_info_index</code> + * @param name <code>inner_name_index</code> + * @param flags <code>inner_class_access_flags</code> + */ + public void append(int inner, int outer, int name, int flags) { + byte[] data = get(); + int len = data.length; + byte[] newData = new byte[len + 8]; + for (int i = 2; i < len; ++i) + newData[i] = data[i]; + + int n = ByteArray.readU16bit(data, 0); + ByteArray.write16bit(n + 1, newData, 0); + + ByteArray.write16bit(inner, newData, len); + ByteArray.write16bit(outer, newData, len + 2); + ByteArray.write16bit(name, newData, len + 4); + ByteArray.write16bit(flags, newData, len + 6); + + set(newData); + } + + /** * Makes a copy. Class names are replaced according to the * given <code>Map</code> object. * |