/*
* Copyright 2013. Guidewire Software, Inc.
*/
package gw.lang.reflect.java.asm;
import gw.lang.reflect.TypeSystem;
import gw.util.cache.FqnCache;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
*/
public class AsmClassLoader {
private static final Map<Object, AsmClassLoader> CACHE_BY_MOD = new HashMap<Object, AsmClassLoader>();
private Object _module;
private FqnCache<AsmClass> _cache;
public static AsmClass loadClass( Object module, String fqn, InputStream is ) {
AsmClassLoader loader = getAsmClassLoader( module );
return loader.findClass( fqn, is );
}
private static AsmClassLoader getAsmClassLoader( Object module ) {
AsmClassLoader loader = CACHE_BY_MOD.get( module );
if( loader == null ) {
TypeSystem.lock();
try {
loader = CACHE_BY_MOD.get( module );
if( loader == null ) {
CACHE_BY_MOD.put( module, loader = new AsmClassLoader( module ) );
}
}
finally {
TypeSystem.unlock();
}
}
return loader;
}
private AsmClassLoader( Object module ) {
_module = module;
_cache = new FqnCache<AsmClass>();
}
private AsmClass findClass( String fqn, InputStream is ) {
AsmClass asmClass = _cache.get( fqn );
if( asmClass == null ) {
asmClass = _cache.get( fqn );
if( asmClass == null ) {
asmClass = new AsmClass( _module, getContent( is ) );
_cache.add( fqn, asmClass );
}
}
return asmClass;
}
private static byte[] getContent( InputStream is ) {
byte[] buf = new byte[1024];
ExposedByteArrayOutputStream out = new ExposedByteArrayOutputStream();
while( true ) {
int count = 0;
try {
count = is.read( buf );
}
catch( IOException e ) {
throw new RuntimeException( e );
}
if( count < 0 ) {
break;
}
out.write( buf, 0, count );
}
try {
out.flush();
is.close();
return out.getByteArray();
}
catch( Exception e ) {
throw new RuntimeException( e );
}
}
public static class ExposedByteArrayOutputStream extends ByteArrayOutputStream {
public ExposedByteArrayOutputStream() {
super( 1024 );
}
public byte[] getByteArray() {
return buf;
}
}
}