001    /*
002     * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package sun.tools.javap;
027    
028    import java.util.*;
029    import java.io.*;
030    
031    import static sun.tools.javap.RuntimeConstants.*;
032    
033    /**
034     * Strores method data informastion.
035     *
036     * @author  Sucheta Dambalkar (Adopted code from jdis)
037     */
038    public class MethodData {
039    
040        ClassData cls;
041        int access;
042        int name_index;
043        int descriptor_index;
044        int attributes_count;
045        byte[] code;
046        Vector<TrapData> exception_table = new Vector<TrapData>(0);
047        Vector<LineNumData> lin_num_tb = new Vector<LineNumData>(0);
048        Vector<LocVarData> loc_var_tb = new Vector<LocVarData>(0);
049        StackMapTableData[] stackMapTable;
050        StackMapData[] stackMap;
051        int[] exc_index_table=null;
052        Vector<AttrData> attrs=new Vector<AttrData>(0);
053        Vector<AttrData> code_attrs=new Vector<AttrData>(0);
054        int max_stack,  max_locals;
055        boolean isSynthetic=false;
056        boolean isDeprecated=false;
057    
058        public MethodData(ClassData cls){
059            this.cls=cls;
060        }
061    
062        /**
063         * Read method info.
064         */
065        public void read(DataInputStream in) throws IOException {
066            access = in.readUnsignedShort();
067            name_index=in.readUnsignedShort();
068            descriptor_index =in.readUnsignedShort();
069            int attributes_count = in.readUnsignedShort();
070            for (int i = 0; i < attributes_count; i++) {
071                int attr_name_index=in.readUnsignedShort();
072    
073            readAttr: {
074                    if (cls.getTag(attr_name_index)==CONSTANT_UTF8) {
075                        String  attr_name=cls.getString(attr_name_index);
076                        if ( attr_name.equals("Code")){
077                            readCode (in);
078                            AttrData attr=new AttrData(cls);
079                            attr.read(attr_name_index);
080                            attrs.addElement(attr);
081                            break readAttr;
082                        } else if ( attr_name.equals("Exceptions")){
083                            readExceptions(in);
084                            AttrData attr=new AttrData(cls);
085                            attr.read(attr_name_index);
086                            attrs.addElement(attr);
087                            break readAttr;
088                        } else if (attr_name.equals("Synthetic")){
089                            if (in.readInt()!=0)
090                                throw new ClassFormatError("invalid Synthetic attr length");
091                            isSynthetic=true;
092                            AttrData attr=new AttrData(cls);
093                            attr.read(attr_name_index);
094                            attrs.addElement(attr);
095                            break readAttr;
096                        } else if (attr_name.equals("Deprecated")){
097                            if (in.readInt()!=0)
098                                throw new ClassFormatError("invalid Synthetic attr length");
099                            isDeprecated = true;
100                            AttrData attr=new AttrData(cls);
101                            attr.read(attr_name_index);
102                            attrs.addElement(attr);
103                            break readAttr;
104                        }
105                    }
106                    AttrData attr=new AttrData(cls);
107                    attr.read(attr_name_index, in);
108                    attrs.addElement(attr);
109                }
110            }
111        }
112    
113        /**
114         * Read code attribute info.
115         */
116        public void readCode(DataInputStream in) throws IOException {
117    
118            int attr_length = in.readInt();
119            max_stack=in.readUnsignedShort();
120            max_locals=in.readUnsignedShort();
121            int codelen=in.readInt();
122    
123            code=new byte[codelen];
124            int totalread = 0;
125            while(totalread < codelen){
126                totalread += in.read(code, totalread, codelen-totalread);
127            }
128            //      in.read(code, 0, codelen);
129            int clen = 0;
130            readExceptionTable(in);
131            int code_attributes_count = in.readUnsignedShort();
132    
133            for (int k = 0 ; k < code_attributes_count ; k++) {
134                int table_name_index=in.readUnsignedShort();
135                int table_name_tag=cls.getTag(table_name_index);
136                AttrData attr=new AttrData(cls);
137                if (table_name_tag==CONSTANT_UTF8) {
138                    String table_name_tstr=cls.getString(table_name_index);
139                    if (table_name_tstr.equals("LineNumberTable")) {
140                        readLineNumTable(in);
141                        attr.read(table_name_index);
142                    } else if (table_name_tstr.equals("LocalVariableTable")) {
143                        readLocVarTable(in);
144                        attr.read(table_name_index);
145                    } else if (table_name_tstr.equals("StackMapTable")) {
146                        readStackMapTable(in);
147                        attr.read(table_name_index);
148                    } else if (table_name_tstr.equals("StackMap")) {
149                        readStackMap(in);
150                        attr.read(table_name_index);
151                    } else {
152                        attr.read(table_name_index, in);
153                    }
154                    code_attrs.addElement(attr);
155                    continue;
156                }
157    
158                attr.read(table_name_index, in);
159                code_attrs.addElement(attr);
160            }
161        }
162    
163        /**
164         * Read exception table info.
165         */
166        void readExceptionTable (DataInputStream in) throws IOException {
167            int exception_table_len=in.readUnsignedShort();
168            exception_table=new Vector<TrapData>(exception_table_len);
169            for (int l = 0; l < exception_table_len; l++) {
170                exception_table.addElement(new TrapData(in, l));
171            }
172        }
173    
174        /**
175         * Read LineNumberTable attribute info.
176         */
177        void readLineNumTable (DataInputStream in) throws IOException {
178            int attr_len = in.readInt(); // attr_length
179            int lin_num_tb_len = in.readUnsignedShort();
180            lin_num_tb=new Vector<LineNumData>(lin_num_tb_len);
181            for (int l = 0; l < lin_num_tb_len; l++) {
182                lin_num_tb.addElement(new LineNumData(in));
183            }
184        }
185    
186        /**
187         * Read LocalVariableTable attribute info.
188         */
189        void readLocVarTable (DataInputStream in) throws IOException {
190            int attr_len=in.readInt(); // attr_length
191            int loc_var_tb_len = in.readUnsignedShort();
192            loc_var_tb = new Vector<LocVarData>(loc_var_tb_len);
193            for (int l = 0; l < loc_var_tb_len; l++) {
194                loc_var_tb.addElement(new LocVarData(in));
195            }
196        }
197    
198        /**
199         * Read Exception attribute info.
200         */
201        public void readExceptions(DataInputStream in) throws IOException {
202            int attr_len=in.readInt(); // attr_length in prog
203            int num_exceptions = in.readUnsignedShort();
204            exc_index_table=new int[num_exceptions];
205            for (int l = 0; l < num_exceptions; l++) {
206                int exc=in.readShort();
207                exc_index_table[l]=exc;
208            }
209        }
210    
211        /**
212         * Read StackMapTable attribute info.
213         */
214        void readStackMapTable(DataInputStream in) throws IOException {
215            int attr_len = in.readInt();  //attr_length
216            int stack_map_tb_len = in.readUnsignedShort();
217            stackMapTable = new StackMapTableData[stack_map_tb_len];
218            for (int i=0; i<stack_map_tb_len; i++) {
219                stackMapTable[i] = StackMapTableData.getInstance(in, this);
220            }
221        }
222    
223        /**
224         * Read StackMap attribute info.
225         */
226        void readStackMap(DataInputStream in) throws IOException {
227            int attr_len = in.readInt();  //attr_length
228            int stack_map_len = in.readUnsignedShort();
229            stackMap = new StackMapData[stack_map_len];
230            for (int i = 0; i<stack_map_len; i++) {
231                stackMap[i] = new StackMapData(in, this);
232            }
233        }
234    
235        /**
236         * Return access of the method.
237         */
238        public String[] getAccess(){
239    
240            Vector<String> v = new Vector<String>();
241            if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
242            if ((access & ACC_PRIVATE)   !=0) v.addElement("private");
243            if ((access & ACC_PROTECTED)   !=0) v.addElement("protected");
244            if ((access & ACC_STATIC)   !=0) v.addElement("static");
245            if ((access & ACC_FINAL)    !=0) v.addElement("final");
246            if ((access & ACC_SYNCHRONIZED) !=0) v.addElement("synchronized");
247            if ((access & ACC_NATIVE) !=0) v.addElement("native");
248            if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
249            if ((access & ACC_STRICT) !=0) v.addElement("strictfp");
250    
251            String[] accflags = new String[v.size()];
252            v.copyInto(accflags);
253            return accflags;
254        }
255    
256        /**
257         * Return name of the method.
258         */
259        public String getName(){
260            return cls.getStringValue(name_index);
261        }
262    
263        /**
264         * Return internal siganature of the method.
265         */
266        public String getInternalSig(){
267            return cls.getStringValue(descriptor_index);
268        }
269    
270        /**
271         * Return java return type signature of method.
272         */
273        public String getReturnType(){
274    
275            String rttype = (new TypeSignature(getInternalSig())).getReturnType();
276            return rttype;
277        }
278    
279        /**
280         * Return java type parameter signature.
281         */
282        public String getParameters(){
283            String ptype = (new TypeSignature(getInternalSig())).getParameters();
284    
285            return ptype;
286        }
287    
288        /**
289         * Return code attribute data of a method.
290         */
291        public byte[] getCode(){
292            return code;
293        }
294    
295        /**
296         * Return LineNumberTable size.
297         */
298        public int getnumlines(){
299            return lin_num_tb.size();
300        }
301    
302        /**
303         * Return LineNumberTable
304         */
305        public Vector<?> getlin_num_tb(){
306            return lin_num_tb;
307        }
308    
309        /**
310         * Return LocalVariableTable size.
311         */
312        public int getloc_var_tbsize(){
313            return loc_var_tb.size();
314        }
315    
316    
317        /**
318         * Return LocalVariableTable.
319         */
320        public Vector<?> getloc_var_tb(){
321            return loc_var_tb;
322        }
323    
324        /**
325         * Return StackMap.
326         */
327        public StackMapData[] getStackMap() {
328            return stackMap;
329        }
330    
331        /**
332         * Return StackMapTable.
333         */
334        public StackMapTableData[] getStackMapTable() {
335            return stackMapTable;
336        }
337    
338        /**
339         * Return number of arguments of that method.
340         */
341        public int getArgumentlength(){
342            return new TypeSignature(getInternalSig()).getArgumentlength();
343        }
344    
345        /**
346         * Return true if method is static
347         */
348        public boolean isStatic(){
349            if ((access & ACC_STATIC)   !=0) return true;
350            return false;
351        }
352    
353    
354        /**
355         * Return max depth of operand stack.
356         */
357        public int getMaxStack(){
358            return  max_stack;
359        }
360    
361    
362        /**
363         * Return number of local variables.
364         */
365        public int getMaxLocals(){
366            return max_locals;
367        }
368    
369    
370        /**
371         * Return exception index table in Exception attribute.
372         */
373        public int []get_exc_index_table(){
374            return  exc_index_table;
375        }
376    
377    
378        /**
379         * Return exception table in code attributre.
380         */
381        public Vector<?> getexception_table(){
382            return exception_table;
383        }
384    
385    
386        /**
387         * Return method attributes.
388         */
389        public Vector<?> getAttributes(){
390            return attrs;
391        }
392    
393    
394        /**
395         * Return code attributes.
396         */
397        public Vector<?> getCodeAttributes(){
398            return code_attrs;
399        }
400    
401    
402        /**
403         * Return true if method id synthetic.
404         */
405        public boolean isSynthetic(){
406            return isSynthetic;
407        }
408    
409    
410        /**
411         * Return true if method is deprecated.
412         */
413        public boolean isDeprecated(){
414            return isDeprecated;
415        }
416    }