You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefinePackageHelper.java 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later,
  9. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.util.proxy;
  17. import java.lang.invoke.MethodHandle;
  18. import java.lang.reflect.InvocationTargetException;
  19. import java.lang.reflect.Method;
  20. import java.net.URL;
  21. import javassist.CannotCompileException;
  22. import javassist.CtClass;
  23. import javassist.bytecode.ClassFile;
  24. /**
  25. * Helper class for invoking {@link ClassLoader#defineClass(String,byte[],int,int)}.
  26. *
  27. * @since 3.22
  28. */
  29. public class DefinePackageHelper
  30. {
  31. private static enum SecuredPrivileged
  32. {
  33. JAVA_9 {
  34. // definePackage has been discontinued for JAVA 9
  35. @Override
  36. protected Package definePackage(ClassLoader loader, String name, String specTitle,
  37. String specVersion, String specVendor, String implTitle, String implVersion,
  38. String implVendor, URL sealBase) throws IllegalArgumentException
  39. {
  40. throw new RuntimeException("define package has been disabled for jigsaw");
  41. }
  42. },
  43. JAVA_7 {
  44. private final SecurityActions stack = SecurityActions.stack;
  45. private final MethodHandle definePackage = getDefinePackageMethodHandle();
  46. private MethodHandle getDefinePackageMethodHandle()
  47. {
  48. if (stack.getCallerClass() != this.getClass())
  49. throw new IllegalAccessError("Access denied for caller.");
  50. try {
  51. return SecurityActions.getMethodHandle(ClassLoader.class,
  52. "definePackage", new Class[] {
  53. String.class, String.class, String.class, String.class,
  54. String.class, String.class, String.class, URL.class
  55. });
  56. } catch (NoSuchMethodException e) {
  57. throw new RuntimeException("cannot initialize", e);
  58. }
  59. }
  60. @Override
  61. protected Package definePackage(ClassLoader loader, String name, String specTitle,
  62. String specVersion, String specVendor, String implTitle, String implVersion,
  63. String implVendor, URL sealBase) throws IllegalArgumentException {
  64. if (stack.getCallerClass() != DefinePackageHelper.class)
  65. throw new IllegalAccessError("Access denied for caller.");
  66. try {
  67. return (Package) definePackage.invokeWithArguments(loader, name, specTitle,
  68. specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
  69. } catch (Throwable e) {
  70. if (e instanceof IllegalArgumentException) throw (IllegalArgumentException) e;
  71. if (e instanceof RuntimeException) throw (RuntimeException) e;
  72. }
  73. return null;
  74. }
  75. },
  76. JAVA_OTHER {
  77. private final SecurityActions stack = SecurityActions.stack;
  78. private final Method definePackage = getDefinePackageMethod();
  79. private Method getDefinePackageMethod()
  80. {
  81. if (stack.getCallerClass() != this.getClass())
  82. throw new IllegalAccessError("Access denied for caller.");
  83. try {
  84. return SecurityActions.getDeclaredMethod(ClassLoader.class,
  85. "definePackage", new Class[] {
  86. String.class, String.class, String.class, String.class,
  87. String.class, String.class, String.class, URL.class
  88. });
  89. } catch (NoSuchMethodException e) {
  90. throw new RuntimeException("cannot initialize", e);
  91. }
  92. }
  93. @Override
  94. protected Package definePackage(ClassLoader loader, String name, String specTitle,
  95. String specVersion, String specVendor, String implTitle, String implVersion,
  96. String implVendor, URL sealBase) throws IllegalArgumentException
  97. {
  98. if (stack.getCallerClass() != DefinePackageHelper.class)
  99. throw new IllegalAccessError("Access denied for caller.");
  100. try {
  101. definePackage.setAccessible(true);
  102. return (Package) definePackage.invoke(loader, new Object[] {
  103. name, specTitle, specVersion, specVendor, implTitle,
  104. implVersion, implVendor, sealBase
  105. });
  106. } catch (Throwable e) {
  107. if (e instanceof InvocationTargetException) {
  108. Throwable t = ((InvocationTargetException) e).getTargetException();
  109. if (t instanceof IllegalArgumentException)
  110. throw (IllegalArgumentException) t;
  111. }
  112. if (e instanceof RuntimeException) throw (RuntimeException) e;
  113. }
  114. finally {
  115. definePackage.setAccessible(false);
  116. }
  117. return null;
  118. }
  119. };
  120. protected abstract Package definePackage(ClassLoader loader, String name, String specTitle,
  121. String specVersion, String specVendor, String implTitle, String implVersion,
  122. String implVendor, URL sealBase) throws IllegalArgumentException;
  123. }
  124. private static final SecuredPrivileged privileged = ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9
  125. ? SecuredPrivileged.JAVA_9
  126. : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7
  127. ? SecuredPrivileged.JAVA_7
  128. : SecuredPrivileged.JAVA_OTHER;
  129. /**
  130. * Defines a new package. If the package is already defined, this method
  131. * performs nothing.
  132. *
  133. * <p>You do not necessarily need to
  134. * call this method. If this method is called, then
  135. * <code>getPackage()</code> on the <code>Class</code> object returned
  136. * by <code>toClass()</code> will return a non-null object.</p>
  137. *
  138. * <p>The jigsaw module introduced by Java 9 has broken this method.
  139. * In Java 9 or later, the VM argument
  140. * <code>--add-opens java.base/java.lang=ALL-UNNAMED</code>
  141. * has to be given to the JVM so that this method can run.
  142. * </p>
  143. *
  144. * @param loader the class loader passed to <code>toClass()</code> or
  145. * the default one obtained by <code>getClassLoader()</code>.
  146. * @param className the package name.
  147. * @see Class#getClassLoader()
  148. * @see CtClass#toClass()
  149. */
  150. public static void definePackage(String className, ClassLoader loader)
  151. throws CannotCompileException
  152. {
  153. try {
  154. privileged.definePackage(loader, className,
  155. null, null, null, null, null, null, null);
  156. }
  157. catch (IllegalArgumentException e) {
  158. // if the package is already defined, an IllegalArgumentException
  159. // is thrown.
  160. return;
  161. }
  162. catch (Exception e) {
  163. throw new CannotCompileException(e);
  164. }
  165. }
  166. private DefinePackageHelper() {}
  167. }