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.5KB

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 abstract class Helper {
  32. abstract Package definePackage(ClassLoader loader, String name, String specTitle,
  33. String specVersion, String specVendor, String implTitle, String implVersion,
  34. String implVendor, URL sealBase)
  35. throws IllegalArgumentException;
  36. }
  37. private static class Java9 extends Helper {
  38. // definePackage has been discontinued for JAVA 9
  39. @Override
  40. Package definePackage(ClassLoader loader, String name, String specTitle,
  41. String specVersion, String specVendor, String implTitle, String implVersion,
  42. String implVendor, URL sealBase)
  43. throws IllegalArgumentException
  44. {
  45. throw new RuntimeException("define package has been disabled for jigsaw");
  46. }
  47. };
  48. private static class Java7 extends Helper {
  49. private final SecurityActions stack = SecurityActions.stack;
  50. private final MethodHandle definePackage = getDefinePackageMethodHandle();
  51. private MethodHandle getDefinePackageMethodHandle() {
  52. if (stack.getCallerClass() != this.getClass())
  53. throw new IllegalAccessError("Access denied for caller.");
  54. try {
  55. return SecurityActions.getMethodHandle(ClassLoader.class,
  56. "definePackage", new Class[] {
  57. String.class, String.class, String.class, String.class,
  58. String.class, String.class, String.class, URL.class
  59. });
  60. } catch (NoSuchMethodException e) {
  61. throw new RuntimeException("cannot initialize", e);
  62. }
  63. }
  64. @Override
  65. Package definePackage(ClassLoader loader, String name, String specTitle,
  66. String specVersion, String specVendor, String implTitle, String implVersion,
  67. String implVendor, URL sealBase)
  68. throws IllegalArgumentException
  69. {
  70. if (stack.getCallerClass() != DefinePackageHelper.class)
  71. throw new IllegalAccessError("Access denied for caller.");
  72. try {
  73. return (Package) definePackage.invokeWithArguments(loader, name, specTitle,
  74. specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
  75. } catch (Throwable e) {
  76. if (e instanceof IllegalArgumentException) throw (IllegalArgumentException) e;
  77. if (e instanceof RuntimeException) throw (RuntimeException) e;
  78. }
  79. return null;
  80. }
  81. }
  82. private static class JavaOther extends Helper {
  83. private final SecurityActions stack = SecurityActions.stack;
  84. private final Method definePackage = getDefinePackageMethod();
  85. private Method getDefinePackageMethod() {
  86. if (stack.getCallerClass() != this.getClass())
  87. throw new IllegalAccessError("Access denied for caller.");
  88. try {
  89. return SecurityActions.getDeclaredMethod(ClassLoader.class,
  90. "definePackage", new Class[] {
  91. String.class, String.class, String.class, String.class,
  92. String.class, String.class, String.class, URL.class
  93. });
  94. } catch (NoSuchMethodException e) {
  95. throw new RuntimeException("cannot initialize", e);
  96. }
  97. }
  98. @Override
  99. Package definePackage(ClassLoader loader, String name, String specTitle,
  100. String specVersion, String specVendor, String implTitle, String implVersion,
  101. String implVendor, URL sealBase)
  102. throws IllegalArgumentException
  103. {
  104. if (stack.getCallerClass() != DefinePackageHelper.class)
  105. throw new IllegalAccessError("Access denied for caller.");
  106. try {
  107. definePackage.setAccessible(true);
  108. return (Package) definePackage.invoke(loader, new Object[] {
  109. name, specTitle, specVersion, specVendor, implTitle,
  110. implVersion, implVendor, sealBase
  111. });
  112. } catch (Throwable e) {
  113. if (e instanceof InvocationTargetException) {
  114. Throwable t = ((InvocationTargetException) e).getTargetException();
  115. if (t instanceof IllegalArgumentException)
  116. throw (IllegalArgumentException) t;
  117. }
  118. if (e instanceof RuntimeException) throw (RuntimeException) e;
  119. }
  120. return null;
  121. }
  122. };
  123. private static final Helper privileged
  124. = ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9
  125. ? new Java9() : ClassFile.MAJOR_VERSION >= ClassFile.JAVA_7
  126. ? new Java7() : new JavaOther();
  127. /**
  128. * Defines a new package. If the package is already defined, this method
  129. * performs nothing.
  130. *
  131. * <p>You do not necessarily need to
  132. * call this method. If this method is called, then
  133. * <code>getPackage()</code> on the <code>Class</code> object returned
  134. * by <code>toClass()</code> will return a non-null object.</p>
  135. *
  136. * <p>The jigsaw module introduced by Java 9 has broken this method.
  137. * In Java 9 or later, the VM argument
  138. * <code>--add-opens java.base/java.lang=ALL-UNNAMED</code>
  139. * has to be given to the JVM so that this method can run.
  140. * </p>
  141. *
  142. * @param loader the class loader passed to <code>toClass()</code> or
  143. * the default one obtained by <code>getClassLoader()</code>.
  144. * @param className the package name.
  145. * @see Class#getClassLoader()
  146. * @see CtClass#toClass()
  147. */
  148. public static void definePackage(String className, ClassLoader loader)
  149. throws CannotCompileException
  150. {
  151. try {
  152. privileged.definePackage(loader, className,
  153. null, null, null, null, null, null, null);
  154. }
  155. catch (IllegalArgumentException e) {
  156. // if the package is already defined, an IllegalArgumentException
  157. // is thrown.
  158. return;
  159. }
  160. catch (Exception e) {
  161. throw new CannotCompileException(e);
  162. }
  163. }
  164. private DefinePackageHelper() {}
  165. }