KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > expr > Evaluator


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.expr;
21
22 import com.sun.jdi.*;
23
24 import java.util.*;
25 import java.util.logging.Level JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27
28 import org.netbeans.api.debugger.jpda.InvalidExpressionException;
29 import org.netbeans.api.debugger.jpda.JPDAClassType;
30 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
31 import org.openide.util.NbBundle;
32
33
34 /**
35  * Engine that evaluates a Java expression in a context of a running JVM. The
36  * JVM (or at least the current thread) must be suspended. A single instance of this evaluator may
37  * only be used from a single thread, no multithreading support is provided.
38  *
39  * TODO: the evaluator should check the expression's language version
40  *
41  * @author Maros Sandor
42  */

43 public class Evaluator implements JavaParserVisitor {
44     
45     private static final boolean verbose =
46         System.getProperty ("netbeans.debugger.noInvokeMethods") != null;
47     
48     private static final Logger JavaDoc loggerMethod = Logger.getLogger("org.netbeans.modules.debugger.jpda.invokeMethod"); // NOI18N
49
private static final Logger JavaDoc loggerValue = Logger.getLogger("org.netbeans.modules.debugger.jpda.getValue"); // NOI8N
50

51     private Expression expression;
52     private EvaluationContext evaluationContext;
53
54     private VirtualMachine vm;
55     private StackFrame frame;
56     private ThreadReference frameThread;
57     private int frameIndex;
58
59     private SimpleNode currentNode;
60     private String JavaDoc currentPackage;
61     private Operators operators;
62
63     Evaluator(Expression expression, EvaluationContext context) {
64         this.expression = expression;
65         this.evaluationContext = context;
66     }
67
68     /**
69      * Evaluates the expression for which it was created.
70      *
71      * @return the result of evaluating the expression as a JDI Value object.
72      * It returns null if the result itself is null.
73      * @throws EvaluationException if the expression cannot be evaluated for whatever reason
74      * @throws IncompatibleThreadStateException if the context thread is in an
75      * incompatible state (running, dead)
76      */

77     public Value evaluate() throws EvaluationException, IncompatibleThreadStateException
78     {
79         frame = evaluationContext.getFrame();
80         vm = evaluationContext.getFrame().virtualMachine();
81         frameThread = frame.thread();
82         frameIndex = indexOf(frameThread.frames(), frame);
83         if (frameIndex == -1) {
84             throw new IncompatibleThreadStateException("Thread does not contain current frame");
85         }
86         currentPackage = evaluationContext.getFrame().location().declaringType().name();
87         int idx = currentPackage.lastIndexOf('.');
88         currentPackage = (idx > 0) ? currentPackage.substring(0, idx + 1) : "";
89         operators = new Operators(vm);
90         SimpleNode rootNode = expression.getRoot();
91         return (Value) rootNode.jjtAccept(this, null);
92     }
93
94     private int indexOf(List frames, StackFrame frame) {
95         int n = frames.size();
96         Location loc = frame.location();
97         for (int i = 0; i < n; i++) {
98             if (loc.equals(((StackFrame)frames.get(i)).location())) return i;
99         }
100         return -1;
101     }
102
103     public Object JavaDoc visit(SimpleNode node, Object JavaDoc data) throws EvaluationException {
104         currentNode = node;
105         switch (node.jjtGetID())
106         {
107         case JavaParserTreeConstants.JJTRESULTTYPE:
108             return visitResultType(node, data);
109
110         case JavaParserTreeConstants.JJTARRAYINITIALIZER:
111             return visitArrayInitializer(node, data);
112
113         case JavaParserTreeConstants.JJTARRAYDIMSANDINITS:
114             return visitArrayDimsAndInits(node, data);
115
116         case JavaParserTreeConstants.JJTALLOCATIONEXPRESSION:
117             return visitAllocationExpression(node, data);
118
119         case JavaParserTreeConstants.JJTARGUMENTLIST:
120             return visitArgumentList(node, data);
121
122         case JavaParserTreeConstants.JJTARGUMENTS:
123             return visitArguments(node, data);
124
125         case JavaParserTreeConstants.JJTCASTEXPRESSION:
126             return visitCastExpression(node, data);
127
128         case JavaParserTreeConstants.JJTPOSTFIXEXPRESSION:
129             return visitPostfixExpression(node, data);
130
131         case JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION:
132         case JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION:
133             return visitPrefixExpression(node, data);
134
135         case JavaParserTreeConstants.JJTUNARYEXPRESSION:
136         case JavaParserTreeConstants.JJTUNARYEXPRESSIONNOTPLUSMINUS:
137             return visitUnaryExpression(node, data);
138
139         case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE:
140             return visitClassOrInterfaceType(node, data);
141
142         case JavaParserTreeConstants.JJTIDENTIFIER:
143             return visitIdentifier(node, data);
144
145         case JavaParserTreeConstants.JJTPRIMITIVETYPE:
146             return visitPrimitiveType(node, data);
147
148         case JavaParserTreeConstants.JJTREFERENCETYPE:
149             return visitReferenceType(node, data);
150
151         case JavaParserTreeConstants.JJTNAME:
152             return visitName(node, data);
153
154         case JavaParserTreeConstants.JJTEXPRESSION:
155             return visitExpression(node, data);
156
157         case JavaParserTreeConstants.JJTPRIMARYEXPRESSION:
158             return visitPrimaryExpression(node, data);
159
160         case JavaParserTreeConstants.JJTPRIMARYPREFIX:
161             return visitPrimaryPrefix(node, data);
162
163         case JavaParserTreeConstants.JJTPRIMARYSUFFIX:
164             return visitPrimarySuffix(node, data);
165
166         case JavaParserTreeConstants.JJTCONDITIONALEXPRESSION:
167             return visitConditionalExpression(node, data);
168
169         case JavaParserTreeConstants.JJTCONDITIONALOREXPRESSION:
170         case JavaParserTreeConstants.JJTCONDITIONALANDEXPRESSION:
171             return visitConditionalOrAndExpression(node, data);
172
173         case JavaParserTreeConstants.JJTSHIFTEXPRESSION:
174         case JavaParserTreeConstants.JJTRELATIONALEXPRESSION:
175         case JavaParserTreeConstants.JJTEQUALITYEXPRESSION:
176         case JavaParserTreeConstants.JJTINCLUSIVEOREXPRESSION:
177         case JavaParserTreeConstants.JJTANDEXPRESSION:
178         case JavaParserTreeConstants.JJTEXCLUSIVEOREXPRESSION:
179         case JavaParserTreeConstants.JJTADDITIVEEXPRESSION:
180         case JavaParserTreeConstants.JJTMULTIPLICATIVEEXPRESSION:
181             return visitBinaryExpression(node, data);
182
183         case JavaParserTreeConstants.JJTINSTANCEOFEXPRESSION:
184             return visitInstanceOfExpression(node, data);
185
186         case JavaParserTreeConstants.JJTLITERAL:
187             return visitLiteral(node, data);
188
189         case JavaParserTreeConstants.JJTBOOLEANLITERAL:
190             return visitBooleanLiteral(node, data);
191
192         case JavaParserTreeConstants.JJTNULLLITERAL:
193             return null;
194         }
195         return Assert.error(node, "unknownNonterminal");
196     }
197
198     private ObjectReference primitiveClass(String JavaDoc name) throws IncompatibleThreadStateException {
199         ReferenceType primType = resolveType("java.lang." + name.substring(0, 1).toUpperCase() + name.substring(1));
200         try {
201             if (loggerValue.isLoggable(Level.FINE)) {
202                 loggerValue.fine("STARTED : "+primType+".getValue("+primType.fieldByName("TYPE")+")");
203             }
204             return (ObjectReference) primType.getValue(primType.fieldByName("TYPE"));
205         } finally {
206             if (loggerValue.isLoggable(Level.FINE)) {
207                 loggerValue.fine("FINISHED: "+primType+".getValue("+primType.fieldByName("TYPE")+")");
208             }
209         }
210     }
211
212     private Object JavaDoc visitResultType(SimpleNode node, Object JavaDoc data) {
213         try {
214             if (node.getAttribute("void") != null) {
215                 return primitiveClass("void");
216             }
217             Type type = (Type) node.jjtGetChild(0).jjtAccept(this, data);
218             if (type instanceof ReferenceType) return type;
219
220             return primitiveClass(type.name());
221         } catch (IncompatibleThreadStateException e) {
222             return Assert.error(node, "internalErrorResolvingType", "void");
223         }
224     }
225
226     private Object JavaDoc visitArrayInitializer(SimpleNode node, Object JavaDoc data) {
227         Object JavaDoc [] values = new Object JavaDoc[node.jjtGetNumChildren()];
228         for (int i = 0; i < values.length; i++) {
229             values[i] = node.jjtGetChild(i).jjtAccept(this, data);
230             if (!(values[i] instanceof Value) && !(values[i] instanceof Object JavaDoc[])) {
231                 Assert.error(node, "invalidArrayInitializer", values[i]);
232             }
233         }
234         return values;
235     }
236
237     private Object JavaDoc visitArrayDimsAndInits(SimpleNode node, Object JavaDoc data) {
238
239         Type arrayType = (Type) data;
240         int dimensions = ((Integer JavaDoc) node.getAttribute("dimensions")).intValue();
241         ArrayReference arrayRef = null;
242
243         try {
244             if (node.getAttribute("initializers") != null) {
245                 Object JavaDoc [] initValues = (Object JavaDoc []) node.jjtGetChild(0).jjtAccept(this, data);
246                 return createArray(arrayType, dimensions, initValues);
247             } else {
248                 int sizeCount = node.jjtGetNumChildren();
249                 int [] sizes = new int[sizeCount];
250                 for (int i = 0; i < sizeCount; i++) {
251                     Object JavaDoc sizeObj = node.jjtGetChild(i).jjtAccept(this, data);
252                     Assert.assertAssignable(sizeObj, PrimitiveValue.class, node, "arraySizeBadType", sizeObj);
253                     Assert.assertNotAssignable(sizeObj, BooleanValue.class, node, "arraySizeBadType", sizeObj);
254                     Assert.assertNotAssignable(sizeObj, FloatValue.class, node, "arraySizeBadType", sizeObj);
255                     Assert.assertNotAssignable(sizeObj, DoubleValue.class, node, "arraySizeBadType", sizeObj);
256                     sizes[i] = ((PrimitiveValue) sizeObj).intValue();
257                 }
258                 return createArray(arrayType, dimensions, sizes, 0);
259             }
260         } catch (IncompatibleThreadStateException e) {
261             Assert.error(node, "arrayCreateError", e);
262         } catch (ClassNotLoadedException e) {
263             Assert.error(node, "arrayCreateError", e);
264         } catch (InvalidTypeException e) {
265             Assert.error(node, "arrayCreateError", e);
266         } catch (UnsupportedOperationException JavaDoc uoex) {
267             return Assert.error(node, "calleeException", uoex);
268         }
269
270         return arrayRef;
271     }
272
273     private String JavaDoc brackets = "[[[[[[[[[[[[[[[[[[[";
274     private String JavaDoc brackets(int length) {
275         if (brackets.length() < length) {
276             char [] bracketsArray = new char[length];
277             Arrays.fill(bracketsArray, '[');
278             brackets = new String JavaDoc(bracketsArray);
279         }
280         return brackets.substring(0, length);
281     }
282
283     private ArrayReference createArray(Type baseType, int dimensions, int [] sizes, int index) throws IncompatibleThreadStateException,
284             ClassNotLoadedException, InvalidTypeException {
285
286         ArrayType arrayType = (ArrayType) resolveType(brackets(dimensions) + baseType.signature());
287         ArrayReference arrayRef = arrayType.newInstance(sizes[index]);
288         if (sizes.length > index + 1) {
289             for (int i = 0; i < sizes[index]; i++) {
290                 arrayRef.setValue(i, createArray(baseType, dimensions - 1, sizes, index + 1));
291             }
292         }
293         return arrayRef;
294     }
295
296     private ArrayReference createArray(Type baseType, int dimensions, Object JavaDoc [] values) throws IncompatibleThreadStateException,
297             ClassNotLoadedException, InvalidTypeException {
298
299         ArrayType arrayType = (ArrayType) resolveType(brackets(dimensions) + baseType.signature());
300         ArrayReference arrayRef = arrayType.newInstance(values.length);
301         for (int i = 0; i < values.length; i++) {
302             if (values[i] instanceof Object JavaDoc []) {
303                 arrayRef.setValue(i, createArray(baseType, dimensions - 1, (Object JavaDoc[]) values[i]));
304             } else {
305                 arrayRef.setValue(i, (Value) values[i]);
306             }
307         }
308         return arrayRef;
309     }
310
311     private Object JavaDoc visitAllocationExpression(SimpleNode node, Object JavaDoc data) {
312
313         Type arrayType = (Type) node.jjtGetChild(0).jjtAccept(this, data);
314
315         // new object creation
316
if (((SimpleNode) node.jjtGetChild(1)).jjtGetID() == JavaParserTreeConstants.JJTARGUMENTS) {
317             if (arrayType instanceof ClassType) {
318                 Identifier fvmc = new Identifier(false, (ReferenceType) arrayType, "<init>");
319                 return node.jjtGetChild(1).jjtAccept(this, fvmc);
320             }
321             Assert.assertNotAssignable(arrayType, InterfaceType.class, node, "instantiateInterface", arrayType.name());
322         }
323
324         // an array
325
return node.jjtGetChild(1).jjtAccept(this, arrayType);
326     }
327
328     private Object JavaDoc visitPrimitiveType(SimpleNode node, Object JavaDoc data) {
329         //TODO: cache primitive types
330
Token token = (Token) node.getAttribute("token");
331         switch (token.kind) {
332         case JavaParserConstants.BOOLEAN:
333             return vm.mirrorOf(true).type();
334         case JavaParserConstants.CHAR:
335             return vm.mirrorOf('a').type();
336         case JavaParserConstants.BYTE:
337             return vm.mirrorOf((byte)0).type();
338         case JavaParserConstants.SHORT:
339             return vm.mirrorOf((short)0).type();
340         case JavaParserConstants.INT:
341             return vm.mirrorOf(0).type();
342         case JavaParserConstants.LONG:
343             return vm.mirrorOf(0L).type();
344         case JavaParserConstants.FLOAT:
345             return vm.mirrorOf(1.0f).type();
346         case JavaParserConstants.DOUBLE:
347             return vm.mirrorOf(1.0).type();
348         default:
349             throw new RuntimeException JavaDoc("Unknown primitive type: " + token.image);
350         }
351     }
352
353     private Object JavaDoc visitCastExpression(SimpleNode node, Object JavaDoc data) {
354         Object JavaDoc value = node.jjtGetChild(1).jjtAccept(this, data);
355         if (value == null) return null;
356         Type castType = (Type) node.jjtGetChild(0).jjtAccept(this, data);
357
358         if (value instanceof PrimitiveValue) {
359             PrimitiveValue primValue = (PrimitiveValue) value;
360             if (primValue instanceof BooleanValue) {
361                 Assert.assertAssignable(castType, BooleanType.class, node, "castToBooleanRequired", primValue, castType);
362                 return primValue;
363             }
364             Assert.assertNotAssignable(castType, BooleanType.class, node, "castFromBooleanRequired", primValue, castType);
365             if (castType instanceof ByteType) {
366                 return vm.mirrorOf(primValue.byteValue());
367             } else if (castType instanceof CharType) {
368                 return vm.mirrorOf(primValue.charValue());
369             } else if (castType instanceof DoubleType) {
370                 return vm.mirrorOf(primValue.doubleValue());
371             } else if (castType instanceof FloatType) {
372                 return vm.mirrorOf(primValue.floatValue());
373             } else if (castType instanceof IntegerType) {
374                 return vm.mirrorOf(primValue.intValue());
375             } else if (castType instanceof LongType) {
376                 return vm.mirrorOf(primValue.longValue());
377             } else {
378                 return vm.mirrorOf(primValue.shortValue());
379             }
380         }
381
382         // value is an object reference
383
ObjectReference valueType = (ObjectReference) value;
384         if (!instanceOf(valueType.type(), castType)) {
385             Assert.error(node, "castError", valueType.type(), castType);
386         }
387         return value;
388     }
389
390     /**
391      * Evaluates a postfix expression (i++). This evaluation does NOT modify the variable i as would be
392      * the case in the real life. It also does not check that the operand is a variable, thus 6++ is also legal.
393      * These checks are really not necessary here in the evaluator.
394      *
395      * @param node
396      * @param data
397      * @return
398      */

399     private Object JavaDoc visitPostfixExpression(SimpleNode node, Object JavaDoc data) {
400         Object JavaDoc value = node.jjtGetChild(0).jjtAccept(this, data);
401         Assert.assertAssignable(value, PrimitiveValue.class, node, "badOperandForPostfixOperator", value);
402         Assert.assertNotAssignable(value, BooleanValue.class, node, "badOperandForPostfixOperator", value);
403
404         Token operator = (Token) node.getAttribute("operator");
405         try {
406             return operators.evaluate(operator, (PrimitiveValue) value);
407         } catch (IllegalArgumentException JavaDoc e) {
408             return Assert.error(node, "postfixOperatorEvaluationError", operator, e);
409         }
410     }
411
412     /**
413      * Evaluates a prefix expression (++i). This evaluation does NOT modify the variable i as would be
414      * the case in the real life. It also does not check that the operand is a variable, thus ++6 is also legal.
415      * These checks are really not necessary here in the evaluator.
416      *
417      * @param node
418      * @param data
419      * @return
420      */

421     private Object JavaDoc visitPrefixExpression(SimpleNode node, Object JavaDoc data) {
422         Object JavaDoc value = node.jjtGetChild(0).jjtAccept(this, data);
423         Assert.assertAssignable(value, PrimitiveValue.class, node, "badOperandForPrefixOperator", value);
424         Assert.assertNotAssignable(value, BooleanValue.class, node, "badOperandForPrefixOperator", value);
425
426         Token operator = (Token) node.getAttribute("operator");
427         try {
428             return operators.evaluate(operator, (PrimitiveValue) value);
429         } catch (IllegalArgumentException JavaDoc e) {
430             return Assert.error(node, "prefixOperatorEvaluationError", operator, e);
431         }
432     }
433
434     private Object JavaDoc visitUnaryExpression(SimpleNode node, Object JavaDoc data) {
435
436         Object JavaDoc value = node.jjtGetChild(0).jjtAccept(this, data);
437 // System.out.println("In visitUnaryExpression:");
438
// System.out.println("value -> " + value);
439
// System.out.println("value.class -> " + value.getClass());
440
// System.out.println("PrimitiveValue.class -> " + PrimitiveValue.class);
441
// System.out.println("BooleanValue.class -> " + BooleanValue.class);
442
// System.out.println("Assignable ? " + BooleanValue.class.isAssignableFrom(value.getClass()));
443
Assert.assertAssignable(value, PrimitiveValue.class, node, "badOperandForUnaryOperator", value);
444         // Assert on next line is probably a mistake:
445
//Assert.assertNotAssignable(value, BooleanValue.class, node, "badOperandForUnaryOperator", value);
446

447
448         Token operator = (Token) node.getAttribute("operator");
449         try {
450             return operators.evaluate(operator, (PrimitiveValue) value);
451         } catch (IllegalArgumentException JavaDoc e) {
452             return Assert.error(node, "unaryOperatorEvaluationError", operator, e);
453         }
454     }
455
456     private Object JavaDoc visitIdentifier(SimpleNode node, Object JavaDoc data) {
457         return ((Token) node.getAttribute("token")).image;
458     }
459
460     private Object JavaDoc visitClassOrInterfaceType(SimpleNode node, Object JavaDoc data) {
461
462         StringBuffer JavaDoc fullName = new StringBuffer JavaDoc();
463
464         int n = node.jjtGetNumChildren();
465         for (int i = 0; i < n; i++) {
466             String JavaDoc namePart = (String JavaDoc) node.jjtGetChild(i).jjtAccept(this, data);
467             fullName.append('.');
468             fullName.append(namePart);
469
470             if (i < n-1) {
471                 SimpleNode nextNode = (SimpleNode) node.jjtGetChild(i + 1);
472                 if (nextNode.jjtGetID() == JavaParserTreeConstants.JJTTYPEARGUMENTS) {
473                     i++;
474                 }
475             }
476         }
477
478         String JavaDoc name = fullName.substring(1);
479         try {
480             return resolveType(name);
481         } catch (IncompatibleThreadStateException e) {
482             return Assert.error(node, "internalErrorResolvingType", name);
483         }
484     }
485
486     /**
487      * Resolving of types is slow.
488      *
489      * @param name
490      * @return
491      * @throws IncompatibleThreadStateException
492      */

493     private ReferenceType resolveType(String JavaDoc name) throws IncompatibleThreadStateException {
494         ReferenceType type;
495
496         if (name.charAt(0) == '[') {
497             if ((type = getClass(name)) != null) return type;
498             Assert.error(currentNode, "unknownType", name);
499         }
500
501         String JavaDoc innerName = frame.location().declaringType().name() + "$" + name;
502         if ((type = getClass(innerName)) != null) return type;
503
504         int idx = name.lastIndexOf('.');
505         if (idx == -1) {
506             if ((type = getClass(currentPackage + name)) != null) return type;
507         } else {
508             if ((type = getClass(name)) != null) return type;
509         }
510
511         if (idx != -1) {
512             innerName = name.substring(0, idx) + "$" + name.substring(idx + 1);
513             if (innerName.indexOf('.') == -1) innerName = currentPackage + innerName;
514             if ((type = getClass(innerName)) != null) return type;
515         }
516
517         List imports = evaluationContext.getImports();
518         for (Iterator i = imports.iterator(); i.hasNext();) {
519             String JavaDoc importStatement = (String JavaDoc) i.next();
520             int ix = importStatement.lastIndexOf('.');
521             String JavaDoc qualifier = importStatement.substring(ix + 1);
522             if (!qualifier.equals("*") && !qualifier.equals(name)) continue;
523             String JavaDoc fullName = importStatement.substring(0, ix + 1) + name;
524             type = getClass(fullName);
525             if (type != null) return type;
526         }
527
528         Assert.error(currentNode, "unknownType", name);
529         return null;
530     }
531
532     private ReferenceType getClass(String JavaDoc typeName) throws IncompatibleThreadStateException {
533
534         List classes = vm.classesByName(typeName);
535         if (classes.size() != 0) {
536             return (ReferenceType) classes.get(0);
537         }
538
539 // if (forName == null) {
540
// try {
541
// ClassObjectReference executingClass = frame.location().declaringType().classObject();
542
// ClassType currentClass = (ClassType) executingClass.referenceType();
543
// forName = currentClass.concreteMethodByName("forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
544
// } catch (Exception e) {
545
// // The should not happen
546
// }
547
// }
548
//
549
// try {
550
// ClassLoaderReference executingClassloader = frame.location().declaringType().classLoader();
551
// ClassObjectReference executingClass = frame.location().declaringType().classObject();
552
// List args = new ArrayList();
553
// args.add(vm.mirrorOf(typeName));
554
// args.add(vm.mirrorOf(true));
555
// args.add(executingClassloader);
556
// if (verbose) {
557
// throw new UnsupportedOperationException (NbBundle.getMessage (
558
// Evaluator.class,
559
// "CTL_UnsupportedOperationException"
560
// ));
561
// }
562
// ClassObjectReference cor = (ClassObjectReference) executingClass.
563
// invokeMethod (frameThread, forName, args, 0);
564
// return cor.reflectedType();
565
// } catch (Exception e) {
566
// // The class cannot be loaded, return null
567
// } finally {
568
// // the stack frame may have been invalidated by invoking the forName method
569
// frame = frameThread.frame(frameIndex);
570
// }
571
return null;
572     }
573
574     private Object JavaDoc visitReferenceType(SimpleNode node, Object JavaDoc data) {
575         Type baseType = (Type) node.jjtGetChild(0).jjtAccept(this, data);
576         int dimensions = ((Integer JavaDoc) node.getAttribute("arrayCount")).intValue();
577         if (dimensions > 0) {
578             try {
579                 return resolveType(brackets(dimensions) + baseType.signature().replace('/', '.'));
580             } catch (IncompatibleThreadStateException e) {
581                 Assert.error(node, "internalError");
582             }
583         }
584         return baseType;
585     }
586
587     private Object JavaDoc visitInstanceOfExpression(SimpleNode node, Object JavaDoc data) {
588
589         Object JavaDoc leftOper = node.jjtGetChild(0).jjtAccept(this, data);
590         if (leftOper == null) return vm.mirrorOf(false);
591         Assert.assertAssignable(leftOper, ObjectReference.class, node, "instanceOfLeftOperandNotAReference", leftOper);
592
593         ReferenceType left = ((ObjectReference) leftOper).referenceType(); // org.netbeans.Sucks
594
ReferenceType right = (ReferenceType) node.jjtGetChild(1).jjtAccept(this, data); // int []
595

596         return vm.mirrorOf(instanceOf(left, right));
597     }
598
599     private boolean instanceOf(Type left, Type right) {
600         if (left == null) return false;
601         if (left.equals(right)) return true;
602
603         if (right instanceof ArrayType) {
604             if (!(left instanceof ArrayType)) {
605                 return false;
606             } else {
607                 ArrayType leftArray = (ArrayType) left;
608                 ArrayType rightArray = (ArrayType) right;
609                 Type leftType;
610                 Type rightType;
611                 try {
612                     leftType = leftArray.componentType();
613                     rightType = rightArray.componentType();
614                 } catch (ClassNotLoadedException e) {
615                     // TODO: load missing classes
616
return false;
617                 }
618                 return instanceOf(leftType, rightType);
619             }
620         }
621
622         if (left instanceof ClassType) {
623             ClassType classLeft = (ClassType) left;
624             if (right instanceof InterfaceType) {
625                 List ifaces = classLeft.allInterfaces();
626                 for (Iterator i = ifaces.iterator(); i.hasNext();) {
627                     InterfaceType type = (InterfaceType) i.next();
628                     if (type.equals(right)) return true;
629                 }
630                 return false;
631             } else { // right instanceof ClassType
632
for (;;) {
633                     classLeft = classLeft.superclass();
634                     if (classLeft == null) return false;
635                     if (classLeft.equals(right)) return true;
636                 }
637             }
638         }
639
640         return false;
641     }
642
643
644     private Object JavaDoc visitConditionalOrAndExpression(SimpleNode node, Object JavaDoc data) {
645
646         Token operator = (Token) node.getAttribute("operator");
647
648         int n = node.jjtGetNumChildren();
649         for (int i = 0; i < n; i++) {
650             Object JavaDoc value = node.jjtGetChild(i).jjtAccept(this, data);
651             Assert.assertAssignable(value, BooleanValue.class, node, "conditionalOrAndBooleanOperandRequired", value);
652             boolean val = ((BooleanValue) value).booleanValue();
653             if (operator.kind == JavaParserConstants.SC_OR && val || operator.kind == JavaParserConstants.SC_AND && !val) {
654                 return value;
655             }
656         }
657         return vm.mirrorOf(operator.kind == JavaParserConstants.SC_AND);
658     }
659
660     private Object JavaDoc visitConditionalExpression(SimpleNode node, Object JavaDoc data) {
661
662         Object JavaDoc condition = node.jjtGetChild(0).jjtAccept(this, data);
663         Assert.assertAssignable(condition, BooleanValue.class, node, "conditionalQuestionMarkBooleanOperandRequired", condition);
664
665         boolean val = ((BooleanValue) condition).booleanValue();
666
667         if (val) {
668             return node.jjtGetChild(1).jjtAccept(this, data);
669         } else {
670             return node.jjtGetChild(2).jjtAccept(this, data);
671         }
672     }
673
674     private Object JavaDoc visitBooleanLiteral(SimpleNode node, Object JavaDoc data) {
675         Token token = (Token) node.getAttribute("token");
676         return vm.mirrorOf(token.kind == JavaParserConstants.TRUE);
677     }
678
679     private Object JavaDoc visitName(SimpleNode node, Object JavaDoc data) {
680         Object JavaDoc [] tokens = node.getAttributes("token");
681         StringBuffer JavaDoc name = new StringBuffer JavaDoc();
682         for (int i = 0; i < tokens.length; i++) {
683             name.append('.');
684             name.append(tokens[i]);
685         }
686         return name.substring(1);
687     }
688
689     private Object JavaDoc visitPrimaryPrefix(SimpleNode node, Object JavaDoc data) {
690
691         if (node.jjtGetNumChildren() == 0) {
692             ObjectReference thisObject = frame.thisObject();
693             if (thisObject == null) {
694                 Assert.error(node, "thisObjectUnavailable");
695             }
696
697             if (node.getAttribute("this") != null) return thisObject; // this
698

699             // (X.)*super.X?
700
String JavaDoc qualifier = (String JavaDoc) node.getAttribute("qualifier");
701             String JavaDoc identifier = (String JavaDoc) node.getAttribute("identifier");
702
703             return new Identifier((ObjectReference) thisObject, identifier, qualifier);
704         }
705
706         SimpleNode first = (SimpleNode) node.jjtGetChild(0);
707         switch (first.jjtGetID()) {
708
709         case JavaParserTreeConstants.JJTLITERAL:
710             return visit(first, data);
711
712         case JavaParserTreeConstants.JJTEXPRESSION:
713             return visit(first, data);
714
715         case JavaParserTreeConstants.JJTNAME:
716         {
717             String JavaDoc identifier = (String JavaDoc) visit(first, data);
718             if (identifier.indexOf('.') == -1) {
719                 return new Identifier(true, frame.thisObject(), frame.location().declaringType(), identifier);
720             }
721
722             // check for variable dereference: var.toString
723
int idx = identifier.indexOf('.');
724             String JavaDoc name = identifier.substring(0, idx);
725
726             ObjectReference member = null;
727             try {
728                 Value variable = evaluateVariable(new Identifier(true, frame.thisObject(), frame.location().declaringType(), name));
729                 Assert.assertAssignable(variable, ObjectReference.class, node, "objectReferenceRequiredOnDereference", variable);
730                 member = (ObjectReference) variable;
731             } catch (EvaluationException e) {
732                 // not a variable
733
}
734
735             ReferenceType type = null;
736             if (member == null) {
737                 // type declaration first: System.out, or java.lang.System.out.println
738
for (;;) {
739                     try {
740                         type = resolveType(name);
741                         break;
742                     } catch (EvaluationException e) {
743                         // unknown type
744
} catch (IncompatibleThreadStateException e) {
745                         Assert.error(node, "internalError");
746                     }
747                     idx = identifier.indexOf('.', idx + 1);
748                     if (idx == -1) break;
749                     name = identifier.substring(0, idx);
750                 }
751                 if (type == null) Assert.error(node, "unknownType", identifier);
752             }
753
754             // resolve dereferences until the last name component
755
for (;;) {
756                 int idx2 = identifier.indexOf('.', idx + 1);
757                 int idx22 = idx2;
758                 if (idx2 == -1) {
759                     idx2 = identifier.length();
760                 }
761                 Identifier ident;
762                 if (member != null) {
763                     ident = new Identifier(false, member, identifier.substring(idx + 1, idx2));
764                 } else {
765                     ident = new Identifier(false, type, identifier.substring(idx + 1, idx2));
766                 }
767                 if (idx22 == -1) return ident;
768                 Value variable = evaluateVariable(ident);
769                 Assert.assertAssignable(variable, ObjectReference.class, node, "objectReferenceRequiredOnDereference", variable);
770                 member = (ObjectReference) variable;
771                 idx = idx2;
772             }
773         }
774         case JavaParserTreeConstants.JJTRESULTTYPE:
775             Object JavaDoc type = first.jjtAccept(this, data);
776             if (type instanceof ReferenceType) {
777                 return ((ReferenceType)type).classObject();
778             } else {
779                 return type;
780             }
781
782         default:
783             return first.jjtAccept(this, data);
784         }
785     }
786
787     private Object JavaDoc visitArgumentList(SimpleNode node, Object JavaDoc data) {
788         int n = node.jjtGetNumChildren();
789         Value [] argValues = new Value[n];
790         for (int i = 0; i < n ; i++) {
791             Object JavaDoc val = node.jjtGetChild(i).jjtAccept(this, data);
792             if (val != null) Assert.assertAssignable(val, Value.class, node, "badArgument", val);
793             argValues[i] = (Value) val;
794         }
795         return argValues;
796     }
797
798     private class MethodCall {
799         ReferenceType typeContext;
800         ObjectReference instanceContext;
801         Method method;
802         List<Value> args;
803
804         public MethodCall(ReferenceType typeContext, ObjectReference instanceContext, Method method, List<Value> args) {
805             this.typeContext = typeContext;
806             this.instanceContext = instanceContext;
807             this.method = method;
808             this.args = args;
809         }
810     }
811
812     private Object JavaDoc visitArguments(SimpleNode node, Object JavaDoc data) {
813         Assert.assertAssignable(data, Identifier.class, node, "argumentsBadSyntax", data);
814         Identifier ctx = (Identifier) data;
815
816         Value [] args;
817         if (node.jjtGetNumChildren() > 0) {
818             args = (Value[]) node.jjtGetChild(0).jjtAccept(this, null);
819         } else {
820             args = new Value[0];
821         }
822
823         MethodCall method;
824         try {
825             method = getConcreteMethod(ctx, args);
826         } catch (UnsupportedOperationException JavaDoc uoex) {
827             return Assert.error(node, "calleeException", uoex, ctx);
828         }
829
830         if (method.instanceContext != null) {
831             try {
832                 if (verbose)
833                     throw new UnsupportedOperationException JavaDoc (NbBundle.getMessage (
834                         Evaluator.class,
835                         "CTL_UnsupportedOperationException"
836                     ));
837                 if (!evaluationContext.canInvokeMethods()) {
838                     return Assert.error(node, "calleeException", new UnsupportedOperationException JavaDoc(), ctx);
839                 }
840                 evaluationContext.methodToBeInvoked();
841                 if (loggerMethod.isLoggable(Level.FINE)) {
842                     loggerMethod.fine("STARTED : "+method.instanceContext+"."+method.method+" ("+method.args+") in thread "+frameThread);
843                 }
844                 return method.instanceContext.invokeMethod(frameThread, method.method, method.args,
845                                                         ObjectReference.INVOKE_SINGLE_THREADED | ObjectReference.INVOKE_NONVIRTUAL);
846             } catch (InvalidTypeException e) {
847                 Assert.error(node, "callException", e, ctx);
848             } catch (ClassNotLoadedException e) {
849                 // TODO: load the class
850
Assert.error(node, "callException", e, ctx);
851             } catch (IncompatibleThreadStateException e) {
852                 Assert.error(node, "callException", e, ctx);
853             } catch (InvocationException e) {
854                 Assert.error(node, "calleeException", e, ctx);
855             } catch (UnsupportedOperationException JavaDoc e) {
856                 evaluationContext.setCanInvokeMethods(false);
857                 Assert.error(node, "calleeException", e, ctx);
858             }
859             finally {
860                 if (loggerMethod.isLoggable(Level.FINE)) {
861                     loggerMethod.fine("FINISHED: "+method.instanceContext+"."+method.method+" ("+method.args+") in thread "+frameThread);
862                 }
863                 try {
864                     frame = frameThread.frame(frameIndex);
865                 } catch (IncompatibleThreadStateException e) {
866                     Assert.error(node, "callException", e, ctx);
867                 }
868             }
869         }
870
871         if (method.typeContext instanceof ClassType) {
872             ClassType classContext = (ClassType) method.typeContext;
873             try {
874                 if (method.method.isConstructor()) {
875                     if (verbose)
876                         throw new UnsupportedOperationException JavaDoc (NbBundle.getMessage (
877                             Evaluator.class,
878                             "CTL_UnsupportedOperationException"
879                         ));
880                     try {
881                         return classContext.newInstance(frameThread, method.method, method.args, ClassType.INVOKE_SINGLE_THREADED);
882                     } catch (UnsupportedOperationException JavaDoc uoex) {
883                         return Assert.error(node, "calleeException", uoex, ctx);
884                     }
885                 } else {
886                     if (verbose)
887                         throw new UnsupportedOperationException JavaDoc (NbBundle.getMessage (
888                             Evaluator.class,
889                             "CTL_UnsupportedOperationException"
890                         ));
891                     if (!evaluationContext.canInvokeMethods()) {
892                         return Assert.error(node, "calleeException", new UnsupportedOperationException JavaDoc(), ctx);
893                     }
894                     evaluationContext.methodToBeInvoked();
895                     return classContext.invokeMethod(frameThread, method.method, method.args, ClassType.INVOKE_SINGLE_THREADED);
896                 }
897             } catch (InvalidTypeException e) {
898                 Assert.error(node, "callException", e, ctx);
899             } catch (ClassNotLoadedException e) {
900                 // TODO: load the class
901
Assert.error(node, "callException", e, ctx);
902             } catch (IncompatibleThreadStateException e) {
903                 Assert.error(node, "callException", e, ctx);
904             } catch (InvocationException e) {
905                 Assert.error(node, "calleeException", e, ctx);
906             } catch (IllegalArgumentException JavaDoc e) {
907                 Assert.error(node, "callException", e, ctx);
908             } catch (UnsupportedOperationException JavaDoc e) {
909                 evaluationContext.setCanInvokeMethods(false);
910                 Assert.error(node, "calleeException", e, ctx);
911             }
912             finally {
913                 try {
914                     frame = frameThread.frame(frameIndex);
915                 } catch (IncompatibleThreadStateException e) {
916                     Assert.error(node, "callException", e, ctx);
917                 }
918             }
919         }
920
921         return Assert.error(node, "noSuchMethod", ctx);
922     }
923
924     private boolean isAccessible(TypeComponent member) {
925         if (member.isPublic()) return true;
926
927         ReferenceType callerType = frame.location().declaringType();
928         ReferenceType calleeType = member.declaringType();
929
930         if (member.isPrivate()) {
931             if (callerType.equals(calleeType)) return true;
932             if (isNested(calleeType, callerType) || isNested(callerType, calleeType)) return true;
933             return false;
934         }
935
936         String JavaDoc callerName = callerType.name();
937         String JavaDoc calleeName = calleeType.name();
938         int idx1 = callerName.lastIndexOf('.');
939         int idx2 = calleeName.lastIndexOf('.');
940
941         if (idx1 * idx2 < 0) return false;
942         if (idx1 + idx2 == -2) return true;
943
944         if (callerName.substring(0, idx1).equals(calleeName.substring(0, idx2))) return true;
945         if (member.isProtected()) {
946             return instanceOf(callerType, calleeType);
947         }
948
949         return false;
950     }
951
952     private boolean isNested(ReferenceType outter, ReferenceType inner) {
953         List nestedTypes = outter.nestedTypes();
954         for (Iterator i = nestedTypes.iterator(); i.hasNext();) {
955             ReferenceType type = (ReferenceType) i.next();
956             if (type.equals(inner) || isNested(type, inner)) return true;
957         }
958         return false;
959     }
960
961     private MethodCall getConcreteMethod(Identifier ctx, Value [] args) {
962         ReferenceType type = ctx.typeContext;
963         ObjectReference object = ctx.instanceContext;
964
965         if (ctx.superQualifier != null) {
966             if (!(ctx.typeContext instanceof ClassType)) Assert.error(currentNode, "superUsedOnNonClass", ctx);
967             if (ctx.superQualifier.length() > 0) {
968                 object = getEnclosingObject(ctx.instanceContext, ctx.superQualifier);
969                 Assert.assertNotNull(object, currentNode, "notEnclosingType", ctx);
970             }
971             ClassType cls = (ClassType) object.referenceType();
972             type = cls.superclass();
973         }
974         
975         if (ctx.typeContext == null) {
976             Assert.error(currentNode, "methodCallOnNull", ctx.identifier);
977         }
978
979         List<Method> methods = getMethodsByName(type, ctx.identifier);
980         
981         //Try outer classes
982
ReferenceType origType = type;
983         ObjectReference origObject = object;
984         
985         while (methods.size() == 0) {
986             Field outerRef = type.fieldByName("this$0");
987             if (outerRef == null) {
988                 //System.out.println("No outerRef.");
989
type = origType;
990                 object = origObject;
991                 break; //No outer reference
992
}
993             if (loggerValue.isLoggable(Level.FINE)) {
994                 loggerValue.fine("STARTED : "+object+".getValue("+outerRef+")");
995             }
996             object = (ObjectReference) object.getValue(outerRef);
997             if (loggerValue.isLoggable(Level.FINE)) {
998                 loggerValue.fine("FINISHED: getValue("+outerRef+") = "+object);
999             }
1000            type = object.referenceType();
1001            methods = getMethodsByName(type, ctx.identifier);
1002                
1003        }
1004       
1005        //Static Imports
1006
if (ctx.localContext && methods.size() == 0) {
1007            for (Iterator i = staticImportsIterator(ctx.identifier); i.hasNext(); ) {
1008                String JavaDoc typeName = (String JavaDoc) i.next();
1009                try {
1010                    ReferenceType importedType = resolveType(typeName);
1011                    methods = getMethodsByName(importedType, ctx.identifier);
1012                    if (methods.size() > 0) {
1013                        type = importedType;
1014                        object = null;
1015                        break;
1016                    }
1017                } catch (Exception JavaDoc e) {
1018                    // no such method
1019
continue;
1020                }
1021            }
1022        }
1023
1024        List<MethodCall> possibleMethods = new ArrayList<MethodCall>();
1025
1026        for (Iterator<Method> i = methods.iterator(); i.hasNext();) {
1027            Method method = i.next();
1028            if (!isAccessible(method)) continue;
1029
1030            List argTypes = null;
1031            try {
1032                argTypes = method.argumentTypes();
1033            } catch (ClassNotLoadedException e) {
1034                // TODO: load class
1035
continue;
1036            }
1037
1038            // TODO: probably incomplete handling of an implicit constructor of a nested type
1039
if (args.length == 0 && "<init>".equals(ctx.identifier) && argTypes.size() == 1) {
1040                if (frame.thisObject() != null && argTypes.get(0).equals(frame.location().declaringType())) {
1041                    args = new Value[] { frame.thisObject() } ;
1042                }
1043            }
1044
1045            List<Value> newArgs = prepareArguments(args, argTypes);
1046            if (newArgs == null) continue;
1047            possibleMethods.add(new MethodCall(type, object, method, newArgs));
1048        }
1049        Assert.assertNonEmpty(possibleMethods, currentNode, "noSuchMethod", ctx);
1050        MethodCall call = mostSpecific(possibleMethods, args);
1051        call = findConcrete(call);
1052        Assert.assertNotNull(call, currentNode, "ambigousMethod", ctx);
1053        return call;
1054    }
1055    
1056    private static List<Method> getMethodsByName(ReferenceType type, String JavaDoc name) {
1057        if (type instanceof ArrayType) { // There are no methods by JDI definition ?!?
1058
type = type.classObject().referenceType();
1059            if ("toString".equals(name)) { // NOI18N
1060
// We have to get the super class' toString() method for some strange reason...
1061
type = ((ClassType) type).superclass();
1062            }
1063        }
1064        List<Method> methods = type.methodsByName(name);
1065        return methods;
1066    }
1067
1068    private MethodCall mostSpecific(List<MethodCall> possibleMethods, Value [] args) {
1069        if (possibleMethods.size() == 0) return null;
1070        if (possibleMethods.size() == 1) return possibleMethods.get(0);
1071
1072        MethodCall mostSpecific = null;
1073        int conversions = Integer.MAX_VALUE;
1074        for (Iterator<MethodCall> i = possibleMethods.iterator(); i.hasNext();) {
1075            MethodCall methodCall = i.next();
1076            List methodArguments = null;
1077            try {
1078                methodArguments = methodCall.method.argumentTypes();
1079            } catch (ClassNotLoadedException e) {
1080                continue;
1081            }
1082            int cc = conversionsCount(methodArguments, args);
1083            if (cc == 0) return methodCall;
1084            if (cc == conversions) {
1085                return null;
1086            }
1087            if (cc < conversions) {
1088                conversions = cc;
1089                mostSpecific = methodCall;
1090            }
1091        }
1092        return mostSpecific;
1093    }
1094
1095    private int conversionsCount(List argumentTypes, Value[] args) {
1096        int idx = 0;
1097        int cc = 0;
1098        for (Iterator i = argumentTypes.iterator(); i.hasNext(); idx++) {
1099            Type argType = (Type) i.next();
1100            if (args[idx] == null) continue;
1101            if (representSameType(argType, args[idx].type())) continue;
1102            cc ++;
1103        }
1104        return cc;
1105    }
1106
1107    private boolean representSameType(Type t1, Type t2) {
1108        String JavaDoc t1s = t1.signature();
1109        String JavaDoc t2s = t2.signature();
1110
1111        if (t1s.equals(t2s)) return true;
1112        if (t1s.length() == 1 && t2s.length() == 1 ||
1113                t1s.length() > 1 && t2s.length() > 1) return false;
1114
1115        String JavaDoc primitiveType = t1s.length() == 1 ? t1s : t2s;
1116        String JavaDoc classType = t1s.length() > 1 ? t1s : t2s;
1117
1118        return wrapperSignature(primitiveType.charAt(0)).equals(classType);
1119    }
1120    
1121    private MethodCall findConcrete(MethodCall call) {
1122        if (call.method.isAbstract()) {
1123            ReferenceType type = call.instanceContext.referenceType();
1124            if (type instanceof ClassType) {
1125                Method m = ((ClassType) type).concreteMethodByName(call.method.name(), call.method.signature());
1126                if (m != null) {
1127                    call.method = m;
1128                    call.typeContext = type;
1129                }
1130            }
1131        }
1132        return call;
1133    }
1134
1135    private List<Value> prepareArguments(Value [] args, List argTypes) {
1136
1137        boolean ellipsis;
1138        try {
1139                ellipsis = argTypes.size() > 0 &&
1140                           argTypes.get(argTypes.size() - 1) instanceof ArrayType &&
1141                           (args.length == 0 ||
1142                            args[args.length - 1] == null ||
1143                            isConvertible(((ArrayType) argTypes.get(argTypes.size() - 1)).componentType(),
1144                                          args[args.length - 1]));
1145        } catch (ClassNotLoadedException e) {
1146            // TODO: load the offending class?
1147
return null;
1148        }
1149        if (ellipsis) {
1150            if (args.length < argTypes.size() - 1) return null;
1151        } else {
1152            if (args.length != argTypes.size()) return null;
1153        }
1154
1155        List<Value> newArgs = new ArrayList<Value>();
1156        int idx = 0;
1157        for (Iterator i = argTypes.iterator(); i.hasNext(); idx++) {
1158            Type type = (Type) i.next();
1159            if (ellipsis && !i.hasNext()) continue;
1160            if (!isConvertible(type, args[idx])) return null;
1161            newArgs.add(boxUnboxIfNeeded(args[idx], type));
1162        }
1163
1164        if (ellipsis) {
1165            // JDI will handle vararg calls, we just need to check argument types
1166
ArrayType elipsisType = (ArrayType) argTypes.get(argTypes.size() - 1);
1167            if (args.length == argTypes.size() - 1) {
1168                // nothing to check
1169
} else {
1170                Type componentType = null;
1171                try {
1172                    componentType = elipsisType.componentType();
1173                } catch (ClassNotLoadedException e) {
1174                    // TODO: load the offending class
1175
return null;
1176                }
1177                if (args.length == argTypes.size()) {
1178                    if (args[args.length -1] != null && !elipsisType.equals(args[args.length -1].type())) {
1179                        if (!isConvertible(componentType, args[args.length -1])) return null;
1180                    }
1181                    newArgs.add(boxUnboxIfNeeded(args[args.length -1], componentType));
1182                } else if (args.length > argTypes.size()) {
1183                    for (int i = argTypes.size() - 1; i < args.length; i++) {
1184                        if (!isConvertible(componentType, args[i])) return null;
1185                        newArgs.add(boxUnboxIfNeeded(args[i], componentType));
1186                    }
1187                }
1188            }
1189        }
1190
1191        return newArgs;
1192    }
1193
1194    private Value boxUnboxIfNeeded(Value value, Type type) {
1195        if (value instanceof ObjectReference && type instanceof PrimitiveType) {
1196            return unbox((ObjectReference) value, type);
1197        } else if (value instanceof PrimitiveValue && type instanceof ClassType) {
1198            return box((PrimitiveValue) value, (ClassType) type);
1199        } else {
1200            return value;
1201        }
1202    }
1203
1204    /**
1205     * Wraps the passed primitive value to an object of the given type. The class type of the object must be
1206     * wider than the primitive value type. For example, it is not possible to wrap a long value to a Short object.
1207     *
1208     * @param primitiveValue
1209     * @param type
1210     * @return
1211     */

1212    private ObjectReference box(PrimitiveValue primitiveValue, ClassType type) {
1213        try {
1214            if (type instanceof Object JavaDoc) {
1215                type = wrapperType((PrimitiveType) primitiveValue.type());
1216            }
1217            return newInstance(type, new Value[] { primitiveValue });
1218        } catch (Exception JavaDoc e) {
1219            // this should never happen, indicates an internal error
1220
throw new RuntimeException JavaDoc("Unexpected exception while invoking boxing method", e);
1221        }
1222    }
1223
1224    private ClassType wrapperType(PrimitiveType type) throws IncompatibleThreadStateException {
1225        char sig = type.signature().charAt(0);
1226        return (ClassType) resolveType(wrapperClassname(sig));
1227    }
1228
1229    private String JavaDoc wrapperSignature(char primitiveSignature) {
1230        switch (primitiveSignature) {
1231        case 'Z':
1232            return "Ljava/lang/Boolean;";
1233        case 'B':
1234            return "Ljava/lang/Byte;";
1235        case 'C':
1236            return "Ljava/lang/Character;";
1237        case 'S':
1238            return "Ljava/lang/Short;";
1239        case 'I':
1240            return "Ljava/lang/Integer;";
1241        case 'J':
1242            return "Ljava/lang/Long;";
1243        case 'F':
1244            return "Ljava/lang/Float;";
1245        case 'D':
1246            return "Ljava/lang/Double;";
1247        }
1248        throw new RuntimeException JavaDoc(); // never happens
1249
}
1250
1251    private String JavaDoc wrapperClassname(char primitiveSignature) {
1252        switch (primitiveSignature) {
1253        case 'Z':
1254            return "java.lang.Boolean";
1255        case 'B':
1256            return "java.lang.Byte";
1257        case 'C':
1258            return "java.lang.Character";
1259        case 'S':
1260            return "java.lang.Short";
1261        case 'I':
1262            return "java.lang.Integer";
1263        case 'J':
1264            return "java.lang.Long";
1265        case 'F':
1266            return "java.lang.Float";
1267        case 'D':
1268            return "java.lang.Double";
1269        }
1270        throw new RuntimeException JavaDoc(); // never happens
1271
}
1272
1273    private ObjectReference newInstance(ClassType type, Value [] constructorArgs) throws
1274            InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
1275
1276        MethodCall method = getConcreteMethod(new Identifier(type, "<init>"), constructorArgs);
1277        try {
1278            return type.newInstance(frameThread, method.method, method.args, ObjectReference.INVOKE_SINGLE_THREADED);
1279        } finally {
1280            frame = frameThread.frame(frameIndex);
1281        }
1282    }
1283
1284    private PrimitiveValue unbox(ObjectReference val, Type type) {
1285
1286        if (type instanceof BooleanType) return invokeUnboxingMethod(val, "booleanValue");
1287        if (type instanceof ByteType) return invokeUnboxingMethod(val, "byteValue");
1288        if (type instanceof CharType) return invokeUnboxingMethod(val, "charValue");
1289        if (type instanceof ShortType) return invokeUnboxingMethod(val, "shortValue");
1290        if (type instanceof IntegerType) return invokeUnboxingMethod(val, "intValue");
1291        if (type instanceof LongType) return invokeUnboxingMethod(val, "longValue");
1292        if (type instanceof FloatType) return invokeUnboxingMethod(val, "floatValue");
1293        if (type instanceof DoubleType) return invokeUnboxingMethod(val, "doubleValue");
1294        throw new RuntimeException JavaDoc("Invalid type while unboxing: " + type.signature()); // never happens
1295
}
1296
1297    private PrimitiveValue invokeUnboxingMethod(ObjectReference reference, String JavaDoc methodName) {
1298        Method toCall = (Method) reference.referenceType().methodsByName(methodName).get(0);
1299        try {
1300            if (verbose)
1301                throw new UnsupportedOperationException JavaDoc (NbBundle.getMessage (
1302                    Evaluator.class,
1303                    "CTL_UnsupportedOperationException"
1304                ));
1305            if (!evaluationContext.canInvokeMethods()) {
1306                throw new UnsupportedOperationException JavaDoc();
1307            }
1308            evaluationContext.methodToBeInvoked();
1309            if (loggerMethod.isLoggable(Level.FINE)) {
1310                loggerMethod.fine("STARTED : "+reference+"."+toCall+" () in thread "+frameThread);
1311            }
1312            return (PrimitiveValue) reference.invokeMethod(frameThread, toCall, new ArrayList<Value>(0), ObjectReference.INVOKE_SINGLE_THREADED);
1313        } catch (UnsupportedOperationException JavaDoc uoex) {
1314            evaluationContext.setCanInvokeMethods(false);
1315            // this can happen on VMs that can not invoke methods...
1316
throw new RuntimeException JavaDoc("Unexpected exception while invoking unboxing method", uoex);
1317        } catch (Exception JavaDoc e) {
1318            // this should never happen, indicates an internal error
1319
throw new RuntimeException JavaDoc("Unexpected exception while invoking unboxing method", e);
1320        } finally {
1321            if (loggerMethod.isLoggable(Level.FINE)) {
1322                loggerMethod.fine("FINISHED: "+reference+"."+toCall+" () in thread "+frameThread);
1323            }
1324            try {
1325                frame = frameThread.frame(frameIndex);
1326            } catch (IncompatibleThreadStateException e) {
1327                throw new RuntimeException JavaDoc("Unexpected exception while invoking unboxing method", e);
1328            }
1329        }
1330    }
1331
1332    private static final String JavaDoc [] typeSignaturesSorted = {
1333            "Ljava/lang/Byte;", "B",
1334            "Ljava/lang/Character;", "C",
1335            "Ljava/lang/Short;", "S",
1336            "Ljava/lang/Integer;", "I",
1337            "Ljava/lang/Long;", "J",
1338            "Ljava/lang/Float;", "F",
1339            "Ljava/lang/Double;", "D"
1340    };
1341
1342    /**
1343     * int short
1344     * double float
1345     * int Integer
1346     * Integer int
1347     * Runnable Thread
1348     * Object Socket
1349     * <OREF> null
1350     *
1351     * @param wideType
1352     * @param value
1353     */

