I need to know if the class represented by one string is superclass (directly or transitively) of another class also represented as a string. For instance:
String class1 = "java.lang.Object";
String class2 = "java.lang.Exception";
assertTrue( isSuperclass( class1, class2 ) );
I tried to get the IType for the second class and check its superclassName. This is how I tried:
/**
* Checks if class1 is directly or transitively superclass of class2.
*/
private boolean isSuperclass(final String class1, final String class2)
{
try
{
String className = class2;
while (className!=null)
{
final IType type = this.javaProject.findType(className);
if (type == null)
{
break;
}
className = type.getSuperclassName();
if (class1.equals(className))
{
return true;
}
}
return false;
}
catch (final JavaModelException e)
{
throw new IllegalStateException(e);
}
}
The problem is that getSuperclassName returns only the class name, not its fully qualified name. For this reason, I can't call javaProject.findType again in the loop to check if any transitive superclass of class2 is equals to class1.
So if I call:
isSuperclass( "java.lang.Throwable", "my.exceptions.Exception" )
It will return false, because
javaProject.findType("my.exceptions.Exception").getSuperclassName()
returns only "ParentException", then the next call will be
javaProject.findType("ParentException")
which returns a null IType, since its not the class fully qualified name. This only occurs with the classes declared in the own application being analyzed; for API classes getSuperclassName returns the fully qualified name.
I also thought of checking isSuperclass via ITypeBindings, but I don't know how to get an ITypeBinding from the fully qualified name String, or from the IType.
Any ideas on how I can check if a class is superclass of another?
EDIT: Solutions based on Class.forName won't work on my context.
Based on the answer from T.J. Crowder, the comment from Brian and the code in this page, I built this answer:
public boolean isSuperclass(final String className1, final String className2)
{
//build a URL Class Loader
final String[] classPathEntries = JavaRuntime.computeDefaultRuntimeClassPath(iJavaProject);
final List<URL> urlList = new ArrayList<URL>();
for (int i = 0; i < classPathEntries.length; i++)
{
final String entry = classPathEntries[i];
final IPath path = new Path(entry);
final URL url = path.toFile().toURI().toURL();
urlList.add(url);
}
final ClassLoader parentClassLoader = iJavaProject.getClass().getClassLoader();
final URL[] urls = urlList.toArray(new URL[urlList.size()]);
final URLClassLoader classLoader = new URLClassLoader(urls, parentClassLoader);
// check if is superclass
final Class<?> class1 = Class.forName(className1, true, classLoader);
final Class<?> class2 = Class.forName(className2, true, classLoader);
return class1.isAssignableFrom(class2);
}