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.

Method.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* ====================================================================
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2001 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution,
  20. * if any, must include the following acknowledgment:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgment may appear in the software itself,
  24. * if and wherever such third-party acknowledgments normally appear.
  25. *
  26. * 4. The names "Apache" and "Apache Software Foundation" and
  27. * "Apache BCEL" must not be used to endorse or promote products
  28. * derived from this software without prior written permission. For
  29. * written permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache",
  32. * "Apache BCEL", nor may "Apache" appear in their name, without
  33. * prior written permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.aspectj.apache.bcel.classfile;
  55. import java.io.DataInputStream;
  56. import java.io.IOException;
  57. import java.util.ArrayList;
  58. import java.util.List;
  59. import org.aspectj.apache.bcel.Constants;
  60. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  61. import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos;
  62. import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
  63. import org.aspectj.apache.bcel.generic.Type;
  64. /**
  65. * This class represents the method info structure, i.e., the representation for a method in the class. See JVM specification for
  66. * details. A method has access flags, a name, a signature and a number of attributes.
  67. *
  68. * @version $Id: Method.java,v 1.11 2009/09/15 19:40:12 aclement Exp $
  69. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  70. */
  71. public final class Method extends FieldOrMethod {
  72. public static final AnnotationGen[][] NO_PARAMETER_ANNOTATIONS = new AnnotationGen[][] {};
  73. public static final Method[] NoMethods = new Method[0];
  74. private boolean parameterAnnotationsOutOfDate = true;
  75. private AnnotationGen[][] unpackedParameterAnnotations;
  76. private Method() {
  77. parameterAnnotationsOutOfDate = true;
  78. }
  79. /**
  80. * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a physical
  81. * copy.
  82. */
  83. public Method(Method c) {
  84. super(c);
  85. parameterAnnotationsOutOfDate = true;
  86. }
  87. Method(DataInputStream file, ConstantPool constant_pool) throws IOException {
  88. super(file, constant_pool);
  89. }
  90. public Method(int access_flags, int name_index, int signature_index, Attribute[] attributes, ConstantPool constant_pool) {
  91. super(access_flags, name_index, signature_index, attributes, constant_pool);
  92. parameterAnnotationsOutOfDate = true;
  93. }
  94. public void accept(ClassVisitor v) {
  95. v.visitMethod(this);
  96. }
  97. // CUSTARD mutable or not?
  98. @Override
  99. public void setAttributes(Attribute[] attributes) {
  100. parameterAnnotationsOutOfDate = true;
  101. super.setAttributes(attributes);
  102. }
  103. /**
  104. * @return Code attribute of method, if any
  105. */
  106. public final Code getCode() {
  107. return AttributeUtils.getCodeAttribute(attributes);
  108. }
  109. public final ExceptionTable getExceptionTable() {
  110. return AttributeUtils.getExceptionTableAttribute(attributes);
  111. }
  112. /**
  113. * Return LocalVariableTable of code attribute if any (the call is forwarded to the Code attribute)
  114. */
  115. public final LocalVariableTable getLocalVariableTable() {
  116. Code code = getCode();
  117. if (code != null)
  118. return code.getLocalVariableTable();
  119. return null;
  120. }
  121. /**
  122. * Return LineNumberTable of code attribute if any (the call is forwarded to the Code attribute)
  123. */
  124. public final LineNumberTable getLineNumberTable() {
  125. Code code = getCode();
  126. if (code != null)
  127. return code.getLineNumberTable();
  128. return null;
  129. }
  130. /**
  131. * Return string representation close to declaration format, eg: 'public static void main(String[] args) throws IOException'
  132. */
  133. @Override
  134. public final String toString() {
  135. ConstantUtf8 c;
  136. String name, signature, access; // Short cuts to constant pool
  137. StringBuilder buf;
  138. access = Utility.accessToString(modifiers);
  139. // Get name and signature from constant pool
  140. c = (ConstantUtf8) cpool.getConstant(signatureIndex, Constants.CONSTANT_Utf8);
  141. signature = c.getValue();
  142. c = (ConstantUtf8) cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8);
  143. name = c.getValue();
  144. signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable());
  145. buf = new StringBuilder(signature);
  146. for (Attribute a : attributes) {
  147. if (!((a instanceof Code) || (a instanceof ExceptionTable)))
  148. buf.append(" [" + a.toString() + "]");
  149. }
  150. ExceptionTable e = getExceptionTable();
  151. if (e != null) {
  152. String str = e.toString();
  153. if (!str.equals(""))
  154. buf.append("\n\t\tthrows " + str);
  155. }
  156. return buf.toString();
  157. }
  158. /**
  159. * @return return type of method
  160. */
  161. public Type getReturnType() {
  162. return Type.getReturnType(getSignature());
  163. }
  164. /**
  165. * @return array of method argument types
  166. */
  167. public Type[] getArgumentTypes() {
  168. return Type.getArgumentTypes(getSignature());
  169. }
  170. private void ensureParameterAnnotationsUnpacked() {
  171. if (!parameterAnnotationsOutOfDate)
  172. return;
  173. parameterAnnotationsOutOfDate = false;
  174. int parameterCount = getArgumentTypes().length;
  175. if (parameterCount == 0) {
  176. unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS;
  177. return;
  178. }
  179. RuntimeVisParamAnnos parameterAnnotationsVis = null;
  180. RuntimeInvisParamAnnos parameterAnnotationsInvis = null;
  181. // Find attributes that contain annotation data
  182. Attribute[] attrs = getAttributes();
  183. for (Attribute attribute : attrs) {
  184. if (attribute instanceof RuntimeVisParamAnnos) {
  185. parameterAnnotationsVis = (RuntimeVisParamAnnos) attribute;
  186. }
  187. else if (attribute instanceof RuntimeInvisParamAnnos) {
  188. parameterAnnotationsInvis = (RuntimeInvisParamAnnos) attribute;
  189. }
  190. }
  191. boolean foundSome = false;
  192. // Build a list of annotation arrays, one per argument
  193. if (parameterAnnotationsInvis != null || parameterAnnotationsVis != null) {
  194. List<AnnotationGen[]> annotationsForEachParameter = new ArrayList<>();
  195. AnnotationGen[] visibleOnes = null;
  196. AnnotationGen[] invisibleOnes = null;
  197. for (int i = 0; i < parameterCount; i++) {
  198. int count = 0;
  199. visibleOnes = new AnnotationGen[0];
  200. invisibleOnes = new AnnotationGen[0];
  201. if (parameterAnnotationsVis != null) {
  202. visibleOnes = parameterAnnotationsVis.getAnnotationsOnParameter(i);
  203. count += visibleOnes.length;
  204. }
  205. if (parameterAnnotationsInvis != null) {
  206. invisibleOnes = parameterAnnotationsInvis.getAnnotationsOnParameter(i);
  207. count += invisibleOnes.length;
  208. }
  209. AnnotationGen[] complete = AnnotationGen.NO_ANNOTATIONS;
  210. if (count != 0) {
  211. complete = new AnnotationGen[visibleOnes.length + invisibleOnes.length];
  212. System.arraycopy(visibleOnes, 0, complete, 0, visibleOnes.length);
  213. System.arraycopy(invisibleOnes, 0, complete, visibleOnes.length, invisibleOnes.length);
  214. foundSome = true;
  215. }
  216. annotationsForEachParameter.add(complete);
  217. }
  218. if (foundSome) {
  219. unpackedParameterAnnotations = annotationsForEachParameter.toArray(new AnnotationGen[][] {});
  220. return;
  221. }
  222. }
  223. unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS;
  224. }
  225. public AnnotationGen[] getAnnotationsOnParameter(int i) {
  226. ensureParameterAnnotationsUnpacked();
  227. if (unpackedParameterAnnotations == NO_PARAMETER_ANNOTATIONS) {
  228. return AnnotationGen.NO_ANNOTATIONS;
  229. }
  230. return unpackedParameterAnnotations[i];
  231. }
  232. public AnnotationGen[][] getParameterAnnotations() {
  233. ensureParameterAnnotationsUnpacked();
  234. return unpackedParameterAnnotations;
  235. }
  236. }