diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-05-08 14:49:33 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-05-08 14:49:33 +0000 |
commit | 318f2be20c448e3412c7fe2c9c3f5fa4c4699ae9 (patch) | |
tree | f3baba84ed6dc9986e0f357a5e630f351dc7fc37 /src/main/javassist/compiler | |
parent | d906bfb3374b900b287ae12a1a837e0ffd9c21c5 (diff) | |
download | javassist-318f2be20c448e3412c7fe2c9c3f5fa4c4699ae9.tar.gz javassist-318f2be20c448e3412c7fe2c9c3f5fa4c4699ae9.zip |
Now, the compiler accepts a method that calls
a private constructor declared in an enclosing class.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@99 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/compiler')
-rw-r--r-- | src/main/javassist/compiler/AccessorMaker.java | 47 | ||||
-rw-r--r-- | src/main/javassist/compiler/MemberCodeGen.java | 42 |
2 files changed, 80 insertions, 9 deletions
diff --git a/src/main/javassist/compiler/AccessorMaker.java b/src/main/javassist/compiler/AccessorMaker.java index bfe59f51..14f46194 100644 --- a/src/main/javassist/compiler/AccessorMaker.java +++ b/src/main/javassist/compiler/AccessorMaker.java @@ -28,12 +28,59 @@ public class AccessorMaker { private int uniqueNumber; private HashMap accessors; + static final String lastParamType = "javassist.runtime.Inner"; + public AccessorMaker(CtClass c) { clazz = c; uniqueNumber = 1; accessors = new HashMap(); } + public String getConstructor(CtClass c, String desc, MethodInfo orig) + throws CompileError + { + String key = "<init>:" + desc; + String consDesc = (String)accessors.get(key); + if (consDesc != null) + return consDesc; // already exists. + + consDesc = Descriptor.appendParameter(lastParamType, desc); + ClassFile cf = clazz.getClassFile(); // turn on the modified flag. + try { + ConstPool cp = cf.getConstPool(); + ClassPool pool = clazz.getClassPool(); + MethodInfo minfo + = new MethodInfo(cp, MethodInfo.nameInit, consDesc); + minfo.setAccessFlags(0); + minfo.addAttribute(new SyntheticAttribute(cp)); + ExceptionsAttribute ea = orig.getExceptionsAttribute(); + if (ea != null) + minfo.addAttribute(ea.copy(cp, null)); + + CtClass[] params = Descriptor.getParameterTypes(desc, pool); + Bytecode code = new Bytecode(cp); + code.addAload(0); + int regno = 1; + for (int i = 0; i < params.length; ++i) + regno += code.addLoad(regno, params[i]); + code.setMaxLocals(regno + 1); // the last parameter is added. + code.addInvokespecial(clazz, MethodInfo.nameInit, desc); + + code.addReturn(null); + minfo.setCodeAttribute(code.toCodeAttribute()); + cf.addMethod(minfo); + } + catch (CannotCompileException e) { + throw new CompileError(e); + } + catch (NotFoundException e) { + throw new CompileError(e); + } + + accessors.put(key, consDesc); + return consDesc; + } + /** * Returns the name of the method for accessing a private method. * diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java index 0a58dc97..a70acf84 100644 --- a/src/main/javassist/compiler/MemberCodeGen.java +++ b/src/main/javassist/compiler/MemberCodeGen.java @@ -331,6 +331,7 @@ public class MemberCodeGen extends CodeGen { int stack = bytecode.getStackDepth(); + // generate code for evaluating arguments. atMethodArgs(args, types, dims, cnames); // used by invokeinterface @@ -370,12 +371,16 @@ public class MemberCodeGen extends CodeGen { isSpecial = true; if (declClass != targetClass) throw new CompileError("no such a constructor"); + + if (declClass != thisClass && AccessFlag.isPrivate(acc)) { + desc = getAccessibleConstructor(desc, declClass, minfo); + bytecode.addOpcode(Opcode.ACONST_NULL); // the last parameter + } } else if (AccessFlag.isPrivate(acc)) if (declClass == thisClass) isSpecial = true; else { - String orgName = mname; isSpecial = false; isStatic = true; String origDesc = desc; @@ -386,9 +391,6 @@ public class MemberCodeGen extends CodeGen { acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC; mname = getAccessiblePrivate(mname, origDesc, desc, minfo, declClass); - if (mname == null) - throw new CompileError("Method " + orgName - + " is private"); } boolean popTarget = false; @@ -435,14 +437,36 @@ public class MemberCodeGen extends CodeGen { { if (isEnclosing(declClass, thisClass)) { AccessorMaker maker = declClass.getAccessorMaker(); - if (maker == null) - return null; - else + if (maker != null) return maker.getMethodAccessor(methodName, desc, newDesc, minfo); } - else - return null; // cannot access this private method. + + throw new CompileError("Method " + methodName + + " is private"); + } + + /* + * Finds (or adds if necessary) a hidden constructor if the given + * constructor is in an enclosing class. + * + * @param desc the descriptor of the constructor. + * @param declClass the class declaring the constructor. + * @param minfo the method info of the constructor. + * @return the descriptor of the hidden constructor. + */ + protected String getAccessibleConstructor(String desc, CtClass declClass, + MethodInfo minfo) + throws CompileError + { + if (isEnclosing(declClass, thisClass)) { + AccessorMaker maker = declClass.getAccessorMaker(); + if (maker != null) + return maker.getConstructor(declClass, desc, minfo); + } + + throw new CompileError("the called constructor is private in " + + declClass.getName()); } private boolean isEnclosing(CtClass outer, CtClass inner) { |