@@ -0,0 +1,3285 @@
+package io.github.deathcap.bukkit2sponge.plugin;%0A%0Aimport com.google.common.io.ByteStreams;%0Aimport net.md_5.specialsource.Jar;%0Aimport net.md_5.specialsource.JarMapping;%0Aimport net.md_5.specialsource.JarRemapper;%0Aimport net.md_5.specialsource.SpecialSource;%0Aimport net.md_5.specialsource.repo.ClassRepo;%0Aimport net.md_5.specialsource.repo.JarRepo;%0Aimport org.objectweb.asm.tree.ClassNode;%0A%0Aimport java.io.File;%0Aimport java.io.IOException;%0Aimport java.io.InputStream;%0Aimport java.net.JarURLConnection;%0Aimport java.net.URL;%0Aimport java.net.URLClassLoader;%0Aimport java.security.CodeSigner;%0Aimport java.security.CodeSource;%0A%0Apublic class ShinyClassLoader extends URLClassLoader %7B%0A%0A    private JarMapping jarMapping;%0A    private JarRemapper jarRemapper;%0A    private ClassRepo classRepo;%0A%0A    public ShinyClassLoader(URL%5B%5D urls, ClassLoader parent) throws IOException %7B%0A        super(urls, parent);%0A%0A        this.jarMapping = new JarMapping();%0A%0A        // Relocate Guava in loaded plugins to match our relocated bundled version, which is%0A        // guaranteed to be Guava 17 unlike the server platform's Guava (old versions are 10)%0A        this.jarMapping.packages.put(%22com/google/common%22, %22io/github/deathcap/bukkit2sponge/libs/guava17/com/google/common%22);%0A%0A        this.jarRemapper = new JarRemapper(this.jarMapping);%0A%0A        File file = new File(urls%5B0%5D.getFile());%0A        Jar jar = Jar.init(file);%0A        //this.classRepo = new NullClassRepo();%0A        this.classRepo = new JarRepo(jar);%0A%0A        System.out.println(%22ShinyClassLoader init%22);%0A    %7D%0A%0A    @Override%0A    protected Class%3C?%3E findClass(String name) throws ClassNotFoundException %7B%0A        System.out.println(%22findClass: %22 + name);%0A%0A        String path = name.replace('.', '/').concat(%22.class%22);%0A        URL url = this.findResource(path);%0A        if (url == null) %7B%0A            throw new ClassNotFoundException(%22Unable to find class resource %22 + name + %22 at %22 + path);%0A        %7D%0A%0A        InputStream stream = null;%0A        byte%5B%5D bytecode = null;%0A        try %7B%0A            stream = url.openStream();%0A            bytecode = ByteStreams.toByteArray(stream);%0A        %7D catch (IOException ex) %7B%0A            ex.printStackTrace();%0A            throw new ClassNotFoundException(%22Unable to open or read stream for class %22 + name + %22: %22 + ex.getLocalizedMessage());%0A        %7D%0A%0A        CodeSource codeSource = null;%0A        try %7B%0A            JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();%0A            URL jarURL = jarURLConnection.getJarFileURL();%0A            codeSource = new CodeSource(jarURL, new CodeSigner%5B0%5D);%0A        %7D catch (IOException ex) %7B%0A            ex.printStackTrace();%0A            throw new ClassNotFoundException(%22Unable to read code source for class %22 + name + %22: %22 + ex.getLocalizedMessage());%0A        %7D%0A%0A        byte%5B%5D remappedBytecode = this.jarRemapper.remapClassFile(bytecode, this.classRepo);%0A%0A        Class%3C?%3E result = this.defineClass(name, remappedBytecode, 0, remappedBytecode.length, codeSource);%0A        if (result != null) %7B%0A            this.resolveClass(result);%0A        %7D%0A%0A        return result;%0A    %7D%0A%0A    private class NullClassRepo implements ClassRepo %7B%0A        @Override%0A        public final ClassNode findClass(String name) %7B%0A            return null;%0A        %7D%0A    %7D%0A%7D%0A

Add custom classloader using SpecialSource