View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software 
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License.
16   */
17  
18  
19  package org.apache.jdo.impl.enhancer.classfile;
20  
21  import java.io.*;
22  import java.util.Vector;
23  import java.util.Stack;
24  import java.util.Enumeration;
25  
26  /***
27   * ClassMethod models the static and non-static methods of a class within
28   * a class file.  This includes constructors and initializer code.
29   */
30  public class ClassMethod extends ClassMember {
31      /* The name of the constructor code */
32      public final static String intializerName = "<init>";
33  
34      /* The name of the static initializer code */
35      public final static String staticIntializerName = "<clinit>";
36  
37      /* access flag bit mask - see VMConstants */
38      private int accessFlags;
39  
40      /* The name of the method */
41      private ConstUtf8 methodName;
42  
43      /* The type signature of the method */
44      private ConstUtf8 methodSignature;
45  
46      /* The attributes associated with the field */
47      private AttributeVector methodAttributes;
48    
49    
50      /* public accessors */
51  
52      /***
53       * Return the access flags for the method - see VMConstants
54       */
55      public int access() {
56          return accessFlags;
57      }
58  
59      /***
60       * Update the access flags for the field - see VMConstants
61       */
62      public void setAccess(int newFlags) {
63          accessFlags = newFlags;
64      }
65  
66      /***
67       * Is the method abstract?
68       */
69      public boolean isAbstract() {
70          return (accessFlags & ACCAbstract) != 0;
71      }
72  
73      /***
74       * Is the method native?
75       */
76      public boolean isNative() {
77          return (accessFlags & ACCNative) != 0;
78      }
79  
80      /***
81       * Return the name of the method
82       */
83      public ConstUtf8 name() {
84          return methodName;
85      }
86  
87      /***
88       * Change the name of the method
89       */
90      public void changeName(ConstUtf8 name) {
91          methodName = name;
92      }
93  
94      /***
95       * Return the type signature of the method
96       */
97      public ConstUtf8 signature() {
98          return methodSignature;
99      }
100 
101     /***
102      * Change the type signature of the method
103      */
104     public void changeSignature(ConstUtf8 newSig) {
105         methodSignature = newSig;
106     }
107 
108     /***
109      * Return the attributes associated with the method
110      */
111     public AttributeVector attributes() {
112         return methodAttributes;
113     }
114 
115     /***
116      * Construct a class method object
117      */
118   
119     public ClassMethod(int accFlags, ConstUtf8 name, ConstUtf8 sig,
120                        AttributeVector methodAttrs) {
121         accessFlags = accFlags;
122         methodName = name;
123         methodSignature = sig;
124         methodAttributes = methodAttrs;
125     }
126 
127     /***
128      * Returns the size of the method byteCode (if any)
129      */
130     int codeSize() {
131         CodeAttribute codeAttr = codeAttribute();
132         return (codeAttr == null) ? 0  : codeAttr.codeSize();
133     }
134 
135     /***
136      * Returns the CodeAttribute associated with this method (if any)
137      */
138     public CodeAttribute codeAttribute() {
139         Enumeration e = methodAttributes.elements();
140         while (e.hasMoreElements()) {
141             ClassAttribute attr = (ClassAttribute) e.nextElement();
142             if (attr instanceof CodeAttribute)
143                 return (CodeAttribute) attr;
144         }
145         return null;
146     }
147 
148     /***
149      * Returns the ExceptionsAttribute associated with this method (if any)
150      */
151     //@olsen: added method
152     public ExceptionsAttribute exceptionsAttribute() {
153         Enumeration e = methodAttributes.elements();
154         while (e.hasMoreElements()) {
155             ClassAttribute attr = (ClassAttribute) e.nextElement();
156             if (attr instanceof ExceptionsAttribute)
157                 return (ExceptionsAttribute) attr;
158         }
159         return null;
160     }
161 
162     /***
163      * Compares this instance with another for structural equality.
164      */
165     //@olsen: added method
166     public boolean isEqual(Stack msg, Object obj) {
167         if (!(obj instanceof ClassMethod)) {
168             msg.push("obj/obj.getClass() = "
169                      + (obj == null ? null : obj.getClass()));
170             msg.push("this.getClass() = "
171                      + this.getClass());
172             return false;
173         }
174         ClassMethod other = (ClassMethod)obj;
175 
176         if (!super.isEqual(msg, other)) {
177             return false;
178         }
179 
180         if (this.accessFlags != other.accessFlags) {
181             msg.push(String.valueOf("accessFlags = 0x"
182                                     + Integer.toHexString(other.accessFlags)));
183             msg.push(String.valueOf("accessFlags = 0x"
184                                     + Integer.toHexString(this.accessFlags)));
185             return false;
186         }
187         if (!this.methodName.isEqual(msg, other.methodName)) {
188             msg.push(String.valueOf("methodName = "
189                                     + other.methodName));
190             msg.push(String.valueOf("methodName = "
191                                     + this.methodName));
192             return false;
193         }
194         if (!this.methodSignature.isEqual(msg, other.methodSignature)) {
195             msg.push(String.valueOf("methodSignature = "
196                                     + other.methodSignature));
197             msg.push(String.valueOf("methodSignature = "
198                                     + this.methodSignature));
199             return false;
200         }
201         if (!this.methodAttributes.isEqual(msg, other.methodAttributes)) {
202             msg.push(String.valueOf("methodAttributes = "
203                                     + other.methodAttributes));
204             msg.push(String.valueOf("methodAttributes = "
205                                     + this.methodAttributes));
206             return false;
207         }
208         return true;
209     }
210 
211     //@olsen: made public
212     public void print(PrintStream out, int indent) {
213         ClassPrint.spaces(out, indent);
214         out.print("'" + methodName.asString() + "'");
215         out.print(" sig = " + methodSignature.asString());
216         out.print(" accessFlags = " + Integer.toString(accessFlags));
217         out.println(" attributes:");
218         methodAttributes.print(out, indent+2);
219     }
220 
221     /* package local methods *//package-summary/html">class="comment"> package local methods *//package-summary.html">/* package local methods *//package-summary.html">class="comment"> package local methods */
222 
223     static ClassMethod read(DataInputStream data, ConstantPool pool) 
224         throws IOException {
225         int accessFlags = data.readUnsignedShort();
226         int nameIndex = data.readUnsignedShort();
227         int sigIndex = data.readUnsignedShort();
228         ClassMethod f = 
229             new ClassMethod(accessFlags, 
230                             (ConstUtf8) pool.constantAt(nameIndex),
231                             (ConstUtf8) pool.constantAt(sigIndex),
232                             null);
233 
234         f.methodAttributes = AttributeVector.readAttributes(data, pool);
235         return f;
236     }
237 
238     void write(DataOutputStream data) throws IOException {
239         CodeAttribute codeAttr = codeAttribute();
240         data.writeShort(accessFlags);
241         data.writeShort(methodName.getIndex());
242         data.writeShort(methodSignature.getIndex());
243         methodAttributes.write(data);
244     }
245 }
246 
247