KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > inject > util > LineNumbers


1 /**
2  * Copyright (C) 2006 Google Inc.
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 com.google.inject.util;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.lang.reflect.*;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24 import org.objectweb.asm.*;
25 import org.objectweb.asm.Type;
26
27 /**
28  * Looks up line numbers for classes and their members.
29  *
30  * @author Chris Nokleberg
31  */

32 public class LineNumbers {
33
34   private final Class JavaDoc cls;
35   private Map JavaDoc<String JavaDoc, Integer JavaDoc> lines = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
36   private String JavaDoc source;
37   private int firstLine = Integer.MAX_VALUE;
38
39   /**
40    * Reads line number information from the given class, if available.
41    *
42    * @param cls the class to read line number information from
43    * @throws IllegalArgumentException if the bytecode for the class cannot be
44    * found
45    * @throws IOException if an error occurs while reading bytecode
46    */

47   public LineNumbers(Class JavaDoc cls) throws IOException JavaDoc {
48     this.cls = cls;
49     InputStream JavaDoc in = cls
50         .getResourceAsStream("/" + cls.getName().replace('.', '/') + ".class");
51     if (in == null) {
52       throw new IllegalArgumentException JavaDoc("Cannot find bytecode for " + cls);
53     }
54     new ClassReader(in).accept(new LineNumberReader(), 0);
55   }
56
57   /**
58    * Get the source file name as read from the bytecode.
59    *
60    * @return the source file name if available, or null
61    */

62   public String JavaDoc getSource() {
63     return source;
64   }
65
66   /**
67    * Get the line number associated with the given member.
68    *
69    * @param member a field, constructor, or method belonging to the class used
70    * during construction
71    * @return the wrapped line number, or null if not available
72    * @throws IllegalArgumentException if the member does not belong to the
73    * class used during construction
74    */

75   public Integer JavaDoc getLineNumber(Member member) {
76     if (!cls.equals(member.getDeclaringClass())) {
77       throw new IllegalArgumentException JavaDoc("Member " + member + " belongs to "
78           + member.getDeclaringClass() + ", not " + cls);
79     }
80     return lines.get(getKey(member));
81   }
82
83   /**
84    * Gets the first line number.
85    */

86   public int getFirstLine() {
87     return firstLine == Integer.MAX_VALUE ? 1 : firstLine;
88   }
89
90   private static String JavaDoc getKey(Member member) {
91     if (member instanceof Field) {
92       return member.getName();
93     }
94     else if (member instanceof Method) {
95       return member.getName() + Type.getMethodDescriptor((Method) member);
96     }
97     else {
98       return "<init>" + Type.getConstructorDescriptor((Constructor) member);
99     }
100   }
101
102   private class LineNumberReader implements ClassVisitor, MethodVisitor {
103
104     private int line = -1;
105     private String JavaDoc pendingMethod;
106     private String JavaDoc name;
107
108     public void visit(int version, int access, String JavaDoc name, String JavaDoc signature,
109         String JavaDoc superName, String JavaDoc[] interfaces) {
110       this.name = name;
111     }
112
113     public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc,
114         String JavaDoc signature, String JavaDoc[] exceptions) {
115       if ((access & Opcodes.ACC_PRIVATE) != 0) {
116         return null;
117       }
118       pendingMethod = name + desc;
119       line = -1;
120       return this;
121     }
122
123     public void visitSource(String JavaDoc source, String JavaDoc debug) {
124       LineNumbers.this.source = source;
125     }
126
127     public void visitLineNumber(int line, Label start) {
128       if (line < firstLine) {
129         firstLine = line;
130       }
131
132       this.line = line;
133       if (pendingMethod != null) {
134         lines.put(pendingMethod, line);
135         pendingMethod = null;
136       }
137     }
138
139     public void visitFieldInsn(int opcode, String JavaDoc owner, String JavaDoc name,
140         String JavaDoc desc) {
141       if (opcode == Opcodes.PUTFIELD && this.name.equals(owner)
142           && !lines.containsKey(name) && line != -1) {
143         lines.put(name, line);
144       }
145     }
146
147     public void visitEnd() {
148     }
149
150     public void visitInnerClass(String JavaDoc name, String JavaDoc outerName, String JavaDoc innerName,
151         int access) {
152     }
153
154     public void visitOuterClass(String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
155     }
156
157     public void visitAttribute(Attribute attr) {
158     }
159
160     public FieldVisitor visitField(int access, String JavaDoc name, String JavaDoc desc,
161         String JavaDoc signature, Object JavaDoc value) {
162       return null;
163     }
164
165     public AnnotationVisitor visitAnnotation(String JavaDoc desc, boolean visible) {
166       return null;
167     }
168
169     public AnnotationVisitor visitAnnotationDefault() {
170       return null;
171     }
172
173     public AnnotationVisitor visitParameterAnnotation(int parameter,
174         String JavaDoc desc, boolean visible) {
175       return null;
176     }
177
178     public void visitCode() {
179     }
180
181     public void visitFrame(int type, int nLocal, Object JavaDoc[] local, int nStack,
182         Object JavaDoc[] stack) {
183     }
184
185     public void visitIincInsn(int var, int increment) {
186     }
187
188     public void visitInsn(int opcode) {
189     }
190
191     public void visitIntInsn(int opcode, int operand) {
192     }
193
194     public void visitJumpInsn(int opcode, Label label) {
195     }
196
197     public void visitLabel(Label label) {
198     }
199
200     public void visitLdcInsn(Object JavaDoc cst) {
201     }
202
203     public void visitLocalVariable(String JavaDoc name, String JavaDoc desc, String JavaDoc signature,
204         Label start, Label end, int index) {
205     }
206
207     public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
208     }
209
210     public void visitMaxs(int maxStack, int maxLocals) {
211     }
212
213     public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name,
214         String JavaDoc desc) {
215     }
216
217     public void visitMultiANewArrayInsn(String JavaDoc desc, int dims) {
218     }
219
220     public void visitTableSwitchInsn(int min, int max, Label dflt,
221         Label[] labels) {
222     }
223
224     public void visitTryCatchBlock(Label start, Label end, Label handler,
225         String JavaDoc type) {
226     }
227
228     public void visitTypeInsn(int opcode, String JavaDoc desc) {
229     }
230
231     public void visitVarInsn(int opcode, int var) {
232     }
233   }
234 }
235
Popular Tags