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);
}
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)
{
// 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
{
File file = new File(rulesFile);
@ -156,7 +125,7 @@ public class AccessTransformer implements IClassTransformer
processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8));
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>()
{

View File

@ -1,34 +1,71 @@
package cpw.mods.fml.common.asm.transformers;
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 com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
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 List<AccessTransformer> embedded = Lists.newArrayList();
public ModAccessTransformer() throws IOException
private static Map<String, String> embedded = Maps.newHashMap(); //Needs to be primitive so that both classloaders get the same class.
public ModAccessTransformer() throws Exception
{
super(ModAccessTransformer.class);
for (AccessTransformer at : embedded)
{
mergeModifiers(at.getModifiers());
}
}
//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);
private void mergeModifiers(Multimap<String, Modifier> modifiers)
{
getModifiers().putAll(modifiers);
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
{
AccessTransformer at = new AccessTransformer(jar);
if (!at.isEmpty())
Manifest manifest = jar.getManifest();
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);
}
}
}