Build classpath from JAR inside a WAR file

Olivier.Roger

I am trying to dynamically extract configuration from a given WAR file. My goal is to find all class that implement some interface (Parameter).

The war file is not on the classpath, so I create a temporary classloader to inspect its classes.

URL webClasses = new URL("jar","","file:" + new File(path).getAbsolutePath() + "!/WEB-INF/classes/");
URLClassLoader cl = URLClassLoader.newInstance(new URL[] { webClasses });
Reflections reflections = new Reflections(ClasspathHelper.forClassLoader(cl), new SubTypesScanner(), cl);
Set<Class<? extends Parameter>> params = reflections.getSubTypesOf(Parameter.class);

This works fine. I find all the implementation of Parameter in my webapp.

Now, I would like to do the same for each jar present in WEB-INF/lib. Unfortunatelly I have not found a way to build the classloader in that case. The classloader seems to ignore jar URLs (jar:<url>!/WEB-INF/lib/{entry}.jar).

When I run the code below, there is no class found by Reflections:

Set<URL> libs = findLibJars(warUrl));
// The URLs are in the following format : {myWar}.war!/WEB-INF/lib/{myLib}.jar
URLClassLoader cl = URLClassLoader.newInstance(urls.toArray(new URL[urls.size()]));
cl.loadClass("my.company.config.AppParameter");

If possible, I would like to avoid having to extract WEB-INF/lib/*.jar from the WAR file and analyze them separately.

I am missing something here ? (other way to do it, other way to create the classloader, ... any lead would help). Maybe this can be done without using the Reflections library ?

Sergei Tachenov

It is certainly possible. Here is an ugly example of doing it:

String warName = "wlaj.war";
ClassLoader loader = new ClassLoader() {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // This probably needs fixing:
        String fileName = name.replace('.', '/') + ".class";
        try {
            try (ZipFile zf = new ZipFile(warName)) {
                ZipEntry jar = zf.getEntry("WEB-INF/lib/jlaj.jar");
                if (jar == null)
                    throw new ClassNotFoundException("No jlaj.jar");
                try (ZipInputStream jarInput = new ZipInputStream(zf.getInputStream(jar))) {
                    for (ZipEntry cl; (cl = jarInput.getNextEntry()) != null; ) {
                        if (fileName.equals(cl.getName())) {
                            ByteArrayOutputStream data = new ByteArrayOutputStream();
                            byte[] buffer = new byte[4096];
                            for (int len; (len = jarInput.read(buffer)) != -1; ) {
                                data.write(buffer, 0, len);
                            }
                            buffer = data.toByteArray();
                            return defineClass(name, buffer, 0, buffer.length);
                        }
                    }
                }
            }
            throw new ClassNotFoundException();
        } catch (IOException ex) {
            throw new ClassNotFoundException("Error opening class file", ex);
        }
    }
};
loader.loadClass("jlaj.NewJFrame");

The problems:

  1. Need an elegant foolproof way to convert a class name into the file path inside the JAR. In my case "jlaj.NewJFrame" -> "jlaj/NewJFrame.class", but it gets very ugly when trying to load inner classes and maybe in some other situations I can't even think about.
  2. Reading the class data should probably belong to some utility readAll method because it looks very messy.
  3. Obviously this needs a non-anonymous class with both WAR name and inner JAR name passed to the constructor. Or ZipFile and ZipEntry, if you want to iterate over those externally.

On the positive side, it works.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Build classpath from JAR inside a WAR file

From Dev

How to get a jar file from classpath?

From Dev

File list from classpath directory in running jar

From Dev

How to access a .jar present inside of a .war from some other .war?

From Dev

Run JAVA war file from command line with classpath to start API

From Dev

Gradle build file with conf folder with properties not in jar but on classpath

From Dev

Maven configuration: pass file inside a classpath jar as an argument

From Dev

spring boot maven how to build both war and jar file

From Dev

Compiling Java source file using classpath from generated jar file

From Dev

"-includeresource" in JAR Manifest inside Gradle build file

From Dev

Java : How to add jar file to build, using build.xml or project's .classpath file?

From Java

Run a JAR file from the command line and specify classpath

From Dev

Importing Spring properties files from jar file on classpath

From Dev

May jar-file with annotations be excluded from the classpath?

From Dev

Set jar file to remove lib from classpath using NetBeans

From Dev

Set jar file to remove lib from classpath using NetBeans

From Dev

May jar-file with annotations be excluded from the classpath?

From Dev

Set classpath to include .jar file

From Dev

Copy resources from a dependency jar or war file in Gradle

From Dev

Unable to load BeanIO mapping from JAR file in WAR application

From Dev

Read property file resides in /ear/war from ear/lib/*.jar

From Dev

Running an ANT build.xml file inside a Jar file

From Dev

Running an ANT build.xml file inside a Jar file

From Dev

Issue unmarshalling object from file inside jar

From Dev

Execute jar file from inside a Java program

From Dev

How to create a jar file from an eclipse java project that uses *.jar files added in "Classpath"

From Dev

How to create a jar file from an eclipse java project that uses *.jar files added in "Classpath"

From Dev

Jar dependency - Application server classpath vs adding it to the application war itself

From Dev

Accessing File from ClassPath

Related Related

  1. 1

    Build classpath from JAR inside a WAR file

  2. 2

    How to get a jar file from classpath?

  3. 3

    File list from classpath directory in running jar

  4. 4

    How to access a .jar present inside of a .war from some other .war?

  5. 5

    Run JAVA war file from command line with classpath to start API

  6. 6

    Gradle build file with conf folder with properties not in jar but on classpath

  7. 7

    Maven configuration: pass file inside a classpath jar as an argument

  8. 8

    spring boot maven how to build both war and jar file

  9. 9

    Compiling Java source file using classpath from generated jar file

  10. 10

    "-includeresource" in JAR Manifest inside Gradle build file

  11. 11

    Java : How to add jar file to build, using build.xml or project's .classpath file?

  12. 12

    Run a JAR file from the command line and specify classpath

  13. 13

    Importing Spring properties files from jar file on classpath

  14. 14

    May jar-file with annotations be excluded from the classpath?

  15. 15

    Set jar file to remove lib from classpath using NetBeans

  16. 16

    Set jar file to remove lib from classpath using NetBeans

  17. 17

    May jar-file with annotations be excluded from the classpath?

  18. 18

    Set classpath to include .jar file

  19. 19

    Copy resources from a dependency jar or war file in Gradle

  20. 20

    Unable to load BeanIO mapping from JAR file in WAR application

  21. 21

    Read property file resides in /ear/war from ear/lib/*.jar

  22. 22

    Running an ANT build.xml file inside a Jar file

  23. 23

    Running an ANT build.xml file inside a Jar file

  24. 24

    Issue unmarshalling object from file inside jar

  25. 25

    Execute jar file from inside a Java program

  26. 26

    How to create a jar file from an eclipse java project that uses *.jar files added in "Classpath"

  27. 27

    How to create a jar file from an eclipse java project that uses *.jar files added in "Classpath"

  28. 28

    Jar dependency - Application server classpath vs adding it to the application war itself

  29. 29

    Accessing File from ClassPath

HotTag

Archive