diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2018-10-29 23:13:52 +0100 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2018-10-29 23:13:59 +0100 |
commit | eca219ee6433cd964f0549a114a791ca4eb9f0fa (patch) | |
tree | 20f6fed449504fbf5dbc52bd15ff3f2458dd90f8 /src/utils/lombok | |
parent | 182cb0cb9e8db6341fb4633c3849b5e90ba6d088 (diff) | |
download | lombok-eca219ee6433cd964f0549a114a791ca4eb9f0fa.tar.gz lombok-eca219ee6433cd964f0549a114a791ca4eb9f0fa.tar.bz2 lombok-eca219ee6433cd964f0549a114a791ca4eb9f0fa.zip |
eliminate ‘you are using private API’ warnings by streamlining all reflective access via a class that uses sun.misc.Unsafe to arrange access. From the nqzero permit-reflect library.
Diffstat (limited to 'src/utils/lombok')
-rw-r--r-- | src/utils/lombok/core/FieldAugment.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/javac/CommentCatcher.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/javac/Javac.java | 20 | ||||
-rw-r--r-- | src/utils/lombok/javac/JavacTreeMaker.java | 21 | ||||
-rw-r--r-- | src/utils/lombok/javac/PackageName.java | 4 | ||||
-rw-r--r-- | src/utils/lombok/javac/java6/CommentCollectingParserFactory.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/javac/java7/CommentCollectingParserFactory.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/javac/java8/CommentCollectingParserFactory.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/javac/java9/CommentCollectingParserFactory.java | 5 | ||||
-rw-r--r-- | src/utils/lombok/permit/Permit.java | 100 | ||||
-rw-r--r-- | src/utils/lombok/permit/package-info.java | 8 |
11 files changed, 149 insertions, 34 deletions
diff --git a/src/utils/lombok/core/FieldAugment.java b/src/utils/lombok/core/FieldAugment.java index ee8acf4d..4a32ad04 100644 --- a/src/utils/lombok/core/FieldAugment.java +++ b/src/utils/lombok/core/FieldAugment.java @@ -27,6 +27,8 @@ import java.lang.reflect.Modifier; import java.util.Map; import java.util.WeakHashMap; +import lombok.permit.Permit; + public abstract class FieldAugment<T, F> { private static Object getDefaultValue(Class<?> type) { if (type == boolean.class) return false; @@ -101,10 +103,9 @@ public abstract class FieldAugment<T, F> { private static Field findField(Class<?> type, Class<?> wantedType, String name) { try { - Field f = type.getDeclaredField(name); + Field f = Permit.getField(type, name); if (Modifier.isStatic(f.getModifiers()) || Modifier.isFinal(f.getModifiers())) return null; if (!typeIsAssignmentCompatible(f.getType(), wantedType)) return null; - f.setAccessible(true); return f; } catch (Exception e) { return null; diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java index afbd7b52..f8b73b0a 100644 --- a/src/utils/lombok/javac/CommentCatcher.java +++ b/src/utils/lombok/javac/CommentCatcher.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.List; import lombok.core.FieldAugment; +import lombok.permit.Permit; import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -79,7 +80,7 @@ public class CommentCatcher { } else { scannerFactory = Class.forName("lombok.javac.java8.CommentCollectingScannerFactory"); } - scannerFactory.getMethod("preRegister", Context.class).invoke(null, context); + Permit.getMethod(scannerFactory, "preRegister", Context.class).invoke(null, context); } catch (InvocationTargetException e) { throw Javac.sneakyThrow(e.getCause()); } catch (Exception e) { @@ -100,7 +101,7 @@ public class CommentCatcher { } else { parserFactory = Class.forName("lombok.javac.java9.CommentCollectingParserFactory"); } - parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class).invoke(null, compiler, context); + Permit.getMethod(parserFactory, "setInCompiler", JavaCompiler.class, Context.class).invoke(null, compiler, context); } catch (InvocationTargetException e) { throw Javac.sneakyThrow(e.getCause()); } catch (Exception e) { diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java index 92961726..a2cb32c6 100644 --- a/src/utils/lombok/javac/Javac.java +++ b/src/utils/lombok/javac/Javac.java @@ -40,6 +40,7 @@ import lombok.core.ClassLiteral; import lombok.core.FieldSelect; import lombok.javac.JavacTreeMaker.TreeTag; import lombok.javac.JavacTreeMaker.TypeTag; +import lombok.permit.Permit; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Symtab; @@ -199,7 +200,6 @@ public class Javac { static { getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]); - getExtendsClause.setAccessible(true); if (getJavaCompilerVersion() < 8) { getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", java.util.Map.class); @@ -214,11 +214,11 @@ public class Javac { throw sneakyThrow(ex); } try { - storeEndMethodTemp = endPosTable.getMethod("storeEnd", JCTree.class, int.class); + storeEndMethodTemp = Permit.getMethod(endPosTable, "storeEnd", JCTree.class, int.class); } catch (NoSuchMethodException e) { try { endPosTable = Class.forName("com.sun.tools.javac.parser.JavacParser$AbstractEndPosTable"); - storeEndMethodTemp = endPosTable.getDeclaredMethod("storeEnd", JCTree.class, int.class); + storeEndMethodTemp = Permit.getMethod(endPosTable, "storeEnd", JCTree.class, int.class); } catch (NoSuchMethodException ex) { throw sneakyThrow(ex); } catch (ClassNotFoundException ex) { @@ -227,13 +227,13 @@ public class Javac { } storeEnd = storeEndMethodTemp; } - getEndPosition.setAccessible(true); - storeEnd.setAccessible(true); + Permit.setAccessible(getEndPosition); + Permit.setAccessible(storeEnd); } private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) { try { - return clazz.getMethod(name, paramTypes); + return Permit.getMethod(clazz, name, paramTypes); } catch (NoSuchMethodException e) { throw sneakyThrow(e); } @@ -243,7 +243,7 @@ public class Javac { try { Class<?>[] c = new Class[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) c[i] = Class.forName(paramTypes[i]); - return clazz.getMethod(name, c); + return Permit.getMethod(clazz, name, c); } catch (NoSuchMethodException e) { throw sneakyThrow(e); } catch (ClassNotFoundException e) { @@ -320,7 +320,7 @@ public class Javac { private static Field getFieldIfExists(Class<?> c, String fieldName) { try { - return c.getField("voidType"); + return Permit.getField(c, "voidType"); } catch (Exception e) { return null; } @@ -370,13 +370,13 @@ public class Javac { static { Field f = null; try { - f = JCCompilationUnit.class.getDeclaredField("endPositions"); + f = Permit.getField(JCCompilationUnit.class, "endPositions"); } catch (NoSuchFieldException e) {} JCCOMPILATIONUNIT_ENDPOSITIONS = f; f = null; try { - f = JCCompilationUnit.class.getDeclaredField("docComments"); + f = Permit.getField(JCCompilationUnit.class, "docComments"); } catch (NoSuchFieldException e) {} JCCOMPILATIONUNIT_DOCCOMMENTS = f; } diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index 5f4fb09c..68a16af2 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -88,6 +88,8 @@ import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +import lombok.permit.Permit; + public class JavacTreeMaker { private final TreeMaker tm; @@ -153,7 +155,7 @@ public class JavacTreeMaker { Object value = cache.get(fieldName); if (value != null) return value; try { - value = Class.forName(className).getField(fieldName).get(null); + value = Permit.getField(Class.forName(className), fieldName).get(null); } catch (NoSuchFieldException e) { throw Javac.sneakyThrow(e); } catch (IllegalAccessException e) { @@ -169,7 +171,7 @@ public class JavacTreeMaker { private static Field NOSUCHFIELDEX_MARKER; static { try { - NOSUCHFIELDEX_MARKER = SchroedingerType.class.getDeclaredField("NOSUCHFIELDEX_MARKER"); + NOSUCHFIELDEX_MARKER = Permit.getField(SchroedingerType.class, "NOSUCHFIELDEX_MARKER"); } catch (NoSuchFieldException e) { throw Javac.sneakyThrow(e); } @@ -180,12 +182,12 @@ public class JavacTreeMaker { Field field = cache.get(c); if (field == null) { try { - field = c.getField(fieldName); + field = Permit.getField(c, fieldName); } catch (NoSuchFieldException e) { cache.putIfAbsent(c, NOSUCHFIELDEX_MARKER); throw Javac.sneakyThrow(e); } - field.setAccessible(true); + Permit.setAccessible(field); Field old = cache.putIfAbsent(c, field); if (old != null) field = old; } @@ -207,8 +209,7 @@ public class JavacTreeMaker { static { Method m = null; try { - m = Type.class.getDeclaredMethod("getTag"); - m.setAccessible(true); + m = Permit.getMethod(Type.class, "getTag"); } catch (NoSuchMethodException e) {} TYPE_TYPETAG_METHOD = m; } @@ -255,8 +256,7 @@ public class JavacTreeMaker { static { Method m = null; try { - m = JCTree.class.getDeclaredMethod("getTag"); - m.setAccessible(true); + m = Permit.getMethod(JCTree.class, "getTag"); } catch (NoSuchMethodException e) {} if (m != null) { @@ -265,8 +265,7 @@ public class JavacTreeMaker { } else { Field f = null; try { - f = JCTree.class.getDeclaredField("tag"); - f.setAccessible(true); + f = Permit.getField(JCTree.class, "tag"); } catch (NoSuchFieldException e) {} TAG_FIELD = f; TAG_METHOD = null; @@ -381,7 +380,7 @@ public class JavacTreeMaker { else throw new IllegalStateException("Lombok TreeMaker frontend issue: multiple matches when looking for method: " + m); } if (found == null) throw new IllegalStateException("Lombok TreeMaker frontend issue: no match when looking for method: " + m); - found.setAccessible(true); + Permit.setAccessible(found); Object marker = METHOD_CACHE.putIfAbsent(m, found); if (marker == null) return found; return METHOD_CACHE.get(m); diff --git a/src/utils/lombok/javac/PackageName.java b/src/utils/lombok/javac/PackageName.java index e4dd6b20..72892cca 100644 --- a/src/utils/lombok/javac/PackageName.java +++ b/src/utils/lombok/javac/PackageName.java @@ -28,13 +28,15 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; +import lombok.permit.Permit; + // Supports JDK6-9 public class PackageName { private static final Method packageNameMethod = getPackageNameMethod(); private static Method getPackageNameMethod() { try { - return JCCompilationUnit.class.getDeclaredMethod("getPackageName"); + return Permit.getMethod(JCCompilationUnit.class, "getPackageName"); } catch (Exception e) { return null; } diff --git a/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java index 0cf8fdcd..5d96f9d1 100644 --- a/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java +++ b/src/utils/lombok/javac/java6/CommentCollectingParserFactory.java @@ -28,6 +28,8 @@ import com.sun.tools.javac.parser.Lexer; import com.sun.tools.javac.parser.Parser; import com.sun.tools.javac.util.Context; +import lombok.permit.Permit; + public class CommentCollectingParserFactory extends Parser.Factory { static Context.Key<Parser.Factory> key() { return parserFactoryKey; @@ -49,8 +51,7 @@ public class CommentCollectingParserFactory extends Parser.Factory { context.put(CommentCollectingParserFactory.key(), (Parser.Factory)null); Field field; try { - field = JavaCompiler.class.getDeclaredField("parserFactory"); - field.setAccessible(true); + field = Permit.getField(JavaCompiler.class, "parserFactory"); field.set(compiler, new CommentCollectingParserFactory(context)); } catch (Exception e) { throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e); diff --git a/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java index ffd68f55..7ef937cd 100644 --- a/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java +++ b/src/utils/lombok/javac/java7/CommentCollectingParserFactory.java @@ -30,6 +30,8 @@ import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.ScannerFactory; import com.sun.tools.javac.util.Context; +import lombok.permit.Permit; + public class CommentCollectingParserFactory extends ParserFactory { private final Context context; @@ -56,8 +58,7 @@ public class CommentCollectingParserFactory extends ParserFactory { context.put(CommentCollectingParserFactory.key(), (ParserFactory)null); Field field; try { - field = JavaCompiler.class.getDeclaredField("parserFactory"); - field.setAccessible(true); + field = Permit.getField(JavaCompiler.class, "parserFactory"); field.set(compiler, new CommentCollectingParserFactory(context)); } catch (Exception e) { throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e); diff --git a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java index 2fdaddfe..0988ce6d 100644 --- a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java +++ b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java @@ -30,6 +30,8 @@ import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.ScannerFactory; import com.sun.tools.javac.util.Context; +import lombok.permit.Permit; + public class CommentCollectingParserFactory extends ParserFactory { private final Context context; @@ -66,8 +68,7 @@ public class CommentCollectingParserFactory extends ParserFactory { context.put(CommentCollectingParserFactory.key(), (ParserFactory) null); Field field; try { - field = JavaCompiler.class.getDeclaredField("parserFactory"); - field.setAccessible(true); + field = Permit.getField(JavaCompiler.class, "parserFactory"); field.set(compiler, new CommentCollectingParserFactory(context)); } catch (Exception e) { throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e); diff --git a/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java index 5af4a419..208d2570 100644 --- a/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java +++ b/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java @@ -30,6 +30,8 @@ import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.ScannerFactory; import com.sun.tools.javac.util.Context; +import lombok.permit.Permit; + public class CommentCollectingParserFactory extends ParserFactory { private final Context context; @@ -60,8 +62,7 @@ public class CommentCollectingParserFactory extends ParserFactory { context.put(CommentCollectingParserFactory.key(), (ParserFactory) null); Field field; try { - field = JavaCompiler.class.getDeclaredField("parserFactory"); - field.setAccessible(true); + field = Permit.getField(JavaCompiler.class, "parserFactory"); field.set(compiler, new CommentCollectingParserFactory(context)); } catch (Exception e) { throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e); diff --git a/src/utils/lombok/permit/Permit.java b/src/utils/lombok/permit/Permit.java new file mode 100644 index 00000000..00b8274c --- /dev/null +++ b/src/utils/lombok/permit/Permit.java @@ -0,0 +1,100 @@ +package lombok.permit; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.util.List; + +// sunapi suppresses javac's warning about using Unsafe; 'all' suppresses eclipse's warning about the unspecified 'sunapi' key. Leave them both. +// Yes, javac's definition of the word 'all' is quite contrary to what the dictionary says it means. 'all' does NOT include 'sunapi' according to javac. +@SuppressWarnings({"sunapi", "all"}) +public class Permit { + private Permit() {} + + + private static final long ACCESSIBLE_OVERRIDE_FIELD_OFFSET; + private static final IllegalAccessException INIT_ERROR; + private static final sun.misc.Unsafe UNSAFE = (sun.misc.Unsafe) reflectiveStaticFieldAccess(sun.misc.Unsafe.class, "theUnsafe"); + + static { + Field f; + long g; + Throwable ex; + + try { + f = AccessibleObject.class.getDeclaredField("override"); + g = UNSAFE.objectFieldOffset(f); + ex = null; + } catch (Throwable t) { + f = null; + g = -1L; + ex = t; + } + + ACCESSIBLE_OVERRIDE_FIELD_OFFSET = g; + if (ex == null) INIT_ERROR = null; + else if (ex instanceof IllegalAccessException) INIT_ERROR = (IllegalAccessException) ex; + else { + INIT_ERROR = new IllegalAccessException("Cannot initialize Unsafe-based permit"); + INIT_ERROR.initCause(ex); + } + } + + public static <T extends AccessibleObject> T setAccessible(T accessor) { + if (INIT_ERROR == null) { + UNSAFE.putBoolean(accessor, ACCESSIBLE_OVERRIDE_FIELD_OFFSET, true); + } else { + accessor.setAccessible(true); + } + + return accessor; + } + + public static Method getMethod(Class<?> c, String mName, Class<?>... parameterTypes) throws NoSuchMethodException { + Method m = null; + Class<?> oc = c; + while (c != null) { + try { + m = c.getDeclaredMethod(mName, parameterTypes); + break; + } catch (NoSuchMethodException e) {} + c = c.getSuperclass(); + } + + if (m == null) throw new NoSuchMethodException(oc.getName() + " :: " + mName + "(args)"); + return setAccessible(m); + } + + public static Field getField(Class<?> c, String fName) throws NoSuchFieldException { + Field f = null; + Class<?> oc = c; + while (c != null) { + try { + f = c.getDeclaredField(fName); + break; + } catch (NoSuchFieldException e) {} + c = c.getSuperclass(); + } + + if (f == null) throw new NoSuchFieldException(oc.getName() + " :: " + fName); + + return setAccessible(f); + } + + public static <T> Constructor<T> getConstructor(Class<T> c, Class<?>... parameterTypes) throws NoSuchMethodException { + return setAccessible(c.getDeclaredConstructor(parameterTypes)); + } + + private static Object reflectiveStaticFieldAccess(Class<?> c, String fName) { + try { + Field f = c.getDeclaredField(fName); + f.setAccessible(true); + return f.get(null); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/utils/lombok/permit/package-info.java b/src/utils/lombok/permit/package-info.java new file mode 100644 index 00000000..a28f7160 --- /dev/null +++ b/src/utils/lombok/permit/package-info.java @@ -0,0 +1,8 @@ +/** + * This is a reduced copy of the nqzero Permit-reflect project. + * https://github.com/nqzero/permit-reflect + * + * Many thanks to nqzero. The permit-reflect project is, like lombok itself, licensed under the MIT license. + * See https://github.com/nqzero/permit-reflect/blob/master/License for license info. + */ +package lombok.permit;
\ No newline at end of file |