git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@210 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
@@ -282,6 +282,13 @@ see javassist.Dump. | |||
<h2>Changes</h2> | |||
<p>- version 3.1 | |||
<ul> | |||
<li>getEnclosingClass() in javassist.CtClass was renamed | |||
to getEnclosingMethod(). | |||
</ul> | |||
<p>- version 3.1 RC2 in September 7, 2005 | |||
<ul> |
@@ -582,7 +582,7 @@ public class ClassPool { | |||
} | |||
/** | |||
* Creates a new nested class. | |||
* Creates a new public nested class. | |||
* This method is called by CtClassType.makeNestedClass(). | |||
* | |||
* @param classname a fully-qualified class name. |
@@ -408,8 +408,9 @@ public abstract class CtBehavior extends CtMember { | |||
* a constructor in the super class or this class is called. | |||
* Therefore, the inserted bytecode is subject to constraints described | |||
* in Section 4.8.2 of The Java Virtual Machine Specification (2nd ed). | |||
* For example, it cannot access instance fields or methods | |||
* although it can access static fields and methods. | |||
* For example, it cannot access instance fields or methods although | |||
* it may assign a value to an instance field directly declared in this | |||
* class. Accessing static fields and methods is allowed. | |||
* Use <code>insertBeforeBody()</code> in <code>CtConstructor</code>. | |||
* | |||
* @param src the source code representing the inserted bytecode. |
@@ -551,18 +551,20 @@ public abstract class CtClass { | |||
} | |||
/** | |||
* Returns the immediately enclosing class of this class. | |||
* Returns the immediately enclosing method of this class. | |||
* This method works only with JDK 1.5 or later. | |||
* | |||
* @return null if this class is a top-level class. | |||
* @return null if this class is not a local class or an anonymous | |||
* class. | |||
*/ | |||
public CtClass getEnclosingClass() throws NotFoundException { | |||
public CtMethod getEnclosingMethod() throws NotFoundException { | |||
return null; | |||
} | |||
/** | |||
* Makes a new nested class. Making a nested class modifies the | |||
* data in this <code>CtClass</code>. | |||
* Makes a new public nested class. If this method is called, | |||
* the <code>CtClass</code>, which encloses the nested class, is modified | |||
* since a class file includes a list of inner classes. | |||
* | |||
* <p>The current implementation only supports a static nested class. | |||
* <code>isStatic</code> must be true. |
@@ -488,23 +488,30 @@ class CtClassType extends CtClass { | |||
String outName = ica.outerClass(i); | |||
if (outName != null) | |||
return classPool.get(outName); | |||
else { | |||
// maybe anonymous or local class. | |||
EnclosingMethodAttribute ema | |||
= (EnclosingMethodAttribute)cf.getAttribute( | |||
EnclosingMethodAttribute.tag); | |||
if (ema != null) | |||
return classPool.get(ema.className()); | |||
} | |||
} | |||
return null; | |||
} | |||
public CtClass getEnclosingClass() throws NotFoundException { | |||
CtClass enc = getDeclaringClass(); | |||
if (enc == null) { | |||
ClassFile cf = getClassFile2(); | |||
EnclosingMethodAttribute ema | |||
public CtMethod getEnclosingMethod() throws NotFoundException { | |||
ClassFile cf = getClassFile2(); | |||
EnclosingMethodAttribute ema | |||
= (EnclosingMethodAttribute)cf.getAttribute( | |||
EnclosingMethodAttribute.tag); | |||
if (ema != null) | |||
enc = classPool.get(ema.className()); | |||
EnclosingMethodAttribute.tag); | |||
if (ema != null) { | |||
CtClass enc = classPool.get(ema.className()); | |||
return enc.getMethod(ema.methodName(), ema.methodDescriptor()); | |||
} | |||
return enc; | |||
return null; | |||
} | |||
public CtClass makeNestedClass(String name, boolean isStatic) { | |||
@@ -515,6 +522,7 @@ class CtClassType extends CtClass { | |||
checkModify(); | |||
CtClass c = classPool.makeNestedClass(getName() + "$" + name); | |||
ClassFile cf = getClassFile2(); | |||
ClassFile cf2 = c.getClassFile2(); | |||
InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute( | |||
InnerClassesAttribute.tag); | |||
if (ica == null) { | |||
@@ -522,8 +530,8 @@ class CtClassType extends CtClass { | |||
cf.addAttribute(ica); | |||
} | |||
ica.append(c.getName(), this.getName(), name, AccessFlag.STATIC); | |||
ClassFile cf2 = c.getClassFile2(); | |||
ica.append(c.getName(), this.getName(), name, | |||
(cf2.getAccessFlags() & ~AccessFlag.SUPER) | AccessFlag.STATIC); | |||
cf2.addAttribute(ica.copy(cf2.getConstPool(), null)); | |||
return c; | |||
} |
@@ -15,8 +15,12 @@ | |||
package javassist; | |||
import javassist.bytecode.ClassFile; | |||
import javassist.bytecode.AccessFlag; | |||
import javassist.bytecode.InnerClassesAttribute; | |||
/** | |||
* A newly created nested class. | |||
* A newly created public nested class. | |||
*/ | |||
class CtNewNestedClass extends CtNewClass { | |||
CtNewNestedClass(String realName, ClassPool cp, boolean isInterface, | |||
@@ -24,8 +28,39 @@ class CtNewNestedClass extends CtNewClass { | |||
super(realName, cp, isInterface, superclass); | |||
} | |||
/** | |||
* This method does not change the STATIC bit. The original value is kept. | |||
*/ | |||
public void setModifiers(int mod) { | |||
super.setModifiers(Modifier.clear(mod, | |||
Modifier.STATIC | Modifier.PRIVATE)); | |||
mod = mod & ~Modifier.STATIC; | |||
super.setModifiers(mod); | |||
updateInnerEntry(mod, getName(), this, true); | |||
} | |||
private static void updateInnerEntry(int mod, String name, CtClass clazz, boolean outer) { | |||
ClassFile cf = clazz.getClassFile2(); | |||
InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute( | |||
InnerClassesAttribute.tag); | |||
if (ica == null) | |||
return; | |||
int n = ica.tableLength(); | |||
for (int i = 0; i < n; i++) | |||
if (name.equals(ica.innerClass(i))) { | |||
int acc = ica.accessFlags(i) & AccessFlag.STATIC; | |||
ica.setAccessFlags(i, mod | acc); | |||
String outName = ica.outerClass(i); | |||
if (outName != null && outer) | |||
try { | |||
CtClass parent = clazz.getClassPool().get(outName); | |||
updateInnerEntry(mod, name, parent, false); | |||
} | |||
catch (NotFoundException e) { | |||
throw new RuntimeException("cannot find the declaring class: " | |||
+ outName); | |||
} | |||
break; | |||
} | |||
} | |||
} |