diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-09 18:27:10 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-06-09 18:27:10 +0200 |
commit | 41fb7cba62b543243c784757d1af4e05824ddc4e (patch) | |
tree | b910a78f31576d08f7a95440edb8f630cf4164eb /src_eclipseagent/java/lombok/ClassLoaderWorkaround.java | |
parent | 525211b872b982b880aa2bed5e263ec582593f0d (diff) | |
download | lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.gz lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.bz2 lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.zip |
Many changes:
- Split off the actual agent work into a separate src package in preparation for creating separate jars. Involved a lot of renaming
- Renamed TransformCompilationUnitDeclaration to TransformEclipseAST, as this class will also be transforming e.g. MethodDeclaration objects.
- Expanded the patching to also patch in transform calls when the parser fills in the Statement array for existing constructors, methods, and initializers.
- Redesigned the ClassLoaderWorkaround class quite a bit.
- Positioning should not work correctly ('jump to method' should jump to the getter annotation).
(Apparently, Clinit objects are always fully parsed in the original run, so no need to patch anything there).
Diffstat (limited to 'src_eclipseagent/java/lombok/ClassLoaderWorkaround.java')
-rw-r--r-- | src_eclipseagent/java/lombok/ClassLoaderWorkaround.java | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java b/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java new file mode 100644 index 00000000..0238b592 --- /dev/null +++ b/src_eclipseagent/java/lombok/ClassLoaderWorkaround.java @@ -0,0 +1,104 @@ +package java.lombok; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; + +/** + * Allows you to inject the lombok classes into any classloader, even if that classloader does not + * know how to find the lombok classes. + * + * Example: Injecting lombok's Eclipse Parser patching code into eclipse's OSGi BundleLoader. + * + * @author rzwitserloot + */ +public class ClassLoaderWorkaround { + private static boolean initialized; + private static Method transformCompilationUnitDeclaration; + private static Method transformMethodDeclaration; + private static Method transformConstructorDeclaration; + private static Method transformInitializer; + + public static void transformCompilationUnitDeclaration(Object parser, Object cud) throws Exception { + initialize(cud); + transformCompilationUnitDeclaration.invoke(null, parser, cud); + } + + public static void transformMethodDeclaration(Object parser, Object methodDeclaration) throws Exception { + initialize(methodDeclaration); + transformMethodDeclaration.invoke(null, parser, methodDeclaration); + } + + public static void transformConstructorDeclaration(Object parser, Object constructorDeclaration) throws Exception { + initialize(constructorDeclaration); + transformConstructorDeclaration.invoke(null, parser, constructorDeclaration); + } + + public static void transformInitializer(Object parser, Object initializer) throws Exception { + initialize(initializer); + transformInitializer.invoke(null, parser, initializer); + } + + private static void initialize(Object cud) throws ClassNotFoundException { + if ( initialized ) { + if ( transformInitializer == null ) throw new ClassNotFoundException("lombok.eclipse.TransformEclipseAST"); + return; + } + + final ClassLoader parent = cud.getClass().getClassLoader(); + ClassLoader loader = new ClassLoader() { + @Override public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + if ( name.startsWith("lombok.") ) { + InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/") + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + byte[] b = new byte[65536]; + try { + while ( true ) { + int r = in.read(b); + if ( r == -1 ) break; + if ( r > 0 ) out.write(b, 0, r); + } + + in.close(); + byte[] data = out.toByteArray(); + Class<?> result = defineClass(name, data, 0, data.length); + if ( resolve ) resolveClass(result); + return result; + } catch ( IOException e ) { + throw new ClassNotFoundException(); + } + } else { + try { + Class<?> result = ClassLoader.getSystemClassLoader().loadClass(name); + if ( resolve ) resolveClass(result); + return result; + } catch ( ClassNotFoundException e ) { + Class<?> result = parent.loadClass(name); + if ( resolve ) resolveClass(result); + return result; + } + } + } + }; + + try { + Class<?> c = loader.loadClass("lombok.eclipse.TransformEclipseAST"); + for ( Method m : c.getMethods() ) { + if ( m.getName().equals("transform") ) { + if ( m.getParameterTypes().length >= 2 ) { + Class<?> astType = m.getParameterTypes()[1]; + String astName = astType.getName(); + astName = astName.substring(astName.lastIndexOf('.') + 1); + if ( astName.equals("CompilationUnitDeclaration") ) transformCompilationUnitDeclaration = m; + else if ( astName.equals("MethodDeclaration") ) transformMethodDeclaration = m; + else if ( astName.equals("ConstructorDeclaration") ) transformConstructorDeclaration = m; + else if ( astName.equals("Initializer") ) transformInitializer = m; + } + } + } + } catch ( ClassNotFoundException ignore ) {} + initialized = true; + } +} |