Browse Source

Refactor definePackage as well.

Yes it is deprecated but seems the right thing to do
tags/rel_3_23_0_ga
nickl- 6 years ago
parent
commit
af399dbfa0

+ 5
- 64
src/main/javassist/ClassPool.java View File

@@ -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);
}
}
}

+ 179
- 0
src/main/javassist/util/proxy/DefinePackageHelper.java View File

@@ -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() {}
}

Loading…
Cancel
Save