001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License. 
016     *
017     */
018    package org.apache.bcel.classfile;
019    
020    import java.io.DataInputStream;
021    import java.io.DataOutputStream;
022    import java.io.IOException;
023    import java.io.Serializable;
024    
025    /**
026     * This class represents a stack map entry recording the types of
027     * local variables and the the of stack items at a given byte code offset.
028     * See CLDC specification �5.3.1.2
029     *
030     * @version $Id: StackMapEntry.java 1152077 2011-07-29 02:29:42Z dbrosius $
031     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
032     * @see     StackMap
033     * @see     StackMapType
034     */
035    public final class StackMapEntry implements Cloneable, Serializable {
036    
037        private static final long serialVersionUID = 1L;
038    
039        private int byte_code_offset;
040        private int number_of_locals;
041        private StackMapType[] types_of_locals;
042        private int number_of_stack_items;
043        private StackMapType[] types_of_stack_items;
044        private ConstantPool constant_pool;
045    
046    
047        /**
048         * Construct object from file stream.
049         * @param file Input stream
050         * @throws IOException
051         */
052        StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException {
053            this(file.readShort(), file.readShort(), null, -1, null, constant_pool);
054            types_of_locals = new StackMapType[number_of_locals];
055            for (int i = 0; i < number_of_locals; i++) {
056                types_of_locals[i] = new StackMapType(file, constant_pool);
057            }
058            number_of_stack_items = file.readShort();
059            types_of_stack_items = new StackMapType[number_of_stack_items];
060            for (int i = 0; i < number_of_stack_items; i++) {
061                types_of_stack_items[i] = new StackMapType(file, constant_pool);
062            }
063        }
064    
065    
066        public StackMapEntry(int byte_code_offset, int number_of_locals,
067                StackMapType[] types_of_locals, int number_of_stack_items,
068                StackMapType[] types_of_stack_items, ConstantPool constant_pool) {
069            this.byte_code_offset = byte_code_offset;
070            this.number_of_locals = number_of_locals;
071            this.types_of_locals = types_of_locals;
072            this.number_of_stack_items = number_of_stack_items;
073            this.types_of_stack_items = types_of_stack_items;
074            this.constant_pool = constant_pool;
075        }
076    
077    
078        /**
079         * Dump stack map entry
080         *
081         * @param file Output file stream
082         * @throws IOException
083         */
084        public final void dump( DataOutputStream file ) throws IOException {
085            file.writeShort(byte_code_offset);
086            file.writeShort(number_of_locals);
087            for (int i = 0; i < number_of_locals; i++) {
088                types_of_locals[i].dump(file);
089            }
090            file.writeShort(number_of_stack_items);
091            for (int i = 0; i < number_of_stack_items; i++) {
092                types_of_stack_items[i].dump(file);
093            }
094        }
095    
096    
097        /**
098         * @return String representation.
099         */
100        @Override
101        public final String toString() {
102            StringBuilder buf = new StringBuilder(64);
103            buf.append("(offset=").append(byte_code_offset);
104            if (number_of_locals > 0) {
105                buf.append(", locals={");
106                for (int i = 0; i < number_of_locals; i++) {
107                    buf.append(types_of_locals[i]);
108                    if (i < number_of_locals - 1) {
109                        buf.append(", ");
110                    }
111                }
112                buf.append("}");
113            }
114            if (number_of_stack_items > 0) {
115                buf.append(", stack items={");
116                for (int i = 0; i < number_of_stack_items; i++) {
117                    buf.append(types_of_stack_items[i]);
118                    if (i < number_of_stack_items - 1) {
119                        buf.append(", ");
120                    }
121                }
122                buf.append("}");
123            }
124            buf.append(")");
125            return buf.toString();
126        }
127    
128    
129        public void setByteCodeOffset( int b ) {
130            byte_code_offset = b;
131        }
132    
133    
134        public int getByteCodeOffset() {
135            return byte_code_offset;
136        }
137    
138    
139        public void setNumberOfLocals( int n ) {
140            number_of_locals = n;
141        }
142    
143    
144        public int getNumberOfLocals() {
145            return number_of_locals;
146        }
147    
148    
149        public void setTypesOfLocals( StackMapType[] t ) {
150            types_of_locals = t;
151        }
152    
153    
154        public StackMapType[] getTypesOfLocals() {
155            return types_of_locals;
156        }
157    
158    
159        public void setNumberOfStackItems( int n ) {
160            number_of_stack_items = n;
161        }
162    
163    
164        public int getNumberOfStackItems() {
165            return number_of_stack_items;
166        }
167    
168    
169        public void setTypesOfStackItems( StackMapType[] t ) {
170            types_of_stack_items = t;
171        }
172    
173    
174        public StackMapType[] getTypesOfStackItems() {
175            return types_of_stack_items;
176        }
177    
178    
179        /**
180         * @return deep copy of this object
181         */
182        public StackMapEntry copy() {
183            try {
184                return (StackMapEntry) clone();
185            } catch (CloneNotSupportedException e) {
186            }
187            return null;
188        }
189    
190    
191        /**
192         * Called by objects that are traversing the nodes of the tree implicitely
193         * defined by the contents of a Java class. I.e., the hierarchy of methods,
194         * fields, attributes, etc. spawns a tree of objects.
195         *
196         * @param v Visitor object
197         */
198        public void accept( Visitor v ) {
199            v.visitStackMapEntry(this);
200        }
201    
202    
203        /**
204         * @return Constant pool used by this object.
205         */
206        public final ConstantPool getConstantPool() {
207            return constant_pool;
208        }
209    
210    
211        /**
212         * @param constant_pool Constant pool to be used for this object.
213         */
214        public final void setConstantPool( ConstantPool constant_pool ) {
215            this.constant_pool = constant_pool;
216        }
217    }