aboutsummaryrefslogtreecommitdiff
path: root/src/main/javassist/compiler/MemberResolver.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/compiler/MemberResolver.java')
-rw-r--r--src/main/javassist/compiler/MemberResolver.java205
1 files changed, 123 insertions, 82 deletions
diff --git a/src/main/javassist/compiler/MemberResolver.java b/src/main/javassist/compiler/MemberResolver.java
index fb2aa9b..00dac6c 100644
--- a/src/main/javassist/compiler/MemberResolver.java
+++ b/src/main/javassist/compiler/MemberResolver.java
@@ -1,11 +1,12 @@
/*
* Javassist, a Java-bytecode translator toolkit.
- * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
+ * Copyright (C) 1999- 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.
+ * the terms of the GNU Lesser General Public License Version 2.1 or later,
+ * or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
@@ -15,11 +16,28 @@
package javassist.compiler;
-import java.util.List;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Hashtable;
import java.util.Iterator;
-import javassist.*;
-import javassist.bytecode.*;
-import javassist.compiler.ast.*;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import javassist.bytecode.AccessFlag;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.Descriptor;
+import javassist.bytecode.MethodInfo;
+import javassist.compiler.ast.ASTList;
+import javassist.compiler.ast.ASTree;
+import javassist.compiler.ast.Declarator;
+import javassist.compiler.ast.Keyword;
+import javassist.compiler.ast.Symbol;
/* Code generator methods depending on javassist.* classes.
*/
@@ -36,22 +54,6 @@ public class MemberResolver implements TokenId {
throw new CompileError("fatal");
}
- /**
- * @param jvmClassName a class name. Not a package name.
- */
- public void recordPackage(String jvmClassName) {
- String classname = jvmToJavaName(jvmClassName);
- for (;;) {
- int i = classname.lastIndexOf('.');
- if (i > 0) {
- classname = classname.substring(0, i);
- classPool.recordInvalidClassName(classname);
- }
- else
- break;
- }
- }
-
public static class Method {
public CtClass declaring;
public MethodInfo info;
@@ -88,8 +90,7 @@ public class MemberResolver implements TokenId {
Method r = new Method(clazz, current, res);
if (res == YES)
return r;
- else
- maybe = r;
+ maybe = r;
}
}
@@ -97,8 +98,7 @@ public class MemberResolver implements TokenId {
argClassNames, maybe != null);
if (m != null)
return m;
- else
- return maybe;
+ return maybe;
}
private Method lookupMethod(CtClass clazz, String methodName,
@@ -111,11 +111,10 @@ public class MemberResolver implements TokenId {
// If the class is an array type, the class file is null.
// If so, search the super class java.lang.Object for clone() etc.
if (cf != null) {
- List list = cf.getMethods();
- int n = list.size();
- for (int i = 0; i < n; ++i) {
- MethodInfo minfo = (MethodInfo)list.get(i);
- if (minfo.getName().equals(methodName)) {
+ List<MethodInfo> list = cf.getMethods();
+ for (MethodInfo minfo:list) {
+ if (minfo.getName().equals(methodName)
+ && (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0) {
int res = compareSignature(minfo.getDescriptor(),
argTypes, argDims, argClassNames);
if (res != NO) {
@@ -132,7 +131,8 @@ public class MemberResolver implements TokenId {
if (onlyExact)
maybe = null;
else
- onlyExact = maybe != null;
+ if (maybe != null)
+ return maybe;
int mod = clazz.getModifiers();
boolean isIntf = Modifier.isInterface(mod);
@@ -150,30 +150,28 @@ public class MemberResolver implements TokenId {
}
catch (NotFoundException e) {}
- if (isIntf || Modifier.isAbstract(mod))
- try {
- CtClass[] ifs = clazz.getInterfaces();
- int size = ifs.length;
- for (int i = 0; i < size; ++i) {
- Method r = lookupMethod(ifs[i], methodName,
- argTypes, argDims, argClassNames,
- onlyExact);
+ try {
+ CtClass[] ifs = clazz.getInterfaces();
+ for (CtClass intf:ifs) {
+ Method r = lookupMethod(intf, methodName,
+ argTypes, argDims, argClassNames,
+ onlyExact);
+ if (r != null)
+ return r;
+ }
+
+ if (isIntf) {
+ // finally search java.lang.Object.
+ CtClass pclazz = clazz.getSuperclass();
+ if (pclazz != null) {
+ Method r = lookupMethod(pclazz, methodName, argTypes,
+ argDims, argClassNames, onlyExact);
if (r != null)
return r;
}
-
- if (isIntf) {
- // finally search java.lang.Object.
- CtClass pclazz = clazz.getSuperclass();
- if (pclazz != null) {
- Method r = lookupMethod(pclazz, methodName, argTypes,
- argDims, argClassNames, onlyExact);
- if (r != null)
- return r;
- }
- }
}
- catch (NotFoundException e) {}
+ }
+ catch (NotFoundException e) {}
return maybe;
}
@@ -275,6 +273,7 @@ public class MemberResolver implements TokenId {
* Only used by fieldAccess() in MemberCodeGen and TypeChecker.
*
* @param jvmClassName a JVM class name. e.g. java/lang/String
+ * @see #lookupClass(String, boolean)
*/
public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym,
ASTree expr) throws NoFieldException
@@ -309,7 +308,7 @@ public class MemberResolver implements TokenId {
}
/**
- * @param name a qualified class name. e.g. java.lang.String
+ * @param className a qualified class name. e.g. java.lang.String
*/
public CtField lookupField(String className, Symbol fieldName)
throws CompileError
@@ -336,7 +335,7 @@ public class MemberResolver implements TokenId {
}
/**
- * @parma classname jvm class name.
+ * @param classname jvm class name.
*/
public CtClass lookupClass(int type, int dim, String classname)
throws CompileError
@@ -405,45 +404,78 @@ public class MemberResolver implements TokenId {
public CtClass lookupClass(String name, boolean notCheckInner)
throws CompileError
{
+ Map<String,String> cache = getInvalidNames();
+ String found = cache.get(name);
+ if (found == INVALID)
+ throw new CompileError("no such class: " + name);
+ else if (found != null)
+ try {
+ return classPool.get(found);
+ }
+ catch (NotFoundException e) {}
+
+ CtClass cc = null;
try {
- return lookupClass0(name, notCheckInner);
+ cc = lookupClass0(name, notCheckInner);
}
catch (NotFoundException e) {
- return searchImports(name);
+ cc = searchImports(name);
+ }
+
+ cache.put(name, cc.getName());
+ return cc;
+ }
+
+ private static final String INVALID = "<invalid>";
+ private static Map<ClassPool, Reference<Map<String,String>>> invalidNamesMap =
+ new WeakHashMap<ClassPool, Reference<Map<String,String>>>();
+ private Map<String,String> invalidNames = null;
+
+ // for unit tests
+ public static int getInvalidMapSize() { return invalidNamesMap.size(); }
+
+ private Map<String,String> getInvalidNames() {
+ Map<String,String> ht = invalidNames;
+ if (ht == null) {
+ synchronized (MemberResolver.class) {
+ Reference<Map<String,String>> ref = invalidNamesMap.get(classPool);
+ if (ref != null)
+ ht = ref.get();
+
+ if (ht == null) {
+ ht = new Hashtable<String,String>();
+ invalidNamesMap.put(classPool, new WeakReference<Map<String,String>>(ht));
+ }
+ }
+
+ invalidNames = ht;
}
+
+ return ht;
}
private CtClass searchImports(String orgName)
throws CompileError
{
if (orgName.indexOf('.') < 0) {
- Iterator it = classPool.getImportedPackages();
+ Iterator<String> it = classPool.getImportedPackages();
while (it.hasNext()) {
- String pac = (String)it.next();
- String fqName = pac + '.' + orgName;
+ String pac = it.next();
+ String fqName = pac.replaceAll("\\.$","") + "." + orgName;
try {
- CtClass cc = classPool.get(fqName);
- // if the class is found,
- classPool.recordInvalidClassName(orgName);
- return cc;
+ return classPool.get(fqName);
}
catch (NotFoundException e) {
- classPool.recordInvalidClassName(fqName);
try {
- if (pac.endsWith("." + orgName)) {
- CtClass cc = classPool.get(pac);
- // if the class is found,
- classPool.recordInvalidClassName(orgName);
- return cc;
- }
- }
- catch (NotFoundException e2) {
- classPool.recordInvalidClassName(pac);
+ if (pac.endsWith("." + orgName))
+ return classPool.get(pac);
}
+ catch (NotFoundException e2) {}
}
}
}
+ getInvalidNames().put(orgName, INVALID);
throw new CompileError("no such class: " + orgName);
}
@@ -459,11 +491,9 @@ public class MemberResolver implements TokenId {
int i = classname.lastIndexOf('.');
if (notCheckInner || i < 0)
throw e;
- else {
- StringBuffer sbuf = new StringBuffer(classname);
- sbuf.setCharAt(i, '$');
- classname = sbuf.toString();
- }
+ StringBuffer sbuf = new StringBuffer(classname);
+ sbuf.setCharAt(i, '$');
+ classname = sbuf.toString();
}
} while (cc == null);
return cc;
@@ -477,8 +507,7 @@ public class MemberResolver implements TokenId {
public String resolveClassName(ASTList name) throws CompileError {
if (name == null)
return null;
- else
- return javaToJvmName(lookupClassByName(name).getName());
+ return javaToJvmName(lookupClassByName(name).getName());
}
/* Expands a simple class name to java.lang.*.
@@ -487,8 +516,7 @@ public class MemberResolver implements TokenId {
public String resolveJvmClassName(String jvmName) throws CompileError {
if (jvmName == null)
return null;
- else
- return javaToJvmName(lookupClassByJvmName(jvmName).getName());
+ return javaToJvmName(lookupClassByJvmName(jvmName).getName());
}
public static CtClass getSuperclass(CtClass c) throws CompileError {
@@ -502,6 +530,19 @@ public class MemberResolver implements TokenId {
+ c.getName());
}
+ public static CtClass getSuperInterface(CtClass c, String interfaceName)
+ throws CompileError
+ {
+ try {
+ CtClass[] intfs = c.getInterfaces();
+ for (int i = 0; i < intfs.length; i++)
+ if (intfs[i].getName().equals(interfaceName))
+ return intfs[i];
+ } catch (NotFoundException e) {}
+ throw new CompileError("cannot find the super inetrface " + interfaceName
+ + " of " + c.getName());
+ }
+
public static String javaToJvmName(String classname) {
return classname.replace('.', '/');
}