blob: 79973bba0d94077d18bdd4ae8541b5b8cd3d39b7 [file] [log] [blame] [raw]
package net.glowstone.util.linkstone;
import net.glowstone.linkstone.runtime.LinkstoneRuntimeData;
import net.glowstone.linkstone.runtime.boxing.BoxPatchVisitor;
import net.glowstone.linkstone.runtime.direct.DirectFieldAccessReplaceVisitor;
import net.glowstone.linkstone.runtime.inithook.ClassInitInvokeVisitor;
import net.glowstone.linkstone.runtime.reflectionredirect.field.FieldAccessorUtility;
import net.glowstone.linkstone.runtime.reflectionredirect.method.MethodAccessorUtility;
import net.glowstone.linkstone.runtime.reflectionreplace.ReflectionReplaceVisitor;
import org.bukkit.Server;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.bukkit.plugin.java.PluginClassLoader;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import java.io.File;
public class LinkstonePluginLoader extends JavaPluginLoader {
/**
* Bukkit will invoke this constructor via reflection.
* Its signature should therefore not be changed!
*
* @param instance the server instance
*/
public LinkstonePluginLoader(Server instance) {
super(instance);
LinkstoneRuntimeData.setPluginClassLoader(new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return getClassByName(name);
}
});
}
@Override
protected PluginClassLoader newPluginLoader(JavaPluginLoader loader, ClassLoader parent,
PluginDescriptionFile description, File dataFolder, File file) throws Exception {
return new PluginClassLoader(loader, parent, description, dataFolder, file) {
@Override
protected byte[] transformBytecode(byte[] bytecode) {
if (LinkstoneRuntimeData.getFields().isEmpty()
&& LinkstoneRuntimeData.getBoxes().isEmpty()) {
// There are no plugins installed that use a @LField or @LBox annotation
// so there's no need for runtime support
return bytecode;
}
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = cw;
cv = new DirectFieldAccessReplaceVisitor(LinkstoneRuntimeData.getFields(), cv);
if (!FieldAccessorUtility.isSupported() || !MethodAccessorUtility.isSupported()) {
cv = new ReflectionReplaceVisitor(cv);
}
cv = new ClassInitInvokeVisitor(cv);
cv = new BoxPatchVisitor(LinkstoneRuntimeData.getBoxes(), cv);
new ClassReader(bytecode).accept(cv, 0);
return cw.toByteArray();
}
};
}
}