aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/compiler
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-05-08 14:49:33 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-05-08 14:49:33 +0000
commit318f2be20c448e3412c7fe2c9c3f5fa4c4699ae9 (patch)
treef3baba84ed6dc9986e0f357a5e630f351dc7fc37 /src/main/javassist/compiler
parentd906bfb3374b900b287ae12a1a837e0ffd9c21c5 (diff)
downloadjavassist-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.java47
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java42
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) {