czwartek, października 17, 2013

NestedJarClassLoader

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


public class NestedJarClassLoader extends URLClassLoader {

private HashMap jarCache = new HashMap();

@Override
public InputStream getResourceAsStream(String s) {
byte[] data = jarCache.get(s);
if (data==null)
data = jarCache.get("/"+s);
return (data!=null) ? new ByteArrayInputStream(data) : null;
}

@Override
public URL findResource(String name) {
return null; // not supported
}

@Override
public Class loadClass(String s) throws ClassNotFoundException {
byte[] bc = jarCache.get(s+".class");
if (bc!=null)
return super.defineClass(s, bc, 0, bc.length);
return super.loadClass(s);
}

public NestedJarClassLoader(URL url) throws Exception {
super(new URL[] {}, NestedJarClassLoader.class.getClassLoader());
String sURL = url.toString();
String u = url.toString().substring(4);
String name = new File(u.substring(9)).getName();
URL firstJarUrl = new URL(sURL.substring(0, sURL.lastIndexOf("/")+1));
JarFile jf = ((JarURLConnection)firstJarUrl.openConnection()).getJarFile();
InputStream is = jf.getInputStream(jf.getEntry(name));
byte[] binaryJar = new byte[is.available()];
/* read through compressed stream is tricky */
int n = 0;
int cnt = 0;
do {
n = is.read(binaryJar, cnt, binaryJar.length - cnt);
if (n>0)
cnt += n;
}
while (n > 0);
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(binaryJar));
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
byte[] buff = new byte[4096];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int s = 0;
do {
s = zis.read(buff);
if (s>0)
baos.write(buff, 0, s);
}
while (s > 0);
if (baos.size() > 0 && ze.getName() != null) {
jarCache.put(ze.getName(), baos.toByteArray());
if (ze.getName().endsWith(".class")) {
String className = ze.getName().replace('$', '.').replace('/', '.');
jarCache.put(className, baos.toByteArray());
}
}
}
}

public static void main(String[] args) throws Exception {
URL url = new URL("jar:file:C://tibco/bw/5.10/hotfix/lib/tibcoverage.jar!/tdi.jar");
NestedJarClassLoader ucl = new NestedJarClassLoader(url);
ucl.loadClass("tdi.com.tibco.pe.Logger");
}
}

0 komentarze: