浏览代码

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
tags/rel_3_17_1_ga
chiba 20 年前
父节点
当前提交
318f2be20c

+ 1
- 1
src/main/javassist/CtClass.java 查看文件

@@ -35,7 +35,7 @@ public abstract class CtClass {
/**
* The version number of this release.
*/
public static final String version = "3.0 RC1";
public static final String version = "3.0 RC0";

/**
* Prints the version number and the copyright notice.

+ 1
- 0
src/main/javassist/bytecode/MethodInfo.java 查看文件

@@ -57,6 +57,7 @@ public final class MethodInfo {

/**
* Constructs a <code>method_info</code> structure.
* The initial value of <code>access_flags</code> is zero.
*
* @param cp a constant pool table
* @param methodname method name

+ 47
- 0
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.
*

+ 33
- 9
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) {

+ 24
- 0
src/main/javassist/runtime/Inner.java 查看文件

@@ -0,0 +1,24 @@
/*
* 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.runtime;

/**
* A support class for compiling a method declared in an inner class.
* This support class is required at runtime
* only if the method calls a private constructor in the enclosing class.
*/
public class Inner {
}

正在加载...
取消
保存