mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 04:16:19 +00:00
[shadowloader] Fix for lombok v1.16.0 no longer working in eclipses that use -target 1.4 style class files (such as eclipse indigo). It’s a doozy.
This commit is contained in:
1 parent
fd12196eea
commit
65de4693eb
5 files changed
+160
-67
No files matched your search
@@ -173,6 +173,23 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
<fileset dir="build/lombok-utils" />
|
||||
</copy>
|
||||
|
||||
<mkdir dir="build/transformedSources" />
|
||||
<copy todir="build/transformedSources">
|
||||
<fileset dir="src/eclipseAgent">
|
||||
<include name="**/*Transplants.java" />
|
||||
</fileset>
|
||||
<filterchain>
|
||||
<lineContainsRegExp negate="true">
|
||||
<regexp pattern="^\s*@SuppressWarnings.*$" />
|
||||
</lineContainsRegExp>
|
||||
</filterchain>
|
||||
</copy>
|
||||
|
||||
<ivy:compile destdir="build/lombok" source="1.4" target="1.4" includeantruntime="false">
|
||||
<compilerarg value="-Xbootclasspath/p:build/stubs${path.separator}lib/openJDK6Environment/rt-openjdk6.jar" />
|
||||
<src path="build/transformedSources" />
|
||||
</ivy:compile>
|
||||
|
||||
<ivy:compile destdir="build/lombok" source="1.5" target="1.5" includeantruntime="false">
|
||||
<compilerarg value="-Xbootclasspath/p:build/stubs${path.separator}lib/openJDK6Environment/rt-openjdk6.jar" />
|
||||
<src path="src/launch" />
|
||||
@@ -180,6 +197,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
<src path="src/installer" />
|
||||
<src path="src/eclipseAgent" />
|
||||
<exclude name="lombok/javac/**" />
|
||||
<exclude name="**/*Transplants.java" />
|
||||
<classpath location="build/lombok" />
|
||||
<classpath refid="build.path" />
|
||||
</ivy:compile>
|
||||
|
||||
@@ -7,6 +7,7 @@ Lombok Changelog
|
||||
* BUGFIX: The ant `delombok` task was broken starting with v1.16.0. Note that the task def class has been changed; taskdef `lombok.delombok.ant.Tasks$Delombok` instead of the old `lombok.delombok.ant.DelombokTask`. [Issue #775](https://code.google.com/p/projectlombok/issues/detail?id=775).
|
||||
* BUGFIX: `val` in javac would occasionally fail if used inside inner classes. This is (probably) fixed. [Issue #694](https://code.google.com/p/projectlombok/issues/detail?id=694).
|
||||
* BUGFIX: Starting with v1.16.0, lombok would fail to execute as an executable jar if it was in a path was spaced in it. [Issue #777](https://code.google.com/p/projectlombok/issues/detail?id=777).
|
||||
* BUGFIX: v1.16.0 did not work in old eclipse versions (such as eclipse indigo).
|
||||
|
||||
### v1.16.0 "Candid Duck" (January 26th, 2015)
|
||||
* BUGFIX: `@ExtensionMethod` was broken in Eclipse using java 8. [Issue #742](https://code.google.com/p/projectlombok/issues/detail?id=742), [Issue #747](https://code.google.com/p/projectlombok/issues/detail?id=747)
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.eclipse.agent;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import lombok.patcher.ClassRootFinder;
|
||||
import lombok.patcher.Hook;
|
||||
import lombok.patcher.MethodTarget;
|
||||
@@ -16,62 +29,7 @@ import lombok.patcher.StackRequest;
|
||||
import lombok.patcher.scripts.ScriptBuilder;
|
||||
|
||||
public class EclipseLoaderPatcher {
|
||||
public static boolean overrideLoadDecide(ClassLoader original, String name, boolean resolve) {
|
||||
return name.startsWith("lombok.");
|
||||
}
|
||||
|
||||
public static Class<?> overrideLoadResult(ClassLoader original, String name, boolean resolve) throws ClassNotFoundException {
|
||||
try {
|
||||
Field shadowLoaderField = original.getClass().getField("lombok$shadowLoader");
|
||||
ClassLoader shadowLoader = (ClassLoader) shadowLoaderField.get(original);
|
||||
if (shadowLoader == null) {
|
||||
String jarLoc = (String) original.getClass().getField("lombok$location").get(null);
|
||||
JarFile jf = new JarFile(jarLoc);
|
||||
InputStream in = null;
|
||||
try {
|
||||
ZipEntry entry = jf.getEntry("lombok/launch/ShadowClassLoader.class");
|
||||
in = jf.getInputStream(entry);
|
||||
byte[] bytes = new byte[65536];
|
||||
int len = 0;
|
||||
while (true) {
|
||||
int r = in.read(bytes, len, bytes.length - len);
|
||||
if (r == -1) break;
|
||||
len += r;
|
||||
if (len == bytes.length) throw new IllegalStateException("lombok.launch.ShadowClassLoader too large.");
|
||||
}
|
||||
in.close();
|
||||
Class<?> shadowClassLoaderClass; {
|
||||
Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
|
||||
defineClassMethod.setAccessible(true);
|
||||
shadowClassLoaderClass = (Class<?>) defineClassMethod.invoke(original, "lombok.launch.ShadowClassLoader", bytes, 0, len);
|
||||
}
|
||||
Constructor<?> constructor = shadowClassLoaderClass.getDeclaredConstructor(ClassLoader.class, String.class, String.class, String[].class);
|
||||
constructor.setAccessible(true);
|
||||
shadowLoader = (ClassLoader) constructor.newInstance(original, "lombok", jarLoc, new String[] {"lombok."});
|
||||
shadowLoaderField.set(original, shadowLoader);
|
||||
} finally {
|
||||
if (in != null) in.close();
|
||||
jf.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (resolve) {
|
||||
Method m = shadowLoader.getClass().getDeclaredMethod("loadClass", String.class, boolean.class);
|
||||
m.setAccessible(true);
|
||||
return (Class<?>) m.invoke(shadowLoader, name, true);
|
||||
} else {
|
||||
return shadowLoader.loadClass(name);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Throwable t = ex;
|
||||
if (t instanceof InvocationTargetException) t = t.getCause();
|
||||
if (t instanceof RuntimeException) throw (RuntimeException) t;
|
||||
if (t instanceof Error) throw (Error) t;
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SELF_NAME = "lombok.eclipse.agent.EclipseLoaderPatcher";
|
||||
private static final String TRANSPLANTS_CLASS_NAME = "lombok.eclipse.agent.EclipseLoaderPatcherTransplants";
|
||||
|
||||
public static void patchEquinoxLoaders(ScriptManager sm, Class<?> launchingContext) {
|
||||
sm.addScript(ScriptBuilder.exitEarly()
|
||||
@@ -81,8 +39,8 @@ public class EclipseLoaderPatcher {
|
||||
"java.lang.Class", "java.lang.String", "boolean"))
|
||||
.target(new MethodTarget("org.eclipse.osgi.internal.loader.ModuleClassLoader", "loadClass",
|
||||
"java.lang.Class", "java.lang.String", "boolean"))
|
||||
.decisionMethod(new Hook(SELF_NAME, "overrideLoadDecide", "boolean", "java.lang.ClassLoader", "java.lang.String", "boolean"))
|
||||
.valueMethod(new Hook(SELF_NAME, "overrideLoadResult", "java.lang.Class", "java.lang.ClassLoader", "java.lang.String", "boolean"))
|
||||
.decisionMethod(new Hook(TRANSPLANTS_CLASS_NAME, "overrideLoadDecide", "boolean", "java.lang.ClassLoader", "java.lang.String", "boolean"))
|
||||
.valueMethod(new Hook(TRANSPLANTS_CLASS_NAME, "overrideLoadResult", "java.lang.Class", "java.lang.ClassLoader", "java.lang.String", "boolean"))
|
||||
.transplant()
|
||||
.request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.eclipse.agent;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* Contains all the code to be transplanted into eclipse.
|
||||
*
|
||||
* Do not use:
|
||||
*
|
||||
* * Annotations
|
||||
* * Generics
|
||||
* * Varargs
|
||||
* * Auto (un)boxing
|
||||
* * class literals
|
||||
*
|
||||
* The above because this code is compiled with -source 1.4, and is transplanted.
|
||||
*
|
||||
* NB: The suppress warnings will be stripped out before compilation.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class EclipseLoaderPatcherTransplants {
|
||||
public static boolean overrideLoadDecide(ClassLoader original, String name, boolean resolve) {
|
||||
return name.startsWith("lombok.");
|
||||
}
|
||||
|
||||
public static Class overrideLoadResult(ClassLoader original, String name, boolean resolve) throws ClassNotFoundException {
|
||||
try {
|
||||
Field shadowLoaderField = original.getClass().getField("lombok$shadowLoader");
|
||||
ClassLoader shadowLoader = (ClassLoader) shadowLoaderField.get(original);
|
||||
if (shadowLoader == null) {
|
||||
String jarLoc = (String) original.getClass().getField("lombok$location").get(null);
|
||||
JarFile jf = new JarFile(jarLoc);
|
||||
InputStream in = null;
|
||||
try {
|
||||
ZipEntry entry = jf.getEntry("lombok/launch/ShadowClassLoader.class");
|
||||
in = jf.getInputStream(entry);
|
||||
byte[] bytes = new byte[65536];
|
||||
int len = 0;
|
||||
while (true) {
|
||||
int r = in.read(bytes, len, bytes.length - len);
|
||||
if (r == -1) break;
|
||||
len += r;
|
||||
if (len == bytes.length) throw new IllegalStateException("lombok.launch.ShadowClassLoader too large.");
|
||||
}
|
||||
in.close();
|
||||
Class classLoaderClass = Class.forName("java.lang.ClassLoader");
|
||||
Class shadowClassLoaderClass; {
|
||||
Class[] paramTypes = new Class[4];
|
||||
paramTypes[0] = "".getClass();
|
||||
paramTypes[1] = new byte[0].getClass();
|
||||
paramTypes[2] = Integer.TYPE;
|
||||
paramTypes[3] = paramTypes[2];
|
||||
Method defineClassMethod = classLoaderClass.getDeclaredMethod("defineClass", paramTypes);
|
||||
defineClassMethod.setAccessible(true);
|
||||
shadowClassLoaderClass = (Class) defineClassMethod.invoke(original, new Object[] {"lombok.launch.ShadowClassLoader", bytes, new Integer(0), new Integer(len)});
|
||||
}
|
||||
Class[] paramTypes = new Class[4];
|
||||
paramTypes[0] = classLoaderClass;
|
||||
paramTypes[1] = "".getClass();
|
||||
paramTypes[2] = paramTypes[1];
|
||||
paramTypes[3] = new String[0].getClass();
|
||||
Constructor constructor = shadowClassLoaderClass.getDeclaredConstructor(paramTypes);
|
||||
constructor.setAccessible(true);
|
||||
shadowLoader = (ClassLoader) constructor.newInstance(new Object[] {original, "lombok", jarLoc, new String[] {"lombok."}});
|
||||
shadowLoaderField.set(original, shadowLoader);
|
||||
} finally {
|
||||
if (in != null) in.close();
|
||||
jf.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (resolve) {
|
||||
Class[] paramTypes = new Class[2];
|
||||
paramTypes[0] = "".getClass();
|
||||
paramTypes[1] = Boolean.TYPE;
|
||||
Method m = shadowLoader.getClass().getDeclaredMethod("loadClass", new Class[] {String.class, boolean.class});
|
||||
m.setAccessible(true);
|
||||
return (Class) m.invoke(shadowLoader, new Object[] {name, Boolean.TRUE});
|
||||
} else {
|
||||
return shadowLoader.loadClass(name);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Throwable t = ex;
|
||||
if (t instanceof InvocationTargetException) t = t.getCause();
|
||||
if (t instanceof RuntimeException) throw (RuntimeException) t;
|
||||
if (t instanceof Error) throw (Error) t;
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.core.AgentLauncher;
|
||||
|
||||
import lombok.patcher.Hook;
|
||||
import lombok.patcher.MethodTarget;
|
||||
import lombok.patcher.ScriptManager;
|
||||
|
||||
Reference in new issue
Block a user