diff options
-rw-r--r-- | src/delombok/lombok/delombok/DelombokApp.java | 86 |
1 files changed, 83 insertions, 3 deletions
diff --git a/src/delombok/lombok/delombok/DelombokApp.java b/src/delombok/lombok/delombok/DelombokApp.java index e1b7604f..199534e4 100644 --- a/src/delombok/lombok/delombok/DelombokApp.java +++ b/src/delombok/lombok/delombok/DelombokApp.java @@ -1,9 +1,15 @@ package lombok.delombok; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import lombok.core.LombokApp; @@ -18,13 +24,87 @@ public class DelombokApp implements LombokApp { return 0; } catch (ClassNotFoundException e) { //tools.jar is probably not on the classpath. We're going to try and find it, and then load the rest via a ClassLoader that includes tools.jar. - File toolsJar = findToolsJar(); + final File toolsJar = findToolsJar(); if (toolsJar == null) { System.err.println("Can't find tools.jar. Rerun delombok with tools.jar on the classpath."); return 1; } - URLClassLoader loader = new URLClassLoader(new URL[] {toolsJar.toURI().toURL()}); + final JarFile toolsJarFile = new JarFile(toolsJar); + + ClassLoader loader = new ClassLoader() { + private Class<?>loadStreamAsClass(String name, boolean resolve, InputStream in) throws ClassNotFoundException { + try { + try { + byte[] b = new byte[65536]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + while (true) { + int r = in.read(b); + if (r == -1) break; + out.write(b, 0, r); + } + in.close(); + byte[] data = out.toByteArray(); + Class<?> c = defineClass(name, data, 0, data.length); + if (resolve) resolveClass(c); + return c; + } finally { + in.close(); + } + } catch (IOException e2) { + throw new ClassNotFoundException(name, e2); + } + } + + @Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + String rawName = name.replace(".", "/") + ".class"; + JarEntry entry = toolsJarFile.getJarEntry(rawName); + if (entry == null) { + if (name.startsWith("lombok.")) return loadStreamAsClass(name, resolve, super.getResourceAsStream(rawName)); + return super.loadClass(name, resolve); + } + + try { + return loadStreamAsClass(name, resolve, toolsJarFile.getInputStream(entry)); + } catch (IOException e2) { + throw new ClassNotFoundException(name, e2); + } + } + + @Override public URL getResource(String name) { + JarEntry entry = toolsJarFile.getJarEntry(name); + if (entry == null) return super.getResource(name); + try { + return new URL("jar:file:" + toolsJar.getAbsolutePath() + "!" + name); + } catch (MalformedURLException ignore) { + return null; + } + } + + @Override public Enumeration<URL> getResources(final String name) throws IOException { + JarEntry entry = toolsJarFile.getJarEntry(name); + final Enumeration<URL> parent = super.getResources(name); + if (entry == null) return super.getResources(name); + return new Enumeration<URL>() { + private boolean first = false; + @Override public boolean hasMoreElements() { + return !first || parent.hasMoreElements(); + } + + @Override public URL nextElement() { + if (!first) { + first = true; + try { + return new URL("jar:file:" + toolsJar.getAbsolutePath() + "!" + name); + } catch (MalformedURLException ignore) { + return parent.nextElement(); + } + } + return parent.nextElement(); + } + }; + } + }; try { loader.loadClass("lombok.delombok.Delombok").getMethod("main", String[].class).invoke(null, new Object[] {args}); } catch (InvocationTargetException e1) { |