KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > bytecode > MethodInfo


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 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
16 package javassist.bytecode;
17
18 import java.io.DataInputStream JavaDoc;
19 import java.io.DataOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 /**
26  * <code>method_info</code> structure.
27  *
28  * @see javassist.CtMethod#getMethodInfo()
29  * @see javassist.CtConstructor#getMethodInfo()
30  */

31 public final class MethodInfo {
32     ConstPool constPool;
33     int accessFlags;
34     int name;
35     int descriptor;
36     LinkedList JavaDoc attribute; // may be null
37

38     // Bill, do you really need this?
39
// public Exception created = new Exception();
40

41     /**
42      * The name of constructors: <code>&lt;init&gt</code>.
43      */

44     public static final String JavaDoc nameInit = "<init>";
45
46     /**
47      * The name of class initializer (static initializer):
48      * <code>&lt;clinit&gt</code>.
49      */

50     public static final String JavaDoc nameClinit = "<clinit>";
51
52     private MethodInfo(ConstPool cp) {
53         constPool = cp;
54         attribute = null;
55     }
56
57     /**
58      * Constructs a <code>method_info</code> structure. The initial value of
59      * <code>access_flags</code> is zero.
60      *
61      * @param cp
62      * a constant pool table
63      * @param methodname
64      * method name
65      * @param desc
66      * method descriptor
67      * @see Descriptor
68      */

69     public MethodInfo(ConstPool cp, String JavaDoc methodname, String JavaDoc desc) {
70         this(cp);
71         accessFlags = 0;
72         name = cp.addUtf8Info(methodname);
73         descriptor = constPool.addUtf8Info(desc);
74     }
75
76     MethodInfo(ConstPool cp, DataInputStream JavaDoc in) throws IOException JavaDoc {
77         this(cp);
78         read(in);
79     }
80
81     /**
82      * Constructs a copy of <code>method_info</code> structure. Class names
83      * appearing in the source <code>method_info</code> are renamed according
84      * to <code>classnameMap</code>.
85      *
86      * <p>
87      * Note: only <code>Code</code> and <code>Exceptions</code> attributes
88      * are copied from the source. The other attributes are ignored.
89      *
90      * @param cp
91      * a constant pool table
92      * @param methodname
93      * a method name
94      * @param src
95      * a source <code>method_info</code>
96      * @param classnameMap
97      * specifies pairs of replaced and substituted name.
98      * @see Descriptor
99      */

100     public MethodInfo(ConstPool cp, String JavaDoc methodname, MethodInfo src,
101             Map JavaDoc classnameMap) throws BadBytecode {
102         this(cp);
103         read(src, methodname, classnameMap);
104     }
105
106     /**
107      * Returns a string representation of the object.
108      */

109     public String JavaDoc toString() {
110         return constPool.getUtf8Info(name) + " "
111                 + constPool.getUtf8Info(descriptor);
112     }
113
114     /**
115      * Copies all constant pool items to a given new constant pool
116      * and replaces the original items with the new ones.
117      * This is used for garbage collecting the items of removed fields
118      * and methods.
119      *
120      * @param cp the destination
121      */

122     void compact(ConstPool cp) {
123         name = cp.addUtf8Info(getName());
124         descriptor = cp.addUtf8Info(getDescriptor());
125         attribute = AttributeInfo.copyAll(attribute, cp);
126         constPool = cp;
127     }
128
129     void prune(ConstPool cp) {
130         attribute = null;
131         name = cp.addUtf8Info(getName());
132         descriptor = cp.addUtf8Info(getDescriptor());
133         constPool = cp;
134     }
135
136     /**
137      * Returns a method name.
138      */

139     public String JavaDoc getName() {
140         return constPool.getUtf8Info(name);
141     }
142
143     /**
144      * Sets a method name.
145      */

146     public void setName(String JavaDoc newName) {
147         name = constPool.addUtf8Info(newName);
148     }
149
150     /**
151      * Returns true if this is not a constructor or a class initializer (static
152      * initializer).
153      */

154     public boolean isMethod() {
155         String JavaDoc n = getName();
156         return !n.equals(nameInit) && !n.equals(nameClinit);
157     }
158
159     /**
160      * Returns a constant pool table used by this method.
161      */

162     public ConstPool getConstPool() {
163         return constPool;
164     }
165
166     /**
167      * Returns true if this is a constructor.
168      */

169     public boolean isConstructor() {
170         return getName().equals(nameInit);
171     }
172
173     /**
174      * Returns true if this is a class initializer (static initializer).
175      */

176     public boolean isStaticInitializer() {
177         return getName().equals(nameClinit);
178     }
179
180     /**
181      * Returns access flags.
182      *
183      * @see AccessFlag
184      */

185     public int getAccessFlags() {
186         return accessFlags;
187     }
188
189     /**
190      * Sets access flags.
191      *
192      * @see AccessFlag
193      */

194     public void setAccessFlags(int acc) {
195         accessFlags = acc;
196     }
197
198     /**
199      * Returns a method descriptor.
200      *
201      * @see Descriptor
202      */

203     public String JavaDoc getDescriptor() {
204         return constPool.getUtf8Info(descriptor);
205     }
206
207     /**
208      * Sets a method descriptor.
209      *
210      * @see Descriptor
211      */

212     public void setDescriptor(String JavaDoc desc) {
213         if (!desc.equals(getDescriptor()))
214             descriptor = constPool.addUtf8Info(desc);
215     }
216
217     /**
218      * Returns all the attributes. A new element can be added to the returned
219      * list and an existing element can be removed from the list.
220      *
221      * @return a list of <code>AttributeInfo</code> objects.
222      * @see AttributeInfo
223      */

224     public List JavaDoc getAttributes() {
225         if (attribute == null)
226             attribute = new LinkedList JavaDoc();
227
228         return attribute;
229     }
230
231     /**
232      * Returns the attribute with the specified name. If it is not found, this
233      * method returns null.
234      *
235      * @param name
236      * attribute name
237      * @return an <code>AttributeInfo</code> object or null.
238      */

239     public AttributeInfo getAttribute(String JavaDoc name) {
240         return AttributeInfo.lookup(attribute, name);
241     }
242
243     /**
244      * Appends an attribute. If there is already an attribute with the same
245      * name, the new one substitutes for it.
246      */

247     public void addAttribute(AttributeInfo info) {
248         if (attribute == null)
249             attribute = new LinkedList JavaDoc();
250
251         AttributeInfo.remove(attribute, info.getName());
252         attribute.add(info);
253     }
254
255     /**
256      * Returns an Exceptions attribute.
257      *
258      * @return an Exceptions attribute or null if it is not specified.
259      */

260     public ExceptionsAttribute getExceptionsAttribute() {
261         AttributeInfo info = AttributeInfo.lookup(attribute,
262                 ExceptionsAttribute.tag);
263         return (ExceptionsAttribute)info;
264     }
265
266     /**
267      * Returns a Code attribute.
268      *
269      * @return a Code attribute or null if it is not specified.
270      */

271     public CodeAttribute getCodeAttribute() {
272         AttributeInfo info = AttributeInfo.lookup(attribute, CodeAttribute.tag);
273         return (CodeAttribute)info;
274     }
275
276     /**
277      * Removes an Exception attribute.
278      */

279     public void removeExceptionsAttribute() {
280         AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
281     }
282
283     /**
284      * Adds an Exception attribute.
285      *
286      * <p>
287      * The added attribute must share the same constant pool table as this
288      * <code>method_info</code> structure.
289      */

290     public void setExceptionsAttribute(ExceptionsAttribute cattr) {
291         removeExceptionsAttribute();
292         if (attribute == null)
293             attribute = new LinkedList JavaDoc();
294
295         attribute.add(cattr);
296     }
297
298     /**
299      * Removes a Code attribute.
300      */

301     public void removeCodeAttribute() {
302         AttributeInfo.remove(attribute, CodeAttribute.tag);
303     }
304
305     /**
306      * Adds a Code attribute.
307      *
308      * <p>
309      * The added attribute must share the same constant pool table as this
310      * <code>method_info</code> structure.
311      */

312     public void setCodeAttribute(CodeAttribute cattr) {
313         removeCodeAttribute();
314         if (attribute == null)
315             attribute = new LinkedList JavaDoc();
316
317         attribute.add(cattr);
318     }
319
320     /**
321      * Returns the line number of the source line corresponding to the specified
322      * bytecode contained in this method.
323      *
324      * @param pos
325      * the position of the bytecode (&gt;= 0). an index into the code
326      * array.
327      * @return -1 if this information is not available.
328      */

329     public int getLineNumber(int pos) {
330         CodeAttribute ca = getCodeAttribute();
331         if (ca == null)
332             return -1;
333
334         LineNumberAttribute ainfo = (LineNumberAttribute)ca
335                 .getAttribute(LineNumberAttribute.tag);
336         if (ainfo == null)
337             return -1;
338
339         return ainfo.toLineNumber(pos);
340     }
341
342     /**
343      * Changes a super constructor called by this constructor.
344      *
345      * <p>
346      * This method modifies a call to <code>super()</code>, which should be
347      * at the head of a constructor body, so that a constructor in a different
348      * super class is called. This method does not change actural parameters.
349      * Hence the new super class must have a constructor with the same signature
350      * as the original one.
351      *
352      * <p>
353      * This method should be called when the super class of the class declaring
354      * this method is changed.
355      *
356      * <p>
357      * This method does not perform anything unless this <code>MethodInfo</code>
358      * represents a constructor.
359      *
360      * @param superclass
361      * the new super class
362      */

363     public void setSuperclass(String JavaDoc superclass) throws BadBytecode {
364         if (!isConstructor())
365             return;
366
367         CodeAttribute ca = getCodeAttribute();
368         byte[] code = ca.getCode();
369         CodeIterator iterator = ca.iterator();
370         int pos = iterator.skipSuperConstructor();
371         if (pos >= 0) { // not this()
372
ConstPool cp = constPool;
373             int mref = ByteArray.readU16bit(code, pos + 1);
374             int nt = cp.getMethodrefNameAndType(mref);
375             int sc = cp.addClassInfo(superclass);
376             int mref2 = cp.addMethodrefInfo(sc, nt);
377             ByteArray.write16bit(mref2, code, pos + 1);
378         }
379     }
380
381     private void read(MethodInfo src, String JavaDoc methodname, Map JavaDoc classnames)
382             throws BadBytecode {
383         ConstPool destCp = constPool;
384         accessFlags = src.accessFlags;
385         name = destCp.addUtf8Info(methodname);
386
387         ConstPool srcCp = src.constPool;
388         String JavaDoc desc = srcCp.getUtf8Info(src.descriptor);
389         String JavaDoc desc2 = Descriptor.rename(desc, classnames);
390         descriptor = destCp.addUtf8Info(desc2);
391
392         attribute = new LinkedList JavaDoc();
393         ExceptionsAttribute eattr = src.getExceptionsAttribute();
394         if (eattr != null)
395             attribute.add(eattr.copy(destCp, classnames));
396
397         CodeAttribute cattr = src.getCodeAttribute();
398         if (cattr != null)
399             attribute.add(cattr.copy(destCp, classnames));
400     }
401
402     private void read(DataInputStream JavaDoc in) throws IOException JavaDoc {
403         accessFlags = in.readUnsignedShort();
404         name = in.readUnsignedShort();
405         descriptor = in.readUnsignedShort();
406         int n = in.readUnsignedShort();
407         attribute = new LinkedList JavaDoc();
408         for (int i = 0; i < n; ++i)
409             attribute.add(AttributeInfo.read(constPool, in));
410     }
411
412     void write(DataOutputStream JavaDoc out) throws IOException JavaDoc {
413         out.writeShort(accessFlags);
414         out.writeShort(name);
415         out.writeShort(descriptor);
416
417         if (attribute == null)
418             out.writeShort(0);
419         else {
420             out.writeShort(attribute.size());
421             AttributeInfo.writeAll(attribute, out);
422         }
423     }
424 }
425
Popular Tags