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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. StringBuffer 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 StringBuffer(signature);
  146. for (int i = 0; i < attributes.length; i++) {
  147. Attribute a = attributes[i];
  148. if (!((a instanceof Code) || (a instanceof ExceptionTable)))
  149. buf.append(" [" + a.toString() + "]");
  150. }
  151. ExceptionTable e = getExceptionTable();
  152. if (e != null) {
  153. String str = e.toString();
  154. if (!str.equals(""))
  155. buf.append("\n\t\tthrows " + str);
  156. }
  157. return buf.toString();
  158. }
  159. /**
  160. * @return return type of method
  161. */
  162. public Type getReturnType() {
  163. return Type.getReturnType(getSignature());
  164. }
  165. /**
  166. * @return array of method argument types
  167. */
  168. public Type[] getArgumentTypes() {
  169. return Type.getArgumentTypes(getSignature());
  170. }
  171. private void ensureParameterAnnotationsUnpacked() {
  172. if (!parameterAnnotationsOutOfDate)
  173. return;
  174. parameterAnnotationsOutOfDate = false;
  175. int parameterCount = getArgumentTypes().length;
  176. if (parameterCount == 0) {
  177. unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS;
  178. return;
  179. }
  180. RuntimeVisParamAnnos parameterAnnotationsVis = null;
  181. RuntimeInvisParamAnnos parameterAnnotationsInvis = null;
  182. // Find attributes that contain annotation data
  183. Attribute[] attrs = getAttributes();
  184. for (int i = 0; i < attrs.length; i++) {
  185. Attribute attribute = attrs[i];
  186. if (attribute instanceof RuntimeVisParamAnnos) {
  187. parameterAnnotationsVis = (RuntimeVisParamAnnos) attribute;
  188. } else if (attribute instanceof RuntimeInvisParamAnnos) {
  189. parameterAnnotationsInvis = (RuntimeInvisParamAnnos) attribute;
  190. }
  191. }
  192. boolean foundSome = false;
  193. // Build a list of annotation arrays, one per argument
  194. if (parameterAnnotationsInvis != null || parameterAnnotationsVis != null) {
  195. List<AnnotationGen[]> annotationsForEachParameter = new ArrayList<AnnotationGen[]>();
  196. AnnotationGen[] visibleOnes = null;
  197. AnnotationGen[] invisibleOnes = null;
  198. for (int i = 0; i < parameterCount; i++) {
  199. int count = 0;
  200. visibleOnes = new AnnotationGen[0];
  201. invisibleOnes = new AnnotationGen[0];
  202. if (parameterAnnotationsVis != null) {
  203. visibleOnes = parameterAnnotationsVis.getAnnotationsOnParameter(i);
  204. count += visibleOnes.length;
  205. }
  206. if (parameterAnnotationsInvis != null) {
  207. invisibleOnes = parameterAnnotationsInvis.getAnnotationsOnParameter(i);
  208. count += invisibleOnes.length;
  209. }
  210. AnnotationGen[] complete = AnnotationGen.NO_ANNOTATIONS;
  211. if (count != 0) {
  212. complete = new AnnotationGen[visibleOnes.length + invisibleOnes.length];
  213. System.arraycopy(visibleOnes, 0, complete, 0, visibleOnes.length);
  214. System.arraycopy(invisibleOnes, 0, complete, visibleOnes.length, invisibleOnes.length);
  215. foundSome = true;
  216. }
  217. annotationsForEachParameter.add(complete);
  218. }
  219. if (foundSome) {
  220. unpackedParameterAnnotations = annotationsForEachParameter.toArray(new AnnotationGen[][] {});
  221. return;
  222. }
  223. }
  224. unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS;
  225. }
  226. public AnnotationGen[] getAnnotationsOnParameter(int i) {
  227. ensureParameterAnnotationsUnpacked();
  228. if (unpackedParameterAnnotations == NO_PARAMETER_ANNOTATIONS) {
  229. return AnnotationGen.NO_ANNOTATIONS;
  230. }
  231. return unpackedParameterAnnotations[i];
  232. }
  233. public AnnotationGen[][] getParameterAnnotations() {
  234. ensureParameterAnnotationsUnpacked();
  235. return unpackedParameterAnnotations;
  236. }
  237. }