package cpw.mods.fml.common.asm.transformers;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;
import cpw.mods.fml.relauncher.FMLRelaunchLog;
public class ModAccessTransformer extends AccessTransformer {
private static Map<String, String> embedded = Maps.newHashMap(); //Needs to be primitive so that both classloaders get the same class.
@SuppressWarnings("unchecked")
public ModAccessTransformer() throws Exception
{
super(ModAccessTransformer.class);
//We are in the new ClassLoader here, so we need to get the static field from the other ClassLoader.
ClassLoader classLoader = this.getClass().getClassLoader().getClass().getClassLoader(); //Bit odd but it gets the class loader that loaded our current class loader yay java!
Class<?> otherClazz = Class.forName(this.getClass().getName(), true, classLoader);
Field otherField = otherClazz.getDeclaredField("embedded");
otherField.setAccessible(true);
embedded = (Map<String, String>)otherField.get(null);
for (Map.Entry<String, String> e : embedded.entrySet())
{
int old_count = getModifiers().size();
processATFile(CharSource.wrap(e.getValue()));
int added = getModifiers().size() - old_count;
if (added > 0)
{
FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer mod jar file %s\n", added, e.getKey());
}
}
}
public static void addJar(JarFile jar) throws IOException
{
Manifest manifest = jar.getManifest();
String atList = manifest.getMainAttributes().getValue("FMLAT");
if (atList == null) return;
for (String at : atList.split(" "))
{
JarEntry jarEntry = jar.getJarEntry("META-INF/"+at);
if (jarEntry != null)
{
embedded.put(String.format("%s!META-INF/%s", jar.getName(), at),
new JarByteSource(jar,jarEntry).asCharSource(Charsets.UTF_8).read());
}
}
}
private static class JarByteSource extends ByteSource
{
private JarFile jar;
private JarEntry entry;
public JarByteSource(JarFile jar, JarEntry entry)
{
this.jar = jar;
this.entry = entry;
}
@Override
public InputStream openStream() throws IOException
{
return jar.getInputStream(entry);
}
}
}