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.

FactoryHelper.java 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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.io.BufferedOutputStream;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.DataOutputStream;
  20. import java.io.File;
  21. import java.io.FileOutputStream;
  22. import java.io.IOException;
  23. import java.security.ProtectionDomain;
  24. import javassist.CannotCompileException;
  25. import javassist.bytecode.ClassFile;
  26. /**
  27. * A helper class for implementing <code>ProxyFactory</code>.
  28. * The users of <code>ProxyFactory</code> do not have to see this class.
  29. *
  30. * @see ProxyFactory
  31. */
  32. public class FactoryHelper {
  33. /**
  34. * Returns an index for accessing arrays in this class.
  35. *
  36. * @throws RuntimeException if a given type is not a primitive type.
  37. */
  38. public static final int typeIndex(Class<?> type) {
  39. for (int i = 0; i < primitiveTypes.length; i++)
  40. if (primitiveTypes[i] == type)
  41. return i;
  42. throw new RuntimeException("bad type:" + type.getName());
  43. }
  44. /**
  45. * <code>Class</code> objects representing primitive types.
  46. */
  47. public static final Class<?>[] primitiveTypes = {
  48. Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE,
  49. Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE
  50. };
  51. /**
  52. * The fully-qualified names of wrapper classes for primitive types.
  53. */
  54. public static final String[] wrapperTypes = {
  55. "java.lang.Boolean", "java.lang.Byte", "java.lang.Character",
  56. "java.lang.Short", "java.lang.Integer", "java.lang.Long",
  57. "java.lang.Float", "java.lang.Double", "java.lang.Void"
  58. };
  59. /**
  60. * The descriptors of the constructors of wrapper classes.
  61. */
  62. public static final String[] wrapperDesc = {
  63. "(Z)V", "(B)V", "(C)V", "(S)V", "(I)V", "(J)V",
  64. "(F)V", "(D)V"
  65. };
  66. /**
  67. * The names of methods for obtaining a primitive value
  68. * from a wrapper object. For example, <code>intValue()</code>
  69. * is such a method for obtaining an integer value from a
  70. * <code>java.lang.Integer</code> object.
  71. */
  72. public static final String[] unwarpMethods = {
  73. "booleanValue", "byteValue", "charValue", "shortValue",
  74. "intValue", "longValue", "floatValue", "doubleValue"
  75. };
  76. /**
  77. * The descriptors of the unwrapping methods contained
  78. * in <code>unwrapMethods</code>.
  79. */
  80. public static final String[] unwrapDesc = {
  81. "()Z", "()B", "()C", "()S", "()I", "()J", "()F", "()D"
  82. };
  83. /**
  84. * The data size of primitive types. <code>long</code>
  85. * and <code>double</code> are 2; the others are 1.
  86. */
  87. public static final int[] dataSize = {
  88. 1, 1, 1, 1, 1, 2, 1, 2
  89. };
  90. /**
  91. * Loads a class file by a given class loader.
  92. * This method uses a default protection domain for the class
  93. * but it may not work with a security manager or a signed jar file.
  94. *
  95. * @see #toClass(ClassFile,Class,ClassLoader,ProtectionDomain)
  96. * @deprecated
  97. */
  98. public static Class<?> toClass(ClassFile cf, ClassLoader loader)
  99. throws CannotCompileException
  100. {
  101. return toClass(cf, null, loader, null);
  102. }
  103. /**
  104. * Loads a class file by a given class loader.
  105. *
  106. * @param neighbor a class belonging to the same package that
  107. * the loaded class belongs to.
  108. * It can be null.
  109. * @param loader The class loader. It can be null if {@code neighbor}
  110. * is not null.
  111. * @param domain if it is null, a default domain is used.
  112. * @since 3.3
  113. */
  114. public static Class<?> toClass(ClassFile cf, Class<?> neighbor,
  115. ClassLoader loader, ProtectionDomain domain)
  116. throws CannotCompileException
  117. {
  118. try {
  119. byte[] b = toBytecode(cf);
  120. if (ProxyFactory.onlyPublicMethods)
  121. return DefineClassHelper.toPublicClass(cf.getName(), b);
  122. else
  123. return DefineClassHelper.toClass(cf.getName(), neighbor,
  124. loader, domain, b);
  125. }
  126. catch (IOException e) {
  127. throw new CannotCompileException(e);
  128. }
  129. }
  130. /**
  131. * Loads a class file by a given lookup.
  132. *
  133. * @param lookup used to define the class.
  134. * @since 3.24
  135. */
  136. public static Class<?> toClass(ClassFile cf, java.lang.invoke.MethodHandles.Lookup lookup)
  137. throws CannotCompileException
  138. {
  139. try {
  140. byte[] b = toBytecode(cf);
  141. return DefineClassHelper.toClass(lookup, b);
  142. }
  143. catch (IOException e) {
  144. throw new CannotCompileException(e);
  145. }
  146. }
  147. private static byte[] toBytecode(ClassFile cf) throws IOException {
  148. ByteArrayOutputStream barray = new ByteArrayOutputStream();
  149. DataOutputStream out = new DataOutputStream(barray);
  150. try {
  151. cf.write(out);
  152. }
  153. finally {
  154. out.close();
  155. }
  156. return barray.toByteArray();
  157. }
  158. /**
  159. * Writes a class file.
  160. */
  161. public static void writeFile(ClassFile cf, String directoryName)
  162. throws CannotCompileException {
  163. try {
  164. writeFile0(cf, directoryName);
  165. }
  166. catch (IOException e) {
  167. throw new CannotCompileException(e);
  168. }
  169. }
  170. private static void writeFile0(ClassFile cf, String directoryName)
  171. throws CannotCompileException, IOException {
  172. String classname = cf.getName();
  173. String filename = directoryName + File.separatorChar
  174. + classname.replace('.', File.separatorChar) + ".class";
  175. int pos = filename.lastIndexOf(File.separatorChar);
  176. if (pos > 0) {
  177. String dir = filename.substring(0, pos);
  178. if (!dir.equals("."))
  179. new File(dir).mkdirs();
  180. }
  181. DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
  182. new FileOutputStream(filename)));
  183. try {
  184. cf.write(out);
  185. }
  186. catch (IOException e) {
  187. throw e;
  188. }
  189. finally {
  190. out.close();
  191. }
  192. }
  193. }