KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > ExpressionPool


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda;
21
22 import com.sun.jdi.AbsentInformationException;
23 import com.sun.jdi.IncompatibleThreadStateException;
24 import com.sun.jdi.Location;
25 import com.sun.jdi.Method;
26 import com.sun.jdi.ReferenceType;
27 import com.sun.jdi.StackFrame;
28 import com.sun.jdi.ThreadReference;
29
30 import java.lang.reflect.InvocationTargetException JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.logging.Level JavaDoc;
37 import java.util.logging.Logger JavaDoc;
38
39 import org.netbeans.api.debugger.DebuggerManager;
40 import org.netbeans.api.debugger.Session;
41 import org.netbeans.spi.debugger.jpda.EditorContext;
42 import org.netbeans.spi.debugger.jpda.EditorContext.Operation;
43
44 /**
45  * The pool of operations, which are used for expression stepping.
46  *
47  * @author Martin Entlicher
48  */

49 public class ExpressionPool {
50     
51     private static final boolean IS_JDK_16 = !System.getProperty("java.version").startsWith("1.5"); // NOI18N
52
private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.step"); // NOI18N
53

54     private Map JavaDoc<ExpressionLocation, Expression> expressions = new HashMap JavaDoc<ExpressionLocation, Expression>();
55     
56     /**
57      * Creates a new instance of ExpressionPool
58      */

59     ExpressionPool() {
60     }
61     
62     public synchronized Expression getExpressionAt(Location loc, String JavaDoc url) {
63         ExpressionLocation exprLocation = new ExpressionLocation(loc.method(), loc.lineNumber());
64         if (!expressions.containsKey(exprLocation)) {
65             Expression expr = createExpressionAt(loc, url);
66             expressions.put(exprLocation, expr);
67         }
68         return expressions.get(exprLocation);
69     }
70     
71     // TODO: Clean unnecessray expressions:
72
/*
73     public synchronized void removeExpressionAt(Location loc) {
74         expressions.remove(new ExpressionLocation(loc.method(), loc.lineNumber()));
75     }
76      */

77     public void cleanUnusedExpressions(ThreadReference thr) {
78         synchronized (this) {
79             if (expressions.size() == 0) {
80                 return ;
81             }
82         }
83         List JavaDoc<StackFrame> stackFrames;
84         try {
85             stackFrames = thr.frames();
86             synchronized (this) {
87                 for (Iterator JavaDoc<ExpressionLocation> locIt = expressions.keySet().iterator(); locIt.hasNext(); ) {
88                     ExpressionLocation exprLoc = locIt.next();
89                     // TODO: Check the correct thread.
90
Method method = exprLoc.getMethod();
91                     int line = exprLoc.getLine();
92                     for (Iterator JavaDoc<StackFrame> it = stackFrames.iterator(); it.hasNext(); ) {
93                         StackFrame sf = it.next();
94                         if (method.equals(sf.location().method())) {
95                             //&& line == sf.location().lineNumber()) {
96
method = null;
97                             break;
98                         }
99                     }
100                     if (method != null) {
101                         locIt.remove();
102                     }
103                 }
104             }
105         } catch (IncompatibleThreadStateException ex) {
106             // Ignore
107
}
108     }
109
110     private Expression createExpressionAt(Location loc, String JavaDoc url) {
111         ReferenceType clazzType = loc.declaringType();
112         final Method method = loc.method();
113         final byte[] bytecodes = method.bytecodes();
114         byte[] constantPool = new byte[0];
115         String JavaDoc JDKVersion = System.getProperty("java.version"); // NOI18N
116
if (IS_JDK_16) {
117             try { // => clazzType.constantPool(); on JDK 1.6.0 and higher
118
java.lang.reflect.Method JavaDoc constantPoolMethod =
119                         clazzType.getClass().getMethod("constantPool", new Class JavaDoc[0]); // NOI18N
120
try {
121                     constantPool = (byte[]) constantPoolMethod.invoke(clazzType, new Object JavaDoc[0]);
122                 } catch (IllegalArgumentException JavaDoc ex) {
123                 } catch (InvocationTargetException JavaDoc ex) {
124                 } catch (IllegalAccessException JavaDoc ex) {
125                 }
126             } catch (SecurityException JavaDoc ex) {
127             } catch (NoSuchMethodException JavaDoc ex) {
128             }
129         }
130         final byte[] theConstantPool = constantPool;
131         Session currentSession = DebuggerManager.getDebuggerManager().getCurrentSession();
132         final String JavaDoc language = currentSession == null ? null : currentSession.getCurrentLanguage();
133         
134         int line = loc.lineNumber(language);
135         
136         Operation[] ops = EditorContextBridge.getOperations(
137                 url, line, new EditorContext.BytecodeProvider() {
138             public byte[] constantPool() {
139                 return theConstantPool;
140             }
141
142             public byte[] byteCodes() {
143                 return bytecodes;
144             }
145
146             public int[] indexAtLines(int startLine, int endLine) {
147                 return getIndexesAtLines(method, language, startLine, endLine);
148             }
149             
150         });
151         if (ops == null) {
152             logger.log(Level.FINE, "Unsuccessfull bytecode matching.");
153             return null;
154         }
155         if (ops.length == 0) { // No operations - do a line step instead
156
return null;
157         }
158         Location[] locations = new Location[ops.length];
159         for (int i = 0; i < ops.length; i++) {
160             int codeIndex = ops[i].getBytecodeIndex();
161             locations[i] = method.locationOfCodeIndex(codeIndex);
162             if (locations[i] == null) {
163                 logger.log(Level.FINE, "Location of the operation not found.");
164                 return null;
165             }
166         }
167         Expression expr = new Expression(new ExpressionLocation(method, line), ops, locations);
168         return expr;
169     }
170     
171     private static int[] getIndexesAtLines(Method method, String JavaDoc language, int startLine, int endLine) {
172         try {
173             List JavaDoc<Location> startLocations;
174             int startlocline = 0;
175             int endlocline;
176             do {
177                 startLocations = method.locationsOfLine(language, null, startLine - startlocline++);
178             } while (startLocations.isEmpty());
179             if (endLine > startLine - (startlocline - 1)) {
180                 endlocline = 0;
181             } else {
182                 endlocline = 1;
183             }
184             startLine -= (startlocline - 1);
185             endLine += endlocline;
186         } catch (AbsentInformationException aiex) {
187             logger.log(Level.FINE, aiex.getLocalizedMessage());
188             return null;
189         }
190         List JavaDoc<int[]> indexes = new ArrayList JavaDoc<int[]>();
191         List JavaDoc<Location> allLocations;
192         try {
193             allLocations = method.allLineLocations(language, null);
194         } catch (AbsentInformationException aiex) {
195             logger.log(Level.FINE, aiex.getLocalizedMessage());
196             return null;
197         }
198         int startIndex = -1;
199         for (Location l : allLocations) {
200             int line = l.lineNumber(language);
201             if (startIndex == -1 && startLine <= line && line < endLine) {
202                 startIndex = (int) l.codeIndex();
203             } else if (startIndex >= 0) {
204                 indexes.add(new int[] { startIndex, (int) l.codeIndex() });
205                 startIndex = -1;
206             }
207         }
208         if (indexes.size() == 0) {
209             if (startIndex >= 0) {
210                 // End of the method
211
return new int[] { startIndex, method.bytecodes().length };
212             }
213             return null;
214         } else if (indexes.size() == 1) {
215             return indexes.get(0);
216         } else {
217             int[] arr = new int[2*indexes.size()];
218             for (int i = 0; i < indexes.size(); i++) {
219                 arr[2*i] = indexes.get(i)[0];
220                 arr[2*i + 1] = indexes.get(i)[1];
221             }
222             return arr;
223         }
224     }
225     
226     //private int[] singleIndexHolder = new int[1]; // Perf. optimization only
227

228     public static final class Expression {
229         
230         private ExpressionLocation location;
231         private Operation[] operations;
232         private Location[] locations;
233         
234         Expression(ExpressionLocation location, Operation[] operations, Location[] locations) {
235             this.location = location;
236             this.operations = operations;
237             this.locations = locations;
238         }
239         
240         public Operation[] getOperations() {
241             return operations;
242         }
243         
244         public Location[] getLocations() {
245             return locations;
246         }
247         
248         public int findNextOperationIndex(int codeIndex) {
249             for (int i = 0; i < operations.length; i++) {
250                 int operationIndex = operations[i].getBytecodeIndex();
251                 if (operationIndex > codeIndex) {
252                     return i;
253                 }
254             }
255             return -1;
256         }
257         
258         int[] findNextOperationIndexes(int codeIndex) {
259             for (int i = 0; i < operations.length; i++) {
260                 int operationIndex = operations[i].getBytecodeIndex();
261                 if (operationIndex == codeIndex) {
262                     List JavaDoc<Operation> nextOperations = operations[i].getNextOperations();
263                     if (!nextOperations.isEmpty()) {
264                         int l = nextOperations.size();
265                         int[] indexes = new int[l];
266                         for (int ni = 0; ni < l; ni++) {
267                             Operation op = nextOperations.get(ni);
268                             int j;
269                             for (j = 0; j < operations.length; j++) {
270                                 if (op == operations[j]) break;
271                             }
272                             if (j < operations.length) {
273                                 indexes[ni] = j;
274                             } else {
275                                 indexes[ni] = -1;
276                             }
277                         }
278                         return indexes;
279                     }
280                 }
281                 if (operationIndex > codeIndex) {
282                     return new int[] { i };
283                 }
284             }
285             return null;
286         }
287         
288         OperationLocation[] findNextOperationLocations(int codeIndex) {
289             for (int i = 0; i < operations.length; i++) {
290                 int operationIndex = operations[i].getBytecodeIndex();
291                 if (operationIndex == codeIndex) {
292                     List JavaDoc<Operation> nextOperations = operations[i].getNextOperations();
293                     if (!nextOperations.isEmpty()) {
294                         int l = nextOperations.size();
295                         OperationLocation[] opLocations = new OperationLocation[l];
296                         for (int ni = 0; ni < l; ni++) {
297                             Operation op = nextOperations.get(ni);
298                             int j;
299                             for (j = 0; j < operations.length; j++) {
300                                 if (op == operations[j]) break;
301                             }
302                             if (j < operations.length) {
303                                 opLocations[ni] = //locations[j];
304
new OperationLocation(operations[j], locations[j], j);
305                             } else {
306                                 int ci = op.getBytecodeIndex();
307                                 Location loc = location.getMethod().locationOfCodeIndex(ci);
308                                 if (loc == null) {
309                                     logger.log(Level.FINE, "Location of the operation not found.");
310                                     return null;
311                                 }
312                                 opLocations[ni] = //loc;
313
new OperationLocation(op, loc, -1);
314                             }
315                         }
316                         return opLocations;
317                     }
318                 }
319                 if (operationIndex > codeIndex) {
320                     return new OperationLocation[] { new OperationLocation(
321                                 operations[i],
322                                 locations[i],
323                                 i
324                             ) };
325                 }
326             }
327             return null;
328         }
329         
330     }
331
332     public static final class ExpressionLocation {
333
334         private Method method;
335         private int line;
336
337         public ExpressionLocation(Method method, int line) {
338             this.method = method;
339             this.line = line;
340         }
341         
342         public Method getMethod() {
343             return method;
344         }
345         
346         public int getLine() {
347             return line;
348         }
349
350         public boolean equals(Object JavaDoc obj) {
351             if (!(obj instanceof ExpressionLocation)) {
352                 return false;
353             }
354             return ((ExpressionLocation) obj).line == line && ((ExpressionLocation) obj).method.equals(method);
355         }
356
357         public int hashCode() {
358             return method.hashCode() + line;
359         }
360
361     }
362     
363     public static final class OperationLocation {
364         
365         private Operation op;
366         private Location loc;
367         private int index;
368         
369         OperationLocation(Operation op, Location loc, int index) {
370             this.op = op;
371             this.loc = loc;
372             this.index = index;
373         }
374
375         public Operation getOperation() {
376             return op;
377         }
378
379         public Location getLocation() {
380             return loc;
381         }
382         
383         public int getIndex() {
384             return index;
385         }
386
387     }
388         
389 }
390
Popular Tags