Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

AccessorMaker.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2004 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. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist.compiler;
  16. import javassist.*;
  17. import javassist.bytecode.*;
  18. import java.util.HashMap;
  19. /**
  20. * AccessorMaker maintains accessors to private members of an enclosing
  21. * class. It is necessary for compiling a method in an inner class.
  22. */
  23. public class AccessorMaker {
  24. private CtClass clazz;
  25. private int uniqueNumber;
  26. private HashMap accessors;
  27. public AccessorMaker(CtClass c) {
  28. clazz = c;
  29. uniqueNumber = 1;
  30. accessors = new HashMap();
  31. }
  32. /**
  33. * Returns the name of the method for accessing a private method.
  34. *
  35. * @param name the name of the private method.
  36. * @param desc the descriptor of the private method.
  37. * @param accDesc the descriptor of the accessor method. The first
  38. * parameter type is <code>clazz</code>.
  39. * If the private method is static,
  40. * <code>accDesc<code> must be equal to <code>desc</code>.
  41. *
  42. * @param orig the method info of the private method.
  43. * @return
  44. */
  45. public String getMethodAccessor(String name, String desc, String accDesc,
  46. MethodInfo orig)
  47. throws CompileError
  48. {
  49. String key = name + ":" + desc;
  50. String accName = (String)accessors.get(key);
  51. if (accName != null)
  52. return accName; // already exists.
  53. ClassFile cf = clazz.getClassFile(); // turn on the modified flag.
  54. accName = findAccessorName(cf);
  55. try {
  56. ConstPool cp = cf.getConstPool();
  57. ClassPool pool = clazz.getClassPool();
  58. MethodInfo minfo
  59. = new MethodInfo(cp, accName, accDesc);
  60. minfo.setAccessFlags(AccessFlag.STATIC);
  61. minfo.addAttribute(new SyntheticAttribute(cp));
  62. ExceptionsAttribute ea = orig.getExceptionsAttribute();
  63. if (ea != null)
  64. minfo.addAttribute(ea.copy(cp, null));
  65. CtClass[] params = Descriptor.getParameterTypes(accDesc, pool);
  66. int regno = 0;
  67. Bytecode code = new Bytecode(cp);
  68. for (int i = 0; i < params.length; ++i)
  69. regno += code.addLoad(regno, params[i]);
  70. code.setMaxLocals(regno);
  71. if (desc == accDesc)
  72. code.addInvokestatic(clazz, name, desc);
  73. else
  74. code.addInvokevirtual(clazz, name, desc);
  75. code.addReturn(Descriptor.getReturnType(desc, pool));
  76. minfo.setCodeAttribute(code.toCodeAttribute());
  77. cf.addMethod(minfo);
  78. }
  79. catch (CannotCompileException e) {
  80. throw new CompileError(e);
  81. }
  82. catch (NotFoundException e) {
  83. throw new CompileError(e);
  84. }
  85. accessors.put(key, accName);
  86. return accName;
  87. }
  88. /**
  89. * Returns the method_info representing the added getter.
  90. */
  91. public MethodInfo getFieldGetter(FieldInfo finfo, boolean is_static)
  92. throws CompileError
  93. {
  94. String fieldName = finfo.getName();
  95. String key = fieldName + ":getter";
  96. Object res = accessors.get(key);
  97. if (res != null)
  98. return (MethodInfo)res; // already exists.
  99. ClassFile cf = clazz.getClassFile(); // turn on the modified flag.
  100. String accName = findAccessorName(cf);
  101. try {
  102. ConstPool cp = cf.getConstPool();
  103. ClassPool pool = clazz.getClassPool();
  104. String fieldType = finfo.getDescriptor();
  105. String accDesc;
  106. if (is_static)
  107. accDesc = "()" + fieldType;
  108. else
  109. accDesc = "(" + Descriptor.of(clazz) + ")" + fieldType;
  110. MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
  111. minfo.setAccessFlags(AccessFlag.STATIC);
  112. minfo.addAttribute(new SyntheticAttribute(cp));
  113. Bytecode code = new Bytecode(cp);
  114. if (is_static) {
  115. code.addGetstatic(Bytecode.THIS, fieldName, fieldType);
  116. }
  117. else {
  118. code.addAload(0);
  119. code.addGetfield(Bytecode.THIS, fieldName, fieldType);
  120. code.setMaxLocals(1);
  121. }
  122. code.addReturn(Descriptor.toCtClass(fieldType, pool));
  123. minfo.setCodeAttribute(code.toCodeAttribute());
  124. cf.addMethod(minfo);
  125. accessors.put(key, minfo);
  126. return minfo;
  127. }
  128. catch (CannotCompileException e) {
  129. throw new CompileError(e);
  130. }
  131. catch (NotFoundException e) {
  132. throw new CompileError(e);
  133. }
  134. }
  135. /**
  136. * Returns the method_info representing the added setter.
  137. */
  138. public MethodInfo getFieldSetter(FieldInfo finfo, boolean is_static)
  139. throws CompileError
  140. {
  141. String fieldName = finfo.getName();
  142. String key = fieldName + ":setter";
  143. Object res = accessors.get(key);
  144. if (res != null)
  145. return (MethodInfo)res; // already exists.
  146. ClassFile cf = clazz.getClassFile(); // turn on the modified flag.
  147. String accName = findAccessorName(cf);
  148. try {
  149. ConstPool cp = cf.getConstPool();
  150. ClassPool pool = clazz.getClassPool();
  151. String fieldType = finfo.getDescriptor();
  152. String accDesc;
  153. if (is_static)
  154. accDesc = "(" + fieldType + ")V";
  155. else
  156. accDesc = "(" + Descriptor.of(clazz) + fieldType + ")V";
  157. MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
  158. minfo.setAccessFlags(AccessFlag.STATIC);
  159. minfo.addAttribute(new SyntheticAttribute(cp));
  160. Bytecode code = new Bytecode(cp);
  161. int reg;
  162. if (is_static) {
  163. reg = code.addLoad(0, Descriptor.toCtClass(fieldType, pool));
  164. code.addPutstatic(Bytecode.THIS, fieldName, fieldType);
  165. }
  166. else {
  167. code.addAload(0);
  168. reg = code.addLoad(1, Descriptor.toCtClass(fieldType, pool))
  169. + 1;
  170. code.addPutfield(Bytecode.THIS, fieldName, fieldType);
  171. }
  172. code.addReturn(null);
  173. code.setMaxLocals(reg);
  174. minfo.setCodeAttribute(code.toCodeAttribute());
  175. cf.addMethod(minfo);
  176. accessors.put(key, minfo);
  177. return minfo;
  178. }
  179. catch (CannotCompileException e) {
  180. throw new CompileError(e);
  181. }
  182. catch (NotFoundException e) {
  183. throw new CompileError(e);
  184. }
  185. }
  186. private String findAccessorName(ClassFile cf) {
  187. String accName;
  188. do {
  189. accName = "access$" + uniqueNumber++;
  190. } while (cf.getMethod(accName) != null);
  191. return accName;
  192. }
  193. }