1354    private boolean isConvertible(Type wideType, Value value) {
1355
1356        if (value == null) return wideType instanceof ReferenceType;
1357
1358        String JavaDoc narrow = value.type().signature();
1359        String JavaDoc wide = wideType.signature();
1360        if (wide.equals(narrow)) return true;
1361
1362        if (wide.length() == 1) {
1363            if (wide.equals("Z")) return narrow.equals("Ljava/lang/Boolean;");
1364            for (int i = 0; i < typeSignaturesSorted.length; i++) {
1365                if (narrow.equals(typeSignaturesSorted[i])) return true;
1366                if (wide.equals(typeSignaturesSorted[i])) return false;
1367            }
1368            return false;
1369        }
1370
1371        if (wide.equals("Ljava/lang/Object;")) return true;
1372
1373        if (narrow.length() == 1) {
1374            if (narrow.equals("Z")) return wide.equals("Ljava/lang/Boolean;");
1375            for (int i = 0; i < typeSignaturesSorted.length; i++) {
1376                if (narrow.equals(typeSignaturesSorted[i])) {
1377                    for (int j = i - 1; j < typeSignaturesSorted.length; j++) {
1378                        if (wide.equals(typeSignaturesSorted[j])) return true;
1379                    }
1380                    return false;
1381                }
1382            }
1383        }
1384
1385        return instanceOf(value.type(), wideType);
1386    }
1387
1388    private Object JavaDoc visitPrimarySuffix(SimpleNode node, Object JavaDoc data) {
1389        Token token = (Token) node.getAttribute("token");
1390        if (token == null) {
1391            // AllocationExpression() | Arguments() | ReferenceTypeList()
1392
return node.jjtGetChild(0).jjtAccept(this, data);
1393        }
1394        switch (token.kind) {
1395        case JavaParserConstants.IDENTIFIER:
1396            data = resolveVariable(data); // data may be an Identifier, object.field.anotherfield
1397
Assert.assertAssignable(data, ObjectReference.class, node, "identifierNotAReference", data);
1398            return new Identifier(false, (ObjectReference)data, token.image);
1399
1400        case JavaParserConstants.LBRACKET:
1401        {
1402            data = resolveVariable(data);
1403            Assert.assertAssignable(data, ArrayReference.class, node, "notarray", data, token);
1404            Object JavaDoc index = node.jjtGetChild(0).jjtAccept(this, data);
1405            Assert.assertAssignable(index, PrimitiveValue.class, node, "arrayIndexNAN", data, index);
1406            Assert.assertNotAssignable(index, BooleanValue.class, node, "arrayIndexNAN", data, index);
1407            int idx = ((PrimitiveValue) index).intValue();
1408            ArrayReference array = (ArrayReference) data;
1409            Assert.assertLess(idx, array.length(), node, "arrayIndexOutOfBounds", array, new Integer JavaDoc(idx));
1410            return array.getValue(idx);
1411        }
1412
1413        case JavaParserConstants.THIS:
1414        case JavaParserConstants.SUPER:
1415        {
1416            Identifier ctx = (Identifier) data;
1417            if (!vm.canGetSyntheticAttribute()) Assert.error(node, "unknownType", ctx.identifier);
1418
1419            ObjectReference enclosingObject = getEnclosingObject(frame.thisObject(), ctx.identifier);
1420            Assert.assertNotNull(enclosingObject, node, "unknownType", ctx.identifier);
1421            return enclosingObject;
1422        }
1423        }
1424        return Assert.error(node, "internalError");
1425    }
1426
1427    private ObjectReference getEnclosingObject(ObjectReference obj, String JavaDoc typeQualifier) {
1428        boolean done;
1429        do {
1430            done = true;
1431            List fields = obj.referenceType().allFields();
1432            for (Iterator j = fields.iterator(); j.hasNext();) {
1433                Field field = (Field) j.next();
1434                if (field.isSynthetic() && field.name().startsWith("this$")) {
1435                    if (loggerValue.isLoggable(Level.FINE)) {
1436                        loggerValue.fine("STARTED : "+obj+".getValue("+field+")");
1437                    }
1438                    obj = (ObjectReference) obj.getValue(field);
1439                    if (loggerValue.isLoggable(Level.FINE)) {
1440                        loggerValue.fine("FINISHED: getValue("+field+") = "+obj);
1441                    }
1442                    ClassType type = (ClassType) obj.referenceType();
1443                    if (type.name().endsWith(typeQualifier)) {
1444                        return obj;
1445                    }
1446                    done = false;
1447                    break;
1448                }
1449            }
1450        } while (!done);
1451        return null;
1452    }
1453
1454    private Value evaluateVariable(Identifier ctx) {
1455        
1456        // local variable
1457
if (ctx.localContext) {
1458            try {
1459                LocalVariable var = frame.visibleVariableByName(ctx.identifier);
1460                if (var != null) return frame.getValue(var);
1461            } catch (AbsentInformationException e) {
1462            }
1463        }
1464          
1465        // field
1466
if (ctx.instanceContext != null) {
1467            Field field = ctx.typeContext.fieldByName(ctx.identifier);
1468            if (field != null) {
1469                try {
1470                    if (loggerValue.isLoggable(Level.FINE)) {
1471                        loggerValue.fine("STARTED : "+ctx.instanceContext+".getValue("+field+")");
1472                    }
1473                    return ctx.instanceContext.getValue(field);
1474                } finally {
1475                    if (loggerValue.isLoggable(Level.FINE)) {
1476                        loggerValue.fine("FINISHED : "+ctx.instanceContext+".getValue("+field+")");
1477                    }
1478                }
1479            }
1480            if (ctx.instanceContext instanceof ArrayReference) {
1481                if (ctx.identifier.equals("length")) {
1482                    return vm.mirrorOf(((ArrayReference) ctx.instanceContext).length());
1483                }
1484            }
1485        }
1486        
1487        // field from static context
1488
Field field = ctx.typeContext.fieldByName(ctx.identifier);
1489        try {
1490            if (field != null) {
1491                try {
1492                    if (loggerValue.isLoggable(Level.FINE)) {
1493                        loggerValue.fine("STARTED : "+ctx.typeContext+".getValue("+field+")");
1494                    }
1495                    return ctx.typeContext.getValue(field);
1496                } finally {
1497                    if (loggerValue.isLoggable(Level.FINE)) {
1498                        loggerValue.fine("FINISHED : "+ctx.typeContext+".getValue("+field+")");
1499                    }
1500                }
1501            }
1502        } catch (IllegalArgumentException JavaDoc e) {
1503            Assert.error(currentNode, "accessInstanceVariableFromStaticContext", ctx);
1504        }
1505        
1506        // local variable accessed from innerclass
1507
if (ctx.instanceContext != null) {
1508            field = ctx.typeContext.fieldByName("val$" + ctx.identifier);
1509            if (field != null) {
1510                try {
1511                    if (loggerValue.isLoggable(Level.FINE)) {
1512                        loggerValue.fine("STARTED : "+ctx.instanceContext+".getValue("+field+")");
1513                    }
1514                    return ctx.instanceContext.getValue(field);
1515                } finally {
1516                    if (loggerValue.isLoggable(Level.FINE)) {
1517                        loggerValue.fine("FINISHED: "+ctx.instanceContext+".getValue("+field+")");
1518                    }
1519                }
1520            }
1521        }
1522        
1523        // outer field accessed from innerclass
1524
if (ctx.instanceContext != null) {
1525            Field helpField = ctx.typeContext.fieldByName("this$0");
1526            if (helpField != null) {
1527                if (loggerValue.isLoggable(Level.FINE)) {
1528                    loggerValue.fine("STARTED : "+ctx.instanceContext+".getValue("+helpField+")");
1529                }
1530                ObjectReference or = (ObjectReference)ctx.instanceContext.getValue(helpField);
1531                if (loggerValue.isLoggable(Level.FINE)) {
1532                    loggerValue.fine("FINISHED: "+ctx.instanceContext+".getValue("+helpField+") = "+or);
1533                }
1534                if (or != null) {
1535                    field = or.referenceType().fieldByName(ctx.identifier);
1536                    if (field != null) {
1537                        try {
1538                            if (loggerValue.isLoggable(Level.FINE)) {
1539                                loggerValue.fine("STARTED : "+or+".getValue("+field+")");
1540                            }
1541                            return or.getValue(field);
1542                        } finally {
1543                            if (loggerValue.isLoggable(Level.FINE)) {
1544                                loggerValue.fine("FINISHED: "+or+".getValue("+field+")");
1545                            }
1546                        }
1547                    }
1548                }
1549            }
1550        }
1551        
1552        // static import
1553
for (Iterator i = staticImportsIterator(ctx.identifier); i.hasNext(); ) {
1554            String JavaDoc typeName = (String JavaDoc) i.next();
1555            try {
1556                ReferenceType type = resolveType(typeName);
1557                field = type.fieldByName(ctx.identifier);
1558                if (field != null) {
1559                    try {
1560                        if (loggerValue.isLoggable(Level.FINE)) {
1561                            loggerValue.fine("STARTED : "+type+".getValue("+field+")");
1562                        }
1563                        return type.getValue(field);
1564                    } finally {
1565                        if (loggerValue.isLoggable(Level.FINE)) {
1566                            loggerValue.fine("FINISHED: "+type+".getValue("+field+")");
1567                        }
1568                    }
1569                }
1570            } catch (Exception JavaDoc e) {
1571                // no such type or field
1572
}
1573        }
1574        
1575        // class special variable
1576
if (expression.classReplaced().equals(ctx.identifier)) {
1577            ReferenceType refType = frame.location().declaringType();
1578            JPDAClassType classType = evaluationContext.getDebugger().getClassType(refType);
1579            return ((JDIObjectVariable) classType.classObject()).getJDIValue();
1580        }
1581        
1582        // return special variable
1583
if (expression.returnReplaced().equals(ctx.identifier)) {
1584            ThreadReference tr = frame.thread();
1585            JPDAThreadImpl thread = (JPDAThreadImpl) evaluationContext.getDebugger().getThread(tr);
1586            JDIObjectVariable returnVar = (JDIObjectVariable) thread.getReturnVariable();
1587            if (returnVar != null) {
1588                return returnVar.getJDIValue();
1589            } else {
1590                return null;
1591            }
1592        }
1593
1594        return (Value) Assert.error(currentNode, "unknownVariable", ctx);
1595    }
1596
1597    private Iterator<String JavaDoc> staticImportsIterator(String JavaDoc identifier) {
1598        return iterator(evaluationContext.getStaticImports(), identifier);
1599    }
1600
1601    private Iterator<String JavaDoc> iterator(List<String JavaDoc> imports, String JavaDoc identifier) {
1602        List<String JavaDoc> filteredList = new ArrayList<String JavaDoc>();
1603        for (Iterator<String JavaDoc> i = imports.iterator(); i.hasNext();) {
1604            String JavaDoc statement = i.next();
1605            int idx = statement.lastIndexOf('.');
1606            String JavaDoc qualifier = statement.substring(idx + 1);
1607            if (qualifier.equals("*") || qualifier.equals(identifier)) {
1608                filteredList.add(statement.substring(0, idx));
1609            }
1610        }
1611        return filteredList.iterator();
1612    }
1613
1614    private Value resolveVariable(Object JavaDoc data) {
1615        if (data == null || data instanceof Value) return (Value) data;
1616
1617        Identifier name = (Identifier) data;
1618        return evaluateVariable(name);
1619    }
1620
1621    private Object JavaDoc visitPrimaryExpression(SimpleNode node, Object JavaDoc data) {
1622
1623        int n = node.jjtGetNumChildren();
1624
1625        Object JavaDoc value = node.jjtGetChild(0).jjtAccept(this, data);
1626        for (int i = 1; i < n; i++) {
1627            value = node.jjtGetChild(i).jjtAccept(this, value);
1628        }
1629
1630        if (value instanceof Identifier) {
1631            Identifier ctx = (Identifier) value;
1632            return evaluateVariable(ctx);
1633        }
1634
1635        return value;
1636    }
1637
1638    private Object JavaDoc visitExpression(SimpleNode node, Object JavaDoc data) {
1639        int n = node.jjtGetNumChildren();
1640        if (n == 1) {
1641            // conditionalExpression
1642
return node.jjtGetChild(0).jjtAccept(this, data);
1643        } else {
1644            // assignmentoperator conditionalExpression
1645
return node.jjtGetChild(2).jjtAccept(this, data);
1646        }
1647    }
1648
1649    private Object JavaDoc visitLiteral(SimpleNode node, Object JavaDoc data) {
1650        Token token = (Token) node.getAttribute("token");
1651        if (token == null) return node.jjtGetChild(0).jjtAccept(this, data);
1652
1653
1654        try {
1655            switch (token.kind) {
1656
1657            case JavaParser.INTEGER_LITERAL:
1658                // XXX might be simpler to use Long.decode()
1659
String JavaDoc name = token.image.toLowerCase();
1660                boolean isLong = name.endsWith("l");
1661                long value;
1662
1663                if (isLong) {
1664                    name = name.substring(0, name.length() -1);
1665                }
1666
1667                if (name.startsWith("0x")) {
1668                    value = Long.parseLong(name.substring(2), 16);
1669                }
1670                else if (name.length() > 1 && name.charAt(0) == '0') {
1671                    value = Long.parseLong(name.substring(1), 8);
1672                }
1673                else {
1674                    value = Long.parseLong(name);
1675                }
1676
1677                if (isLong) {
1678                    return vm.mirrorOf(value);
1679                }
1680                else {
1681                    if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
1682                        Assert.error(node, "integerLiteralTooBig", name);
1683                    }
1684                    else {
1685                        return vm.mirrorOf((int) value);
1686                    }
1687                }
1688
1689            case JavaParser.FLOATING_POINT_LITERAL:
1690                char spec = token.image.charAt(token.image.length() - 1);
1691                if (spec == 'f' || spec == 'F') {
1692                    return vm.mirrorOf(Float.parseFloat(token.image));
1693                } else {
1694                    return vm.mirrorOf(Double.parseDouble(token.image));
1695                }
1696
1697            case JavaParser.STRING_LITERAL:
1698                return vm.mirrorOf(resolveString(token.image.substring(1, token.image.length() - 1)));
1699
1700            case JavaParser.CHARACTER_LITERAL:
1701                return vm.mirrorOf(resolveString(token.image.substring(1, token.image.length() - 1)).charAt(0));
1702
1703            default:
1704                return Assert.error(node, "unknownLiteralType", token.image);
1705            }
1706        } catch (NumberFormatException JavaDoc e) {
1707            return Assert.error(node, "badFormatOfIntegerLiteral", token.image);
1708        }
1709    }
1710
1711    private String JavaDoc resolveString(String JavaDoc input) {
1712        String JavaDoc result = "";
1713        int index = 0;
1714        while (index < input.length()) {
1715            if (input.charAt(index) != '\\')
1716                result = result + input.charAt (index);
1717            else { // resolve an escape sequence
1718
index++;
1719                char c;
1720                switch (input.charAt(index)) {
1721                    case 'b': c = '\b'; break;
1722                    case 't': c = '\t'; break;
1723                    case 'n': c = '\n'; break;
1724                    case 'f': c = '\f'; break;
1725                    case 'r': c = '\r'; break;
1726                    case '\"': c = '\"'; break;
1727                    case '\'': c = '\''; break;
1728                    case '\\': c = '\\'; break;
1729
1730                    default:
1731                        // resolve octal value
1732
c = 0;
1733                        while ((index < input.length ()) &&
1734                            (input.charAt (index) >= '0') && (input.charAt (index) <= '7') &&
1735                            (c*8 + input.charAt (index) - '0' < 256)) {
1736                                c = (char) (c*8 + (input.charAt (index) - '0'));
1737                                index++;
1738                        } // while
1739
index--;
1740                } // switch
1741
result = result + c;
1742            } // else
1743
index++;
1744        } // while
1745
return result;
1746    }
1747
1748    private Object JavaDoc visitBinaryExpression(SimpleNode node, Object JavaDoc data) {
1749        Object JavaDoc [] operators = node.getAttributes("operator");
1750        int n = node.jjtGetNumChildren();
1751
1752        Value value = (Value) node.jjtGetChild(0).jjtAccept(this, data);
1753        for (int i = 1; i < n; i++) {
1754            Value next = (Value) node.jjtGetChild(i).jjtAccept(this, data);
1755            try {
1756                value = this.operators.evaluate(value, (Token) operators[i-1], next);
1757            } catch (IllegalArgumentException JavaDoc e) {
1758                return Assert.error(node, "evaluateError", value, ((Token) operators[i-1]).image, next);
1759            }
1760        }
1761        return value;
1762    }
1763
1764    public static Value invokeVirtual (
1765        ObjectReference objectReference,
1766        Method method,
1767        ThreadReference evaluationThread,
1768        List<Value> args
1769     ) throws InvalidExpressionException {
1770        
1771        if (verbose)
1772            throw new UnsupportedOperationException JavaDoc (NbBundle.getMessage (
1773                Evaluator.class,
1774                "CTL_UnsupportedOperationException"
1775            ));
1776        try {
1777            if (loggerMethod.isLoggable(Level.FINE)) {
1778                loggerMethod.fine("STARTED : "+objectReference+"."+method+" ("+args+") in thread "+evaluationThread);
1779            }
1780            Value value =
1781                    objectReference.invokeMethod(evaluationThread, method,
1782                                                 args,
1783                                                 ObjectReference.INVOKE_SINGLE_THREADED);
1784            if (loggerMethod.isLoggable(Level.FINE)) {
1785                loggerMethod.fine(" return = "+value);
1786            }
1787            return value;
1788        } catch (InvalidTypeException itex) {
1789            throw new InvalidExpressionException (itex);
1790        } catch (ClassNotLoadedException cnlex) {
1791            throw new InvalidExpressionException (cnlex);
1792        } catch (IncompatibleThreadStateException itsex) {
1793            InvalidExpressionException ieex = new InvalidExpressionException (itsex);
1794            ieex.initCause(itsex);
1795            throw ieex;
1796        } catch (InvocationException iex) {
1797            InvalidExpressionException ieex = new InvalidExpressionException (iex);
1798            ieex.initCause(iex);
1799            throw ieex;
1800        } catch (UnsupportedOperationException JavaDoc uoex) {
1801            InvalidExpressionException ieex = new InvalidExpressionException (uoex);
1802            ieex.initCause(uoex);
1803            throw ieex;
1804        } catch (ObjectCollectedException ocex) {
1805            throw new InvalidExpressionException(NbBundle.getMessage(
1806                Evaluator.class, "CTL_EvalError_collected"));
1807        } finally {
1808            if (loggerMethod.isLoggable(Level.FINE)) {
1809                loggerMethod.fine("FINISHED: "+objectReference+"."+method+" ("+args+") in thread "+evaluationThread);
1810            }
1811        }
1812    }
1813}
1814
Popular Tags