* @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
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.
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);
/**
* 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>.
*/
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)
}
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;
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);
}