diff options
Diffstat (limited to 'src')
4 files changed, 43 insertions, 21 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java index b1327216..ea72f56a 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java @@ -26,6 +26,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.jar.JarFile; import java.util.zip.ZipEntry; @@ -92,14 +93,15 @@ public class EclipseLoaderPatcherTransplants { jf.close(); } } - Class[] paramTypes = new Class[4]; + Class[] paramTypes = new Class[5]; paramTypes[0] = classLoaderClass; paramTypes[1] = "".getClass(); paramTypes[2] = paramTypes[1]; - paramTypes[3] = new String[0].getClass(); + paramTypes[3] = Class.forName("java.util.List"); + paramTypes[4] = paramTypes[3]; Constructor constructor = shadowClassLoaderClass.getDeclaredConstructor(paramTypes); constructor.setAccessible(true); - shadowLoader = (ClassLoader) constructor.newInstance(new Object[] {original, "lombok", jarLoc, new String[] {"lombok."}}); + shadowLoader = (ClassLoader) constructor.newInstance(new Object[] {original, "lombok", jarLoc, Arrays.asList(new Object[] {"lombok."}), Arrays.asList(new Object[] {"lombok.patcher.Symbols"})}); shadowLoaderField.set(original, shadowLoader); } } diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 28e8d0c1..6e5871e6 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -75,8 +75,9 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable { ScriptManager sm = new ScriptManager(); sm.registerTransformer(instrumentation); sm.setTransplantMapper(new TransplantMapper() { - public String getPrefixFor(int classFileFormatVersion) { - return classFileFormatVersion > 49 ? "Class50/" : ""; + public String mapResourceName(int classFileFormatVersion, String resourceName) { + if (classFileFormatVersion < 50) return resourceName; + return "Class50/" + resourceName; } }); diff --git a/src/launch/lombok/launch/Main.java b/src/launch/lombok/launch/Main.java index 63d97d48..b81b6268 100644 --- a/src/launch/lombok/launch/Main.java +++ b/src/launch/lombok/launch/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-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 @@ -22,10 +22,11 @@ package lombok.launch; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; class Main { static ClassLoader createShadowClassLoader() { - return new ShadowClassLoader(Main.class.getClassLoader(), "lombok"); + return new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.<String>asList(), Arrays.asList("lombok.patcher.Symbols")); } public static void main(String[] args) throws Throwable { diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java index 8cfd5e39..83f64370 100644 --- a/src/launch/lombok/launch/ShadowClassLoader.java +++ b/src/launch/lombok/launch/ShadowClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-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 @@ -37,6 +37,8 @@ import java.util.List; import java.util.Map; import java.util.Vector; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -79,7 +81,7 @@ import java.util.jar.JarFile; */ class ShadowClassLoader extends ClassLoader { private static final String SELF_NAME = "lombok/launch/ShadowClassLoader.class"; - private volatile static Class<?> lombokPatcherSymbols; + private static final ConcurrentMap<String, Class<?>> highlanderMap = new ConcurrentHashMap<String, Class<?>>(); private final String SELF_BASE; private final File SELF_BASE_FILE; @@ -88,21 +90,16 @@ class ShadowClassLoader extends ClassLoader { private final List<File> override = new ArrayList<File>(); private final String sclSuffix; private final List<String> parentExclusion = new ArrayList<String>(); - - /** - * Calls the {@link ShadowClassLoader(ClassLoader, String, String, String[]) constructor with no exclusions and the source of this class as base. - */ - ShadowClassLoader(ClassLoader source, String sclSuffix) { - this(source, sclSuffix, null); - } + private final List<String> highlanders = new ArrayList<String>(); /** * @param source The 'parent' classloader. * @param sclSuffix The suffix of the shadowed class files in our own jar. For example, if this is {@code lombok}, then the class files in your jar should be {@code foo/Bar.SCL.lombok} and not {@code foo/Bar.class}. * @param selfBase The (preferably absolute) path to our own jar. This jar will be searched for class/SCL.sclSuffix files. * @param parentExclusion For example {@code "lombok."}; upon invocation of loadClass of this loader, the parent loader ({@code source}) will NOT be invoked if the class to be loaded begins with anything in the parent exclusion list. No exclusion is applied for getResource(s). + * @param highlanders SCL will put in extra effort to ensure that these classes (in simple class spec, so {@code foo.bar.baz.ClassName}) are only loaded once as a class, even if many different classloaders try to load classes, such as equinox/OSGi. */ - ShadowClassLoader(ClassLoader source, String sclSuffix, String selfBase, String... parentExclusion) { + ShadowClassLoader(ClassLoader source, String sclSuffix, String selfBase, List<String> parentExclusion, List<String> highlanders) { super(source); this.sclSuffix = sclSuffix; if (parentExclusion != null) for (String pe : parentExclusion) { @@ -110,6 +107,9 @@ class ShadowClassLoader extends ClassLoader { if (!pe.endsWith("/")) pe = pe + "/"; this.parentExclusion.add(pe); } + if (highlanders != null) for (String hl : highlanders) { + this.highlanders.add(hl); + } if (selfBase != null) { SELF_BASE = selfBase; @@ -362,8 +362,12 @@ class ShadowClassLoader extends ClassLoader { if (alreadyLoaded != null) return alreadyLoaded; } - if (lombokPatcherSymbols != null && name.equals("lombok.patcher.Symbols")) return lombokPatcherSymbols; - String fileNameOfClass = name.replace(".", "/") + ".class"; + if (highlanders.contains(name)) { + Class<?> c = highlanderMap.get(name); + if (c != null) return c; + } + + String fileNameOfClass = name.replace(".", "/") + ".class"; URL res = getResource_(fileNameOfClass, true); if (res == null) { if (!exclusionListMatch(fileNameOfClass)) return super.loadClass(name, resolve); @@ -394,8 +398,22 @@ class ShadowClassLoader extends ClassLoader { throw new ClassNotFoundException("I/O exception reading class " + name, e); } - Class<?> c = defineClass(name, b, 0, p); - if (name.equals("lombok.patcher.Symbols")) lombokPatcherSymbols = c; + Class<?> c; + try { + c = defineClass(name, b, 0, p); + } catch (LinkageError e) { + if (highlanders.contains(name)) { + Class<?> alreadyDefined = highlanderMap.get(name); + if (alreadyDefined != null) return alreadyDefined; + } + throw e; + } + + if (highlanders.contains(name)) { + Class<?> alreadyDefined = highlanderMap.putIfAbsent(name, c); + if (alreadyDefined != null) c = alreadyDefined; + } + if (resolve) resolveClass(c); return c; } |