Search code examples
javaeclipse-plugineclipse-jdt

How do I know if one class is superclass of another, given that I only have the fully qualified names of the classes as strings?


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.


Solution

  • 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);
    }