]> source.dussan.org Git - javassist.git/commitdiff
added CtClass#getDeclaringClass()
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 3 May 2004 17:38:30 +0000 (17:38 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 3 May 2004 17:38:30 +0000 (17:38 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@96 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/ClassPool.java
src/main/javassist/CtClass.java
src/main/javassist/CtClassType.java
src/main/javassist/bytecode/InnerClassesAttribute.java
src/main/javassist/compiler/MemberCodeGen.java

index 054b56e1a31e9ba0c7d1cb8f00e9032be73a681b..8067940e8237d2e02dcd245173a35e5415588c21 100644 (file)
@@ -362,7 +362,12 @@ public class ClassPool {
      * @param classname         a fully-qualified class name.
      */
     public CtClass get(String classname) throws NotFoundException {
-        CtClass clazz = get0(classname, true);
+        CtClass clazz;
+        if (classname == null)
+            clazz = null;
+        else
+            clazz = get0(classname, true);
+
         if (clazz == null)
             throw new NotFoundException(classname);
         else
index c5c86ba531355f38899f5a7612373120052abeb0..f3e8963e474bc3b93035be892de081e34e0ff337 100644 (file)
@@ -480,6 +480,16 @@ public abstract class CtClass {
         checkModify();
     }
 
+    /**
+     * If this class is a member class or interface of another class,
+     * then the class enclosing this class is returned.
+     *
+     * @return null if this class is a top-level class.
+     */
+    public CtClass getDeclaringClass() throws NotFoundException {
+        return null;
+    }
+
     /**
      * Returns an array containing <code>CtField</code> objects
      * representing all the public fields of the class.
index d206b62fc62fa21385b5f41f67e2516b9f1ac95f..e503abcb40b4bb18715a86a396b627f9201e4d75 100644 (file)
@@ -316,6 +316,22 @@ class CtClassType extends CtClass {
             getClassFile2().addInterface(anInterface.getName());
     }
 
+    public CtClass getDeclaringClass() throws NotFoundException {
+        ClassFile cf = getClassFile2();
+        InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
+                                                InnerClassesAttribute.tag);
+        if (ica == null)
+            return null;
+
+        String name = getName();
+        int n = ica.tableLength();
+        for (int i = 0; i < n; ++i)
+            if (name.equals(ica.innerClass(i)))
+                return classPool.get(ica.outerClass(i));
+
+        return null;
+    }
+
     public CtField[] getFields() {
         ArrayList alist = new ArrayList();
         getFields(alist, this);
index 3f3de406d66f239ed073420caa47a1784af3fdee..400a53ca2b9503e6b4ec835e01045581e5588a50 100644 (file)
@@ -46,24 +46,66 @@ public class InnerClassesAttribute extends AttributeInfo {
     /**
      * Returns <code>classes[nth].inner_class_info_index</code>.
      */
-    public int innerClass(int nth) {
+    public int innerClassIndex(int nth) {
         return ByteArray.readU16bit(get(), nth * 8 + 2);
     }
 
+    /**
+     * Returns the class name indicated
+     * by <code>classes[nth].inner_class_info_index</code>.
+     *
+     * @return null or the class name.
+     */
+    public String innerClass(int nth) {
+        int i = innerClassIndex(nth);
+        if (i == 0)
+            return null;
+        else
+            return constPool.getClassInfo(i);
+    }
+
     /**
      * Returns <code>classes[nth].outer_class_info_index</code>.
      */
-    public int outerClass(int nth) {
+    public int outerClassIndex(int nth) {
         return ByteArray.readU16bit(get(), nth * 8 + 4);
     }
 
+    /**
+     * Returns the class name indicated
+     * by <code>classes[nth].outer_class_info_index</code>.
+     *
+     * @return null or the class name.
+     */
+    public String outerClass(int nth) {
+        int i = outerClassIndex(nth);
+        if (i == 0)
+            return null;
+        else
+            return constPool.getClassInfo(i);
+    }
+
     /**
      * Returns <code>classes[nth].inner_name_index</code>.
      */
-    public int innerName(int nth) {
+    public int innerNameIndex(int nth) {
         return ByteArray.readU16bit(get(), nth * 8 + 6);
     }
 
+    /**
+     * Returns the simple class name indicated
+     * by <code>classes[nth].inner_name_index</code>.
+     *
+     * @return null or the class name.
+     */
+    public String innerName(int nth) {
+        int i = innerNameIndex(nth);
+        if (i == 0)
+            return null;
+        else
+            return constPool.getUtf8Info(i);
+    }
+
     /**
      * Returns <code>classes[nth].inner_class_access_flags</code>.
      */
index c35765ef8983e598ecbc47787d0dbc95e28704fa..e8c5ba3b8d636d5abfc18dbd87923e1c029f1e97 100644 (file)
@@ -308,7 +308,12 @@ public class MemberCodeGen extends CodeGen {
         throw new CompileError("bad method");
     }
 
-    // atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew
+    /*
+     * atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew
+     *
+     * @param targetClass       the class at which method lookup starts.
+     * @param found         not null if the method look has been already done.
+     */
     public void atMethodCallCore(CtClass targetClass, String mname,
                         ASTList args, boolean isStatic, boolean isSpecial,
                         int aload0pos, MemberResolver.Method found)
@@ -358,8 +363,10 @@ public class MemberCodeGen extends CodeGen {
         }
         else if ((acc & AccessFlag.PRIVATE) != 0) {
             isSpecial = true;
-            if (declClass != targetClass)
-                throw new CompileError("Method " + mname + "is private");
+            String orgName = mname;
+            mname = getAccessiblePrivate(mname, declClass);
+            if (mname == null)
+                throw new CompileError("Method " + orgName + " is private");
         }
 
         boolean popTarget = false;
@@ -392,6 +399,28 @@ public class MemberCodeGen extends CodeGen {
         setReturnType(desc, isStatic, popTarget);
     }
 
+    protected String getAccessiblePrivate(String methodName,
+                                          CtClass declClass) {
+        if (declClass == thisClass)
+            return methodName;
+        else if (isEnclosing(declClass, thisClass))
+            return null;
+        else
+            return null;    // cannot access this private method.
+    }
+
+    private boolean isEnclosing(CtClass outer, CtClass inner) {
+        try {
+            while (inner != null) {
+                inner = inner.getDeclaringClass();
+                if (inner == outer)
+                    return true;
+            }
+        }
+        catch (NotFoundException e) {}
+        return false;   
+    }
+
     public int getMethodArgsLength(ASTList args) {
         return ASTList.length(args);
     }