aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornickl- <github@jigsoft.co.za>2017-10-27 07:59:12 +0200
committernickl- <github@jigsoft.co.za>2017-11-12 23:49:21 +0200
commitaf399dbfa005ccde16247b88159cc269e243fb22 (patch)
tree36fd0a1a4944747b8bc22c1e3dd27b1fc3d30cc4
parent45e201f2fbc0e75ee5c050f633e23ca5d418d52f (diff)
downloadjavassist-af399dbfa005ccde16247b88159cc269e243fb22.tar.gz
javassist-af399dbfa005ccde16247b88159cc269e243fb22.zip
Refactor definePackage as well.
Yes it is deprecated but seems the right thing to do
-rw-r--r--src/main/javassist/ClassPool.java69
-rw-r--r--src/main/javassist/util/proxy/DefinePackageHelper.java179
2 files changed, 184 insertions, 64 deletions
diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java
index 89a0067e..73a4d857 100644
--- a/src/main/javassist/ClassPool.java
+++ b/src/main/javassist/ClassPool.java
@@ -21,19 +21,16 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.lang.reflect.Method;
import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
-import java.util.Hashtable;
-import java.util.Iterator;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
import javassist.bytecode.ClassFile;
import javassist.bytecode.Descriptor;
+import javassist.util.proxy.DefinePackageHelper;
/**
* A container of <code>CtClass</code> objects.
@@ -69,28 +66,8 @@ import javassist.bytecode.Descriptor;
* @see javassist.CtClass
* @see javassist.ClassPath
*/
+@SuppressWarnings({"unchecked", "rawtypes"})
public class ClassPool {
- private static java.lang.reflect.Method definePackage = null;
-
- static {
- if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9)
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction(){
- public Object run() throws Exception{
- Class cl = Class.forName("java.lang.ClassLoader");
- definePackage = cl.getDeclaredMethod("definePackage",
- new Class[] { String.class, String.class, String.class,
- String.class, String.class, String.class,
- String.class, java.net.URL.class });
- return null;
- }
- });
- }
- catch (PrivilegedActionException pae) {
- throw new RuntimeException("cannot initialize ClassPool",
- pae.getException());
- }
- }
/**
* Determines the search order.
@@ -1175,43 +1152,7 @@ public class ClassPool {
public void makePackage(ClassLoader loader, String name)
throws CannotCompileException
{
- if (definePackage == null)
- throw new CannotCompileException("give the JVM --add-opens");
-
- Object[] args = new Object[] {
- name, null, null, null, null, null, null, null };
- Throwable t;
- try {
- makePackage2(definePackage, loader, args);
- return;
- }
- catch (java.lang.reflect.InvocationTargetException e) {
- t = e.getTargetException();
- if (t == null)
- t = e;
- else if (t instanceof IllegalArgumentException) {
- // if the package is already defined, an IllegalArgumentException
- // is thrown.
- return;
- }
- }
- catch (Exception e) {
- t = e;
- }
-
- throw new CannotCompileException(t);
+ DefinePackageHelper.definePackage(name, loader);
}
- private static synchronized Object makePackage2(Method method,
- ClassLoader loader, Object[] args)
- throws Exception
- {
- method.setAccessible(true);
- try {
- return method.invoke(loader, args);
- }
- finally {
- method.setAccessible(false);
- }
- }
}
diff --git a/src/main/javassist/util/proxy/DefinePackageHelper.java b/src/main/javassist/util/proxy/DefinePackageHelper.java
new file mode 100644
index 00000000..1fe0bd61
--- /dev/null
+++ b/src/main/javassist/util/proxy/DefinePackageHelper.java
@@ -0,0 +1,179 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later,
+ * or the Apache License Version 2.0.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.util.proxy;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.bytecode.ClassFile;
+
+/**
+ * Helper class for invoking {@link ClassLoader#defineClass(String,byte[],int,int)}.
+ *
+ * @since 3.22
+ */
+public class DefinePackageHelper
+{
+
+ private static enum SecuredPrivileged
+ {
+ JAVA_9 {
+ // definePackage has been discontinued for JAVA 9
+ @Override
+ protected Package definePackage(ClassLoader loader, String name, String specTitle,
+ String specVersion, String specVendor, String implTitle, String implVersion,
+ String implVendor, URL sealBase) throws IllegalArgumentException
+ {
+ throw new RuntimeException("define package has been disabled for jigsaw");
+ }
+ },
+ JAVA_7 {
+ private final SecurityActions stack = SecurityActions.stack;
+ private final MethodHandle definePackage = getDefinePackageMethodHandle();
+ private MethodHandle getDefinePackageMethodHandle()
+ {
+ if (stack.getCallerClass() != this.getClass())
+ throw new IllegalAccessError("Access denied for caller.");
+ try {
+ return SecurityActions.getMethodHandle(ClassLoader.class,
+ "definePackage", new Class[] {
+ String.class, String.class, String.class, String.class,
+ String.class, String.class, String.class, URL.class
+ });
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("cannot initialize", e);
+ }
+ }
+
+ @Override
+ protected Package definePackage(ClassLoader loader, String name, String specTitle,
+ String specVersion, String specVendor, String implTitle, String implVersion,
+ String implVendor, URL sealBase) throws IllegalArgumentException {
+ if (stack.getCallerClass() != DefinePackageHelper.class)
+ throw new IllegalAccessError("Access denied for caller.");
+ try {
+ return (Package) definePackage.invokeWithArguments(loader, name, specTitle,
+ specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
+ } catch (Throwable e) {
+ if (e instanceof IllegalArgumentException) throw (IllegalArgumentException) e;
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ }
+ return null;
+ }
+ },
+ JAVA_OTHER {
+ private final SecurityActions stack = SecurityActions.stack;
+ private final Method definePackage = getDefinePackageMethod();
+ private Method getDefinePackageMethod()
+ {
+ if (stack.getCallerClass() != this.getClass())
+ throw new IllegalAccessError("Access denied for caller.");
+ try {
+ return SecurityActions.getDeclaredMethod(ClassLoader.class,
+ "definePackage", new Class[] {
+ String.class, String.class, String.class, String.class,
+ String.class, String.class, String.class, URL.class
+ });
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("cannot initialize", e);
+ }
+ }
+
+ @Override
+ protected Package definePackage(ClassLoader loader, String name, String specTitle,
+ String specVersion, String specVendor, String implTitle, String implVersion,
+ String implVendor, URL sealBase) throws IllegalArgumentException
+ {
+ if (stack.getCallerClass() != DefinePackageHelper.class)
+ throw new IllegalAccessError("Access denied for caller.");
+ try {
+ definePackage.setAccessible(true);
+ return (Package) definePackage.invoke(loader, new Object[] {
+ name, specTitle, specVersion, specVendor, implTitle,
+ implVersion, implVendor, sealBase
+ });
+ } catch (Throwable e) {
+ if (e instanceof InvocationTargetException) {
+ Throwable t = ((InvocationTargetException) e).getTargetException();
+ if (t instanceof IllegalArgumentException)
+ throw (IllegalArgumentException) t;
+ }
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ }
+ finally {
+ definePackage.setAccessible(false);
+ }
+ return null;
+ }
+ };
+
+ protected abstract Package definePackage(ClassLoader loader, String name, String specTitle,
+ String specVersion, String specVendor, String implTitle, String implVersion,
+ String implVendor, URL sealBase) throws IllegalArgumentException;
+ }
+
+ private static final SecuredPrivileged privileged = ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9
+ ? SecuredPrivileged.JAVA_9
+ : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7
+ ? SecuredPrivileged.JAVA_7
+ : SecuredPrivileged.JAVA_OTHER;
+
+
+ /**
+ * Defines a new package. If the package is already defined, this method
+ * performs nothing.
+ *
+ * <p>You do not necessarily need to
+ * call this method. If this method is called, then
+ * <code>getPackage()</code> on the <code>Class</code> object returned
+ * by <code>toClass()</code> will return a non-null object.</p>
+ *
+ * <p>The jigsaw module introduced by Java 9 has broken this method.
+ * In Java 9 or later, the VM argument
+ * <code>--add-opens java.base/java.lang=ALL-UNNAMED</code>
+ * has to be given to the JVM so that this method can run.
+ * </p>
+ *
+ * @param loader the class loader passed to <code>toClass()</code> or
+ * the default one obtained by <code>getClassLoader()</code>.
+ * @param name the package name.
+ * @see #getClassLoader()
+ * @see #toClass(CtClass)
+ * @see CtClass#toClass() */
+ public static void definePackage(String className, ClassLoader loader)
+ throws CannotCompileException
+ {
+ try {
+ privileged.definePackage(loader, className,
+ null, null, null, null, null, null, null);
+ }
+ catch (IllegalArgumentException e) {
+ // if the package is already defined, an IllegalArgumentException
+ // is thrown.
+ return;
+ }
+ catch (Exception e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ private DefinePackageHelper() {}
+}