Fix FMLAT manifest AccessTransformers, class loader fun! Closes #477

This commit is contained in:
Lex Manos 2014-07-16 00:24:03 -07:00
parent 59c628f777
commit 4ed75fd963
2 changed files with 54 additions and 48 deletions

View file

@ -106,41 +106,10 @@ public class AccessTransformer implements IClassTransformer
readMapFile(rulesFile); readMapFile(rulesFile);
} }
AccessTransformer(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)
{
processATFile(new JarByteSource(jar,jarEntry).asCharSource(Charsets.UTF_8));
}
}
FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer mod jar file %s\n", modifiers.size(), jar.getName());
}
AccessTransformer(Class<? extends AccessTransformer> dummyClazz) AccessTransformer(Class<? extends AccessTransformer> dummyClazz)
{ {
// This is a noop // This is a noop
} }
private 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);
}
}
void readMapFile(String rulesFile) throws IOException void readMapFile(String rulesFile) throws IOException
{ {
File file = new File(rulesFile); File file = new File(rulesFile);
@ -156,7 +125,7 @@ public class AccessTransformer implements IClassTransformer
processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8)); processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8));
FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile); FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile);
} }
private void processATFile(CharSource rulesResource) throws IOException protected void processATFile(CharSource rulesResource) throws IOException
{ {
rulesResource.readLines(new LineProcessor<Void>() rulesResource.readLines(new LineProcessor<Void>()
{ {

View file

@ -1,34 +1,71 @@
package cpw.mods.fml.common.asm.transformers; package cpw.mods.fml.common.asm.transformers;
import java.io.IOException; import java.io.IOException;
import java.util.List; 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.JarFile;
import com.google.common.collect.Lists; import java.util.jar.Manifest;
import com.google.common.collect.Multimap; 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 { public class ModAccessTransformer extends AccessTransformer {
private static List<AccessTransformer> embedded = Lists.newArrayList(); private static Map<String, String> embedded = Maps.newHashMap(); //Needs to be primitive so that both classloaders get the same class.
public ModAccessTransformer() throws IOException public ModAccessTransformer() throws Exception
{ {
super(ModAccessTransformer.class); super(ModAccessTransformer.class);
for (AccessTransformer at : embedded) //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!
mergeModifiers(at.getModifiers()); Class<?> otherClazz = Class.forName(this.getClass().getName(), true, classLoader);
} Field otherField = otherClazz.getDeclaredField("embedded");
} otherField.setAccessible(true);
embedded = (Map<String, String>)otherField.get(null);
private void mergeModifiers(Multimap<String, Modifier> modifiers) for (Map.Entry<String, String> e : embedded.entrySet())
{ {
getModifiers().putAll(modifiers); 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 public static void addJar(JarFile jar) throws IOException
{ {
AccessTransformer at = new AccessTransformer(jar); Manifest manifest = jar.getManifest();
if (!at.isEmpty()) String atList = manifest.getMainAttributes().getValue("FMLAT");
if (atList == null) return;
for (String at : atList.split(" "))
{ {
embedded.add(at); 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);
}
}
} }