@@ -550,6 +550,43 @@ public abstract class CtClass { | |||
return null; | |||
} | |||
/** | |||
* Returns a collection of the names of all the classes | |||
* referenced in this class. | |||
* This reference contains a reference to the generic. | |||
* If you wish to exclude generics,see this method{@link CtClass#getRefClasses()} | |||
* That collection includes the name of this class. | |||
* | |||
* <p>This method may return <code>null</code>. | |||
* | |||
* @return a <code>Collection<String></code> object. | |||
*/ | |||
public synchronized Collection<String> getAllRefClasses() { | |||
ClassFile cf = getClassFile2(); | |||
if (cf != null) { | |||
ClassMap cm = new ClassMap() { | |||
/** default serialVersionUID */ | |||
private static final long serialVersionUID = 1L; | |||
@Override | |||
public String put(String oldname, String newname) { | |||
return put0(oldname, newname); | |||
} | |||
@Override | |||
public String get(Object jvmClassName) { | |||
String n = toJavaName((String)jvmClassName); | |||
put0(n, n); | |||
return null; | |||
} | |||
@Override | |||
public void fix(String name) {} | |||
}; | |||
cf.getAllRefClasses(cm); | |||
return cm.values(); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Determines whether this object represents a class or an interface. | |||
* It returns <code>true</code> if this object represents an interface. |
@@ -522,6 +522,39 @@ public final class ClassFile { | |||
} | |||
} | |||
/** | |||
* Internal-use only. | |||
* <code>CtClass.getAllRefClasses()</code> calls this method. | |||
*/ | |||
public final void getAllRefClasses(Map<String, String> classnames) { | |||
constPool.renameClass(classnames); | |||
AttributeInfo.getRefClasses(attributes, classnames); | |||
for (MethodInfo minfo : methods) { | |||
String genericDesc = getGenericDesc(minfo); | |||
if (genericDesc != null) | |||
Descriptor.renameIncludeGenerics(genericDesc, classnames); | |||
else | |||
Descriptor.rename(minfo.getDescriptor(), classnames); | |||
AttributeInfo.getRefClasses(minfo.getAttributes(), classnames); | |||
} | |||
for (FieldInfo finfo : fields) { | |||
String desc = finfo.getDescriptor(); | |||
Descriptor.rename(desc, classnames); | |||
AttributeInfo.getRefClasses(finfo.getAttributes(), classnames); | |||
} | |||
} | |||
/** | |||
* Returns the generic signature | |||
*/ | |||
private String getGenericDesc(MethodInfo methodInfo) { | |||
SignatureAttribute sa | |||
= (SignatureAttribute) methodInfo.getAttribute(SignatureAttribute.tag); | |||
return sa == null ? null : sa.getSignature(); | |||
} | |||
/** | |||
* Returns the names of the interfaces implemented by the class. | |||
* The returned array is read only. |
@@ -188,6 +188,55 @@ public class Descriptor { | |||
return newdesc.toString(); | |||
} | |||
/** | |||
* Substitutes class names and generics in the given descriptor string | |||
* according to the given <code>map</code>. | |||
* | |||
* @param map a map between replaced and substituted | |||
* JVM class names. | |||
* @see Descriptor#toJvmName(String) | |||
*/ | |||
public static String renameIncludeGenerics(String desc, Map<String, String> map) { | |||
if (map == null) | |||
return desc; | |||
StringBuilder newdesc = new StringBuilder(); | |||
int head = 0; | |||
int i = 0; | |||
for (; ; ) { | |||
int j = desc.indexOf('L', i); | |||
if (j < 0) | |||
break; | |||
int x = desc.indexOf('<', j); | |||
int y = desc.indexOf(';', j); | |||
if (x == y) | |||
break; | |||
int k = x == -1 ? y : 0; | |||
if (k == 0) | |||
k = Math.min(x,y); | |||
i = k + 1; | |||
String name = desc.substring(j + 1, k); | |||
String name2 = map.get(name); | |||
if (name2 != null) { | |||
newdesc.append(desc.substring(head, j)); | |||
newdesc.append('L'); | |||
newdesc.append(name2); | |||
newdesc.append(';'); | |||
head = i; | |||
} | |||
} | |||
if (head == 0) | |||
return desc; | |||
int len = desc.length(); | |||
if (head < len) | |||
newdesc.append(desc.substring(head, len)); | |||
return newdesc.toString(); | |||
} | |||
/** | |||
* Substitutes class names in the given descriptor string | |||
* according to the given <code>map</code>. |
@@ -481,6 +481,28 @@ public class JvstTest4 extends JvstTestRoot { | |||
} | |||
} | |||
public void testGetAllRefD() throws Exception { | |||
CtClass cc = sloader.get("test4.GetAllRefD"); | |||
HashSet set = new HashSet(); | |||
set.add("java.lang.Object"); | |||
set.add("java.lang.String"); | |||
set.add("test4.GetAllRefC"); | |||
set.add("test4.GetAllRefAnno"); | |||
set.add("test4.GetAllRefEnum"); | |||
set.add("test4.GetAllRefAnnoC"); | |||
set.add("test4.GetAllRefAnnoC2"); | |||
set.add("test4.GetAllRefAnnoC3"); | |||
set.add("test4.GetAllRefAnnoC4"); | |||
set.add("java.util.List"); | |||
set.add("test4.GetAllRefD"); | |||
java.util.Collection<String> refs | |||
= (java.util.Collection<String>)cc.getAllRefClasses(); | |||
assertEquals(set.size(), refs.size()); | |||
for (String s: refs) { | |||
assertTrue(set.contains(s)); | |||
} | |||
} | |||
public void testGetAllRefInner() throws Exception { | |||
HashSet set = new HashSet(); | |||
set.add("java.lang.Object"); |
@@ -1,5 +1,7 @@ | |||
package test4; | |||
import java.util.List; | |||
enum GetAllRefEnum { A, B }; | |||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) | |||
@@ -31,3 +33,11 @@ class GetAllRefC { | |||
@GetAllRefAnnoC void foo() {} | |||
@GetAllRefAnnoC2 int value; | |||
} | |||
@GetAllRefAnno(getA = GetAllRefEnum.A, getC = String.class) | |||
interface GetAllRefD { | |||
void bar(@GetAllRefAnnoC3 int i, int j, | |||
@GetAllRefAnnoC2 @GetAllRefAnnoC4 boolean b); | |||
@GetAllRefAnnoC | |||
List<GetAllRefC> foo(); | |||
} |