WarClassLoader – load your classes straight from a war
I was of need of a Java Class Loader that can load classes from within a war file.
It took me a bit to find this – in fact, I found it when I looked for ZipClassLoader (a war file is a zip with a specific folder structure). I found this post, and modified it to take the war folder structure into account:
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * Loads classes from war files. See http://www2.java.net/blog/2008/07/25/how-load-classes-jar-or-zip */ public final class WarClassLoader extends ClassLoader { private final ZipFile file; public WarClassLoader(String filename) throws IOException { this.file = new ZipFile(filename); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { ZipEntry entry = this.file.getEntry("WEB-INF/classes/" + name.replace('.', '/') + ".class"); if (entry == null) { throw new ClassNotFoundException(name); } try { byte[] array = new byte[1024]; InputStream in = this.file.getInputStream(entry); ByteArrayOutputStream out = new ByteArrayOutputStream(array.length); int length = in.read(array); while (length > 0) { out.write(array, 0, length); length = in.read(array); } return defineClass(name, out.toByteArray(), 0, out.size()); } catch (IOException exception) { throw new ClassNotFoundException(name, exception); } } } |
Two notes:
- This code isn’t really production grade, as the streams aren’t closed and whatnot
- It is missing one critical addition – if the classes in the war depend on the jars that are included within it, this class loader will not be able to load these classes. I managed to work around the problem because I already had all those jars in my classpath anyway, but in principle the code above needs a bit of extension to be able to work with the embedded jars.