/* * 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 abstract class Helper { 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 class Java9 extends Helper { // definePackage has been discontinued for JAVA 9 @Override 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"); } }; private static class Java7 extends Helper { 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 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; } } private static class JavaOther extends Helper { 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 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; } return null; } }; private static final Helper privileged = ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9 ? new Java9() : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7 ? new Java7() : new JavaOther(); /** * Defines a new package. If the package is already defined, this method * performs nothing. * *
You do not necessarily need to
* call this method. If this method is called, then
* getPackage()
on the Class
object returned
* by toClass()
will return a non-null object.
The jigsaw module introduced by Java 9 has broken this method.
* In Java 9 or later, the VM argument
* --add-opens java.base/java.lang=ALL-UNNAMED
* has to be given to the JVM so that this method can run.
*
toClass()
or
* the default one obtained by getClassLoader()
.
* @param className the package name.
* @see Class#getClassLoader()
* @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() {}
}