KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cojen > classfile > attribute > LocalVariableTableAttr


1 /*
2  * Copyright 2004 Brian S O'Neill
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.cojen.classfile.attribute;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Set JavaDoc;
25 import java.io.DataInput JavaDoc;
26 import java.io.DataOutput JavaDoc;
27 import java.io.IOException JavaDoc;
28 import org.cojen.classfile.Attribute;
29 import org.cojen.classfile.ConstantPool;
30 import org.cojen.classfile.FixedLocation;
31 import org.cojen.classfile.LocalVariable;
32 import org.cojen.classfile.Location;
33 import org.cojen.classfile.LocationRange;
34 import org.cojen.classfile.LocationRangeImpl;
35 import org.cojen.classfile.TypeDesc;
36 import org.cojen.classfile.constant.ConstantUTFInfo;
37
38 /**
39  * This class corresponds to the LocalVariableTable_attribute structure as
40  * defined in section 4.7.7 of <i>The Java Virtual Machine Specification</i>.
41  *
42  * @author Brian S O'Neill
43  */

44 public class LocalVariableTableAttr extends Attribute {
45
46     private List JavaDoc mEntries = new ArrayList JavaDoc(10);
47     private List JavaDoc mCleanEntries;
48     private int mRangeCount;
49     
50     public LocalVariableTableAttr(ConstantPool cp) {
51         super(cp, LOCAL_VARIABLE_TABLE);
52     }
53     
54     public LocalVariableTableAttr(ConstantPool cp, String JavaDoc name) {
55         super(cp, name);
56     }
57
58     public LocalVariableTableAttr(ConstantPool cp, String JavaDoc name, int length, DataInput JavaDoc din)
59         throws IOException JavaDoc
60     {
61         super(cp, name);
62
63         int size = din.readUnsignedShort();
64         for (int i=0; i<size; i++) {
65             int start_pc = din.readUnsignedShort();
66             int end_pc = start_pc + din.readUnsignedShort() + 1;
67             int name_index = din.readUnsignedShort();
68             int descriptor_index = din.readUnsignedShort();
69             final int index = din.readUnsignedShort();
70
71             final ConstantUTFInfo varName =
72                 (ConstantUTFInfo)cp.getConstant(name_index);
73             final ConstantUTFInfo varDesc =
74                 (ConstantUTFInfo)cp.getConstant(descriptor_index);
75
76             final Location startLocation = new FixedLocation(start_pc);
77             final Location endLocation = new FixedLocation(end_pc);
78
79             Set JavaDoc ranges = new HashSet JavaDoc();
80             ranges.add(new LocationRangeImpl(startLocation, endLocation));
81             final Set JavaDoc fRanges = Collections.unmodifiableSet(ranges);
82
83             LocalVariable localVar = new LocalVariable() {
84                 private String JavaDoc mName;
85                 private TypeDesc mType;
86
87                 {
88                     mName = varName.getValue();
89                     mType = TypeDesc.forDescriptor(varDesc.getValue());
90                 }
91
92                 public String JavaDoc getName() {
93                     return mName;
94                 }
95
96                 public void setName(String JavaDoc name) {
97                     mName = name;
98                 }
99
100                 public TypeDesc getType() {
101                     return mType;
102                 }
103                 
104                 public boolean isDoubleWord() {
105                     return mType.isDoubleWord();
106                 }
107                 
108                 public int getNumber() {
109                     return index;
110                 }
111
112                 public Set JavaDoc getLocationRangeSet() {
113                     return fRanges;
114                 }
115             };
116
117             mEntries.add(new Entry(localVar, varName, varDesc));
118         }
119     }
120
121     /**
122      * Add an entry into the LocalVariableTableAttr.
123      */

124     public void addEntry(LocalVariable localVar) {
125         String JavaDoc varName = localVar.getName();
126         if (varName != null) {
127             ConstantUTFInfo name = getConstantPool().addConstantUTF(varName);
128             ConstantUTFInfo descriptor =
129                 getConstantPool().addConstantUTF(localVar.getType().getDescriptor());
130             mEntries.add(new Entry(localVar, name, descriptor));
131         }
132
133         mCleanEntries = null;
134     }
135     
136     public int getLength() {
137         clean();
138         return 2 + 10 * mRangeCount;
139     }
140     
141     public void writeDataTo(DataOutput JavaDoc dout) throws IOException JavaDoc {
142         dout.writeShort(mRangeCount);
143
144         int size = mCleanEntries.size();
145         for (int i=0; i<size; i++) {
146             Entry entry = (Entry)mEntries.get(i);
147             LocalVariable localVar = entry.mLocalVar;
148
149             Set JavaDoc ranges = localVar.getLocationRangeSet();
150             if (ranges == null) {
151                 continue;
152             }
153
154             int name_index = entry.mName.getIndex();
155             int descriptor_index = entry.mDescriptor.getIndex();
156             int index = localVar.getNumber();
157
158             check("local variable table entry name index", name_index);
159             check("local variable table entry descriptor index", descriptor_index);
160             check("local variable table entry index", index);
161
162             Iterator JavaDoc it = ranges.iterator();
163             while (it.hasNext()) {
164                 LocationRange range = (LocationRange)it.next();
165
166                 Location startLocation = range.getStartLocation();
167                 Location endLocation = range.getEndLocation();
168
169                 int start_pc = startLocation.getLocation();
170                 int length = endLocation.getLocation() - start_pc - 1;
171
172                 check("local variable table entry start PC", start_pc);
173
174                 dout.writeShort(start_pc);
175                 dout.writeShort(length);
176                 dout.writeShort(name_index);
177                 dout.writeShort(descriptor_index);
178                 dout.writeShort(index);
179             }
180         }
181     }
182
183     private void check(String JavaDoc type, int addr) throws IllegalStateException JavaDoc {
184         if (addr < 0 || addr > 65535) {
185             throw new IllegalStateException JavaDoc("Value for " + type + " out of " +
186                                             "valid range: " + addr);
187         }
188     }
189
190     private void clean() {
191         if (mCleanEntries != null) {
192             return;
193         }
194
195         // Clean out entries that are incomplete or bogus.
196

197         int size = mEntries.size();
198         mCleanEntries = new ArrayList JavaDoc(size);
199         mRangeCount = 0;
200
201     outer:
202         for (int i=0; i<size; i++) {
203             Entry entry = (Entry)mEntries.get(i);
204             LocalVariable localVar = entry.mLocalVar;
205
206             Set JavaDoc ranges = localVar.getLocationRangeSet();
207             if (ranges == null || ranges.size() == 0) {
208                 continue;
209             }
210
211             Iterator JavaDoc it = ranges.iterator();
212             while (it.hasNext()) {
213                 LocationRange range = (LocationRange)it.next();
214
215                 Location startLocation = range.getStartLocation();
216                 Location endLocation = range.getEndLocation();
217
218                 if (startLocation == null || endLocation == null) {
219                     continue outer;
220                 }
221
222                 int start_pc = startLocation.getLocation();
223                 int length = endLocation.getLocation() - start_pc - 1;
224
225                 if (length < 0) {
226                     continue outer;
227                 }
228             }
229             
230             mCleanEntries.add(entry);
231             mRangeCount += entry.getRangeCount();
232         }
233     }
234
235     private static class Entry {
236         public LocalVariable mLocalVar;
237         public ConstantUTFInfo mName;
238         public ConstantUTFInfo mDescriptor;
239
240         public Entry(LocalVariable localVar,
241                      ConstantUTFInfo name, ConstantUTFInfo descriptor) {
242
243             mLocalVar = localVar;
244             mName = name;
245             mDescriptor = descriptor;
246         }
247
248         public int getRangeCount() {
249             return mLocalVar.getLocationRangeSet().size();
250         }
251     }
252 }
253
Popular Tags