This discussion is archived
1 2 Previous Next 23 Replies Latest reply: Jun 12, 2010 11:44 AM by 843798 RSS

Search for extending classes.

843798 Newbie
Currently Being Moderated
I have to search the classpath for all the classes that extends an abstract class or that implements an interface. The fact is that these classes can be spread through different JArs and if I use the getResource method I only receive the first part...
For example:
//AAA.jar
//  |
//  +- mypackage
//           |
//           +- TheInterface
//           +- TheAbstractClass
//
//BBB.jar
//  |
//  +- mypackage
//           |
//          +- Implementation (implements TheInterface)
//          +- Inheritance (extends TheAbstractClass)
If I put AAA.jar as first in the classpath, I cannot find the real implementations I need.
List<String> myMethod(Class<?> caller, String packageToSearchInto, String classToSearchExtensionsFor) {
    URL address = getResource(packageToSearchInto);
    File content = new File(address.getFile());

    if (content.isDirectory()) {
        list = findInsideClass(package, content, classToSearchExtensionsFor, list);
    } else {
        list = findInsideJar(address, classToSearchExtensionsFor, list);
    }
    return list;
}
And method findInsideJar(URL, String) should return a List<String> of all the (concrete) classes that extends/implements classToSearchExtensionsFor.

(sorry for the Italian language for variables and so on... hope you can understand... I can add a brief translation if needed... note that: Strumenti.BARRA = '/' while Strumenti.CLASSE = ".class" and Strumenti.D_STRUMENTI is a logger.)
    private static List<String> trovaJar(final URL pIndirizzo,
            final Class<?> pClasse, final List<String> pElenco) {

        /* i file .class sono in un file jar (testato: funziona!) */
        try {

            /* definizione variabili */
            final JarURLConnection con =
                (JarURLConnection) pIndirizzo.openConnection();
            final String inizio = con.getEntryName();
            final JarFile file = con.getJarFile();

            /* esplorazione jar */
            for (final Enumeration<JarEntry> i = file.entries();
                    i.hasMoreElements(); ) {

                /* definizione variabili */
                final ZipEntry voce = i.nextElement();
                final String nomeVoce = voce.getName();

                /* controllo voce elenco */
                if ((nomeVoce.startsWith(inizio)) && (nomeVoce
                        .lastIndexOf(Strumenti.BARRA) <= inizio
                        .length()) && (nomeVoce.endsWith(Strumenti.CLASSE))) {

                    /* definizione variabili */
                    String nome =
                        nomeVoce.substring(0, nomeVoce.length()
                                           - Strumenti.CLASSE.length());

                    if (nome.charAt(0) == Strumenti.BARRA) {
                        nome = nome.substring(1);
                    }

                    nome = nome.replace(Strumenti.BARRA, '.');

                    try {

                        /* definizione variabili */
                        final Object corrente =
                            Class.forName(nome).newInstance();

                        if (pClasse.isInstance(corrente)) {
                            pElenco.add(nome);
                        }
                    } catch (InstantiationException iE) {
                        Strumenti.D_STRUMENTI.error(iE.getLocalizedMessage(),
                                                    iE);
                    } catch (IllegalAccessException iAE) {
                        Strumenti.D_STRUMENTI.error(iAE.getLocalizedMessage(),
                                                    iAE);
                    } catch (Exception e) {
                        Strumenti.D_STRUMENTI.error(e.getLocalizedMessage(), e);
                        pElenco.clear();
                    }
                }
            }
        } catch (Exception e) {
            Strumenti.D_STRUMENTI.error(e.getLocalizedMessage(), e);
            pElenco.clear();
        }

        return pElenco;
    }
I'm searching for a way to find, through all available JArs in the classpath, the list of all the classes that extends/implements a specific abstract/interface, possibly without considering the package to search into. Is it possible?
  • 1. Re: Search for extending classes.
    800389 Newbie
    Currently Being Moderated
    You can also have a look at the sample [Identify subclasses at runtime|http://www.javaworld.com/javaworld/javatips/jw-javatip113.html?page=2] . Probably, it may help you.
  • 2. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    Thanks, i'll check!

    Edited by: marco.bresciani on 1-giu-2010 12.57
  • 3. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    Why do you need to do this? Sounds like something that should be solved in another way.
  • 4. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    I actually have an application that use a set of interfaces to retrieve some services and needs.

    These interfaces are implemented by "third parties" and my application does not have any control on how many implementations are available since it only depends on the interfaces. So, for example:

    application.jar
    service_interfaces.jar


    service_implementation1.jar
    service_implementation2.jar
    ...
    service_implementationN.jar


    At startup, I'll put all available JArs in classpath and my application has to search for all the interfaces implementations in order to choose the correct implementation based on other context information.
  • 5. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    A far more common way is to tell the user to place the jar files in a certain directory, and have e.g. an entry in the manifest of each jar that says what the "main class" of each plugin is.
  • 6. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    Do also note that your original code might fail under certain conditions.

    E.g the user created a baseclass that implements your interface. The subclass that is the actual plugin extends the baseclass. Your code would try to instantiate the baseclass, and fail.

    Edit: Did now check your code, and can't see that you actually check that something is implementing your interface. You are trying to instantiate all classes?
  • 7. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    Uhm... so this means that classpath needs no modification, right? If I'm not wrong, manifests already contain this information; I can obviously put it as mandatory requirement.

    Anyway, I have to manually load/open the JArs and then... can I use "Class.forName()" if a class is not in the classpath? How can I load the classes?
  • 8. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    Got the point:
    MyInterface -> MyAbstract -> ThirdPartyClass
                -> AnotherThirdPartyClass
    Something like this? It could happen that "AnotherThirdPartyClass" does not work, right? But I actually search for the class that implements/extends what I want. I mean, if I'm searching for classes that implements MyInterface, I have two results, but if I search for classes extending MyAbstract I only have one result.
    Also, if the "newInstance()" does not work, means that the resulting class is not usable, so I will not put it in the results list.

    Edited by: marco.bresciani on 4-giu-2010 11.06

    Edited by: marco.bresciani on 4-giu-2010 11.07

    Edited by: marco.bresciani on 4-giu-2010 11.07
  • 9. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    marco.bresciani wrote:
    Uhm... so this means that classpath needs no modification, right?
    Correct.
    If I'm not wrong, manifests already contain this information; I can obviously put it as mandatory requirement.
    The manifest can contain lots of different information, and you can tell your clients that their plugins must have a certain entry in the manifest.

    >
    Anyway, I have to manually load/open the JArs and then... can I use "Class.forName()" if a class is not in the classpath? How can I load the classes?
    You can load classes, and instantiate classes that aren't on the classpath by creating an instance of URLClassLoader. That's how many application servers are doing it.
  • 10. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    marco.bresciani wrote:
    Got the point:
    MyInterface -> MyAbstract -> ThirdPartyClass
    -> AnotherThirdPartyClass
    Something like this? It could happen that "AnotherThirdPartyClass" does not work, right? But I actually search for the class that implements/extends what I want. I mean, if I'm searching for classes that implements MyInterface, I have two results, but if I search for classes extending MyAbstract I only have one result.
    Also, if the "newInstance()" does not work, means that the resulting class is not usable, so I will not put it in the results list.
    I wouldn't try to instantiate all classes that I find. I would first check if a certain class implements my interface, and then try to instantiate (if I went with your original solution).

    I don't know how advanced your plugins can be, but I developer of plugins do usually write several classes, but only one class is the "main entry"
  • 11. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    Sure I do! :-) I mean: I'm searching through the classpath for all classes that implements/extends what they want. If I found something, I load the class and try to instantiate it. If it works, I'll add it to the result.

    I'll try to check with URLClassLoader to understand how it works.

    Plugins are very very simple: they instantiate/implements some interfaces. All the "workload" is in charge of the main appplication. I'll load the classes, instantiates them with the default constructor and use the interfaces to work. That's it.
  • 12. Re: Search for extending classes.
    791266 Explorer
    Currently Being Moderated
    marco.bresciani wrote:
    Sure I do! :-) I mean: I'm searching through the classpath for all classes that implements/extends what they want.
    How do you do that? I can't see that you do that in the posted code. I can see that you do a test after you have instantiated something, but not before.

    To me it looks like you are trying to instantiate all classes that you find.
  • 13. Re: Search for extending classes.
    843798 Newbie
    Currently Being Moderated
    I'm now using the solution that Adhir_Mehta shown me above. With very few modifications, I'll return the list of all instantiable classes that extends/implements something I want.
    I'm not in office today. I can post the code here on monday.
  • 14. Re: Search for extending classes.
    jtahlborn Expert
    Currently Being Moderated
    why not use the support for this idea built into the jdk? the java.util.ServiceLoader class facilitates collecting and reading special files that the plugin developers place in the META-INF/services directories inside their jar files. this is how many of the plugins in the jdk itself are handled.
1 2 Previous Next