Source Code Cross Referenced for Evaluator.java in  » IDE-Netbeans » debugger » org » netbeans » modules » debugger » jpda » expr » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » debugger » org.netbeans.modules.debugger.jpda.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.debugger.jpda.expr;
0043:
0044:        import com.sun.jdi.*;
0045:
0046:        import java.util.*;
0047:        import java.util.logging.Level;
0048:        import java.util.logging.Logger;
0049:
0050:        import org.netbeans.api.debugger.jpda.InvalidExpressionException;
0051:        import org.netbeans.api.debugger.jpda.JPDAClassType;
0052:        import org.netbeans.api.debugger.jpda.JPDAThread;
0053:        import org.netbeans.modules.debugger.jpda.models.CallStackFrameImpl;
0054:        import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
0055:        import org.openide.util.NbBundle;
0056:
0057:        /**
0058:         * Engine that evaluates a Java expression in a context of a running JVM. The
0059:         * JVM (or at least the current thread) must be suspended. A single instance of this evaluator may
0060:         * only be used from a single thread, no multithreading support is provided.
0061:         *
0062:         * TODO: the evaluator should check the expression's language version
0063:         *
0064:         * @author Maros Sandor
0065:         */
0066:        public class Evaluator implements  JavaParserVisitor {
0067:
0068:            private static final boolean verbose = System
0069:                    .getProperty("netbeans.debugger.noInvokeMethods") != null;
0070:
0071:            private static final Logger loggerMethod = Logger
0072:                    .getLogger("org.netbeans.modules.debugger.jpda.invokeMethod"); // NOI18N
0073:            private static final Logger loggerValue = Logger
0074:                    .getLogger("org.netbeans.modules.debugger.jpda.getValue"); // NOI8N
0075:
0076:            private Expression expression;
0077:            private EvaluationContext evaluationContext;
0078:
0079:            private VirtualMachine vm;
0080:            private StackFrame frame;
0081:            private ThreadReference frameThread;
0082:            private int frameIndex;
0083:
0084:            private SimpleNode currentNode;
0085:            private String currentPackage;
0086:            private Operators operators;
0087:
0088:            Evaluator(Expression expression, EvaluationContext context) {
0089:                this .expression = expression;
0090:                this .evaluationContext = context;
0091:            }
0092:
0093:            /**
0094:             * Evaluates the expression for which it was created.
0095:             *
0096:             * @return the result of evaluating the expression as a JDI Value object.
0097:             *         It returns null if the result itself is null.
0098:             * @throws EvaluationException if the expression cannot be evaluated for whatever reason
0099:             * @throws IncompatibleThreadStateException if the context thread is in an
0100:             * incompatible state (running, dead)
0101:             */
0102:            public Value evaluate() throws EvaluationException,
0103:                    IncompatibleThreadStateException {
0104:                frame = evaluationContext.getFrame();
0105:                vm = evaluationContext.getFrame().virtualMachine();
0106:                frameThread = frame.thread();
0107:                frameIndex = indexOf(frameThread.frames(), frame);
0108:                if (frameIndex == -1) {
0109:                    throw new IncompatibleThreadStateException(
0110:                            "Thread does not contain current frame");
0111:                }
0112:                currentPackage = evaluationContext.getFrame().location()
0113:                        .declaringType().name();
0114:                int idx = currentPackage.lastIndexOf('.');
0115:                currentPackage = (idx > 0) ? currentPackage.substring(0,
0116:                        idx + 1) : "";
0117:                operators = new Operators(vm);
0118:                SimpleNode rootNode = expression.getRoot();
0119:                return (Value) rootNode.jjtAccept(this , null);
0120:            }
0121:
0122:            private int indexOf(List frames, StackFrame frame) {
0123:                int n = frames.size();
0124:                Location loc = frame.location();
0125:                for (int i = 0; i < n; i++) {
0126:                    if (loc.equals(((StackFrame) frames.get(i)).location()))
0127:                        return i;
0128:                }
0129:                return -1;
0130:            }
0131:
0132:            public Object visit(SimpleNode node, Object data)
0133:                    throws EvaluationException {
0134:                currentNode = node;
0135:                switch (node.jjtGetID()) {
0136:                case JavaParserTreeConstants.JJTRESULTTYPE:
0137:                    return visitResultType(node, data);
0138:
0139:                case JavaParserTreeConstants.JJTARRAYINITIALIZER:
0140:                    return visitArrayInitializer(node, data);
0141:
0142:                case JavaParserTreeConstants.JJTARRAYDIMSANDINITS:
0143:                    return visitArrayDimsAndInits(node, data);
0144:
0145:                case JavaParserTreeConstants.JJTALLOCATIONEXPRESSION:
0146:                    return visitAllocationExpression(node, data);
0147:
0148:                case JavaParserTreeConstants.JJTARGUMENTLIST:
0149:                    return visitArgumentList(node, data);
0150:
0151:                case JavaParserTreeConstants.JJTARGUMENTS:
0152:                    return visitArguments(node, data);
0153:
0154:                case JavaParserTreeConstants.JJTCASTEXPRESSION:
0155:                    return visitCastExpression(node, data);
0156:
0157:                case JavaParserTreeConstants.JJTPOSTFIXEXPRESSION:
0158:                    return visitPostfixExpression(node, data);
0159:
0160:                case JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION:
0161:                case JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION:
0162:                    return visitPrefixExpression(node, data);
0163:
0164:                case JavaParserTreeConstants.JJTUNARYEXPRESSION:
0165:                case JavaParserTreeConstants.JJTUNARYEXPRESSIONNOTPLUSMINUS:
0166:                    return visitUnaryExpression(node, data);
0167:
0168:                case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE:
0169:                    return visitClassOrInterfaceType(node, data);
0170:
0171:                case JavaParserTreeConstants.JJTIDENTIFIER:
0172:                    return visitIdentifier(node, data);
0173:
0174:                case JavaParserTreeConstants.JJTPRIMITIVETYPE:
0175:                    return visitPrimitiveType(node, data);
0176:
0177:                case JavaParserTreeConstants.JJTREFERENCETYPE:
0178:                    return visitReferenceType(node, data);
0179:
0180:                case JavaParserTreeConstants.JJTNAME:
0181:                    return visitName(node, data);
0182:
0183:                case JavaParserTreeConstants.JJTEXPRESSION:
0184:                    return visitExpression(node, data);
0185:
0186:                case JavaParserTreeConstants.JJTPRIMARYEXPRESSION:
0187:                    return visitPrimaryExpression(node, data);
0188:
0189:                case JavaParserTreeConstants.JJTPRIMARYPREFIX:
0190:                    return visitPrimaryPrefix(node, data);
0191:
0192:                case JavaParserTreeConstants.JJTPRIMARYSUFFIX:
0193:                    return visitPrimarySuffix(node, data);
0194:
0195:                case JavaParserTreeConstants.JJTCONDITIONALEXPRESSION:
0196:                    return visitConditionalExpression(node, data);
0197:
0198:                case JavaParserTreeConstants.JJTCONDITIONALOREXPRESSION:
0199:                case JavaParserTreeConstants.JJTCONDITIONALANDEXPRESSION:
0200:                    return visitConditionalOrAndExpression(node, data);
0201:
0202:                case JavaParserTreeConstants.JJTSHIFTEXPRESSION:
0203:                case JavaParserTreeConstants.JJTRELATIONALEXPRESSION:
0204:                case JavaParserTreeConstants.JJTEQUALITYEXPRESSION:
0205:                case JavaParserTreeConstants.JJTINCLUSIVEOREXPRESSION:
0206:                case JavaParserTreeConstants.JJTANDEXPRESSION:
0207:                case JavaParserTreeConstants.JJTEXCLUSIVEOREXPRESSION:
0208:                case JavaParserTreeConstants.JJTADDITIVEEXPRESSION:
0209:                case JavaParserTreeConstants.JJTMULTIPLICATIVEEXPRESSION:
0210:                    return visitBinaryExpression(node, data);
0211:
0212:                case JavaParserTreeConstants.JJTINSTANCEOFEXPRESSION:
0213:                    return visitInstanceOfExpression(node, data);
0214:
0215:                case JavaParserTreeConstants.JJTLITERAL:
0216:                    return visitLiteral(node, data);
0217:
0218:                case JavaParserTreeConstants.JJTBOOLEANLITERAL:
0219:                    return visitBooleanLiteral(node, data);
0220:
0221:                case JavaParserTreeConstants.JJTNULLLITERAL:
0222:                    return null;
0223:                }
0224:                return Assert.error(node, "unknownNonterminal");
0225:            }
0226:
0227:            private ObjectReference primitiveClass(String name)
0228:                    throws IncompatibleThreadStateException {
0229:                ReferenceType primType = resolveType("java.lang."
0230:                        + name.substring(0, 1).toUpperCase()
0231:                        + name.substring(1));
0232:                try {
0233:                    if (loggerValue.isLoggable(Level.FINE)) {
0234:                        loggerValue.fine("STARTED : " + primType + ".getValue("
0235:                                + primType.fieldByName("TYPE") + ")");
0236:                    }
0237:                    return (ObjectReference) primType.getValue(primType
0238:                            .fieldByName("TYPE"));
0239:                } finally {
0240:                    if (loggerValue.isLoggable(Level.FINE)) {
0241:                        loggerValue.fine("FINISHED: " + primType + ".getValue("
0242:                                + primType.fieldByName("TYPE") + ")");
0243:                    }
0244:                }
0245:            }
0246:
0247:            private Object visitResultType(SimpleNode node, Object data) {
0248:                try {
0249:                    if (node.getAttribute("void") != null) {
0250:                        return primitiveClass("void");
0251:                    }
0252:                    Type type = (Type) node.jjtGetChild(0)
0253:                            .jjtAccept(this , data);
0254:                    if (type instanceof  ReferenceType)
0255:                        return type;
0256:
0257:                    return primitiveClass(type.name());
0258:                } catch (IncompatibleThreadStateException e) {
0259:                    return Assert.error(node, "internalErrorResolvingType",
0260:                            "void");
0261:                }
0262:            }
0263:
0264:            private Object visitArrayInitializer(SimpleNode node, Object data) {
0265:                Object[] values = new Object[node.jjtGetNumChildren()];
0266:                for (int i = 0; i < values.length; i++) {
0267:                    values[i] = node.jjtGetChild(i).jjtAccept(this , data);
0268:                    if (!(values[i] instanceof  Value)
0269:                            && !(values[i] instanceof  Object[])) {
0270:                        Assert
0271:                                .error(node, "invalidArrayInitializer",
0272:                                        values[i]);
0273:                    }
0274:                }
0275:                return values;
0276:            }
0277:
0278:            private Object visitArrayDimsAndInits(SimpleNode node, Object data) {
0279:
0280:                Type arrayType = (Type) data;
0281:                int dimensions = ((Integer) node.getAttribute("dimensions"))
0282:                        .intValue();
0283:                ArrayReference arrayRef = null;
0284:
0285:                try {
0286:                    if (node.getAttribute("initializers") != null) {
0287:                        Object[] initValues = (Object[]) node.jjtGetChild(0)
0288:                                .jjtAccept(this , data);
0289:                        return createArray(arrayType, dimensions, initValues);
0290:                    } else {
0291:                        int sizeCount = node.jjtGetNumChildren();
0292:                        int[] sizes = new int[sizeCount];
0293:                        for (int i = 0; i < sizeCount; i++) {
0294:                            Object sizeObj = node.jjtGetChild(i).jjtAccept(
0295:                                    this , data);
0296:                            Assert.assertAssignable(sizeObj,
0297:                                    PrimitiveValue.class, node,
0298:                                    "arraySizeBadType", sizeObj);
0299:                            Assert.assertNotAssignable(sizeObj,
0300:                                    BooleanValue.class, node,
0301:                                    "arraySizeBadType", sizeObj);
0302:                            Assert.assertNotAssignable(sizeObj,
0303:                                    FloatValue.class, node, "arraySizeBadType",
0304:                                    sizeObj);
0305:                            Assert.assertNotAssignable(sizeObj,
0306:                                    DoubleValue.class, node,
0307:                                    "arraySizeBadType", sizeObj);
0308:                            sizes[i] = ((PrimitiveValue) sizeObj).intValue();
0309:                        }
0310:                        return createArray(arrayType, dimensions, sizes, 0);
0311:                    }
0312:                } catch (IncompatibleThreadStateException e) {
0313:                    Assert.error(node, "arrayCreateError", e);
0314:                } catch (ClassNotLoadedException e) {
0315:                    Assert.error(node, "arrayCreateError", e);
0316:                } catch (InvalidTypeException e) {
0317:                    Assert.error(node, "arrayCreateError", e);
0318:                } catch (UnsupportedOperationException uoex) {
0319:                    return Assert.error(node, "calleeException", uoex);
0320:                }
0321:
0322:                return arrayRef;
0323:            }
0324:
0325:            private String brackets = "[[[[[[[[[[[[[[[[[[[";
0326:
0327:            private String brackets(int length) {
0328:                if (brackets.length() < length) {
0329:                    char[] bracketsArray = new char[length];
0330:                    Arrays.fill(bracketsArray, '[');
0331:                    brackets = new String(bracketsArray);
0332:                }
0333:                return brackets.substring(0, length);
0334:            }
0335:
0336:            private ArrayReference createArray(Type baseType, int dimensions,
0337:                    int[] sizes, int index)
0338:                    throws IncompatibleThreadStateException,
0339:                    ClassNotLoadedException, InvalidTypeException {
0340:
0341:                ArrayType arrayType = (ArrayType) resolveType(brackets(dimensions)
0342:                        + baseType.signature());
0343:                ArrayReference arrayRef = arrayType.newInstance(sizes[index]);
0344:                if (sizes.length > index + 1) {
0345:                    for (int i = 0; i < sizes[index]; i++) {
0346:                        arrayRef.setValue(i, createArray(baseType,
0347:                                dimensions - 1, sizes, index + 1));
0348:                    }
0349:                }
0350:                return arrayRef;
0351:            }
0352:
0353:            private ArrayReference createArray(Type baseType, int dimensions,
0354:                    Object[] values) throws IncompatibleThreadStateException,
0355:                    ClassNotLoadedException, InvalidTypeException {
0356:
0357:                ArrayType arrayType = (ArrayType) resolveType(brackets(dimensions)
0358:                        + baseType.signature());
0359:                ArrayReference arrayRef = arrayType.newInstance(values.length);
0360:                for (int i = 0; i < values.length; i++) {
0361:                    if (values[i] instanceof  Object[]) {
0362:                        arrayRef.setValue(i, createArray(baseType,
0363:                                dimensions - 1, (Object[]) values[i]));
0364:                    } else {
0365:                        arrayRef.setValue(i, (Value) values[i]);
0366:                    }
0367:                }
0368:                return arrayRef;
0369:            }
0370:
0371:            private Object visitAllocationExpression(SimpleNode node,
0372:                    Object data) {
0373:
0374:                Type arrayType = (Type) node.jjtGetChild(0).jjtAccept(this ,
0375:                        data);
0376:
0377:                // new object creation
0378:                if (((SimpleNode) node.jjtGetChild(1)).jjtGetID() == JavaParserTreeConstants.JJTARGUMENTS) {
0379:                    if (arrayType instanceof  ClassType) {
0380:                        Identifier fvmc = new Identifier(false,
0381:                                (ReferenceType) arrayType, "<init>");
0382:                        return node.jjtGetChild(1).jjtAccept(this , fvmc);
0383:                    }
0384:                    Assert.assertNotAssignable(arrayType, InterfaceType.class,
0385:                            node, "instantiateInterface", arrayType.name());
0386:                }
0387:
0388:                // an array
0389:                return node.jjtGetChild(1).jjtAccept(this , arrayType);
0390:            }
0391:
0392:            private Object visitPrimitiveType(SimpleNode node, Object data) {
0393:                //TODO: cache primitive types
0394:                Token token = (Token) node.getAttribute("token");
0395:                switch (token.kind) {
0396:                case JavaParserConstants.BOOLEAN:
0397:                    return vm.mirrorOf(true).type();
0398:                case JavaParserConstants.CHAR:
0399:                    return vm.mirrorOf('a').type();
0400:                case JavaParserConstants.BYTE:
0401:                    return vm.mirrorOf((byte) 0).type();
0402:                case JavaParserConstants.SHORT:
0403:                    return vm.mirrorOf((short) 0).type();
0404:                case JavaParserConstants.INT:
0405:                    return vm.mirrorOf(0).type();
0406:                case JavaParserConstants.LONG:
0407:                    return vm.mirrorOf(0L).type();
0408:                case JavaParserConstants.FLOAT:
0409:                    return vm.mirrorOf(1.0f).type();
0410:                case JavaParserConstants.DOUBLE:
0411:                    return vm.mirrorOf(1.0).type();
0412:                default:
0413:                    throw new RuntimeException("Unknown primitive type: "
0414:                            + token.image);
0415:                }
0416:            }
0417:
0418:            private Object visitCastExpression(SimpleNode node, Object data) {
0419:                Object value = node.jjtGetChild(1).jjtAccept(this , data);
0420:                if (value == null)
0421:                    return null;
0422:                Type castType = (Type) node.jjtGetChild(0)
0423:                        .jjtAccept(this , data);
0424:
0425:                if (value instanceof  PrimitiveValue) {
0426:                    PrimitiveValue primValue = (PrimitiveValue) value;
0427:                    if (primValue instanceof  BooleanValue) {
0428:                        Assert.assertAssignable(castType, BooleanType.class,
0429:                                node, "castToBooleanRequired", primValue,
0430:                                castType);
0431:                        return primValue;
0432:                    }
0433:                    Assert.assertNotAssignable(castType, BooleanType.class,
0434:                            node, "castFromBooleanRequired", primValue,
0435:                            castType);
0436:                    if (castType instanceof  ByteType) {
0437:                        return vm.mirrorOf(primValue.byteValue());
0438:                    } else if (castType instanceof  CharType) {
0439:                        return vm.mirrorOf(primValue.charValue());
0440:                    } else if (castType instanceof  DoubleType) {
0441:                        return vm.mirrorOf(primValue.doubleValue());
0442:                    } else if (castType instanceof  FloatType) {
0443:                        return vm.mirrorOf(primValue.floatValue());
0444:                    } else if (castType instanceof  IntegerType) {
0445:                        return vm.mirrorOf(primValue.intValue());
0446:                    } else if (castType instanceof  LongType) {
0447:                        return vm.mirrorOf(primValue.longValue());
0448:                    } else {
0449:                        return vm.mirrorOf(primValue.shortValue());
0450:                    }
0451:                }
0452:
0453:                // value is an object reference
0454:                ObjectReference valueType = (ObjectReference) value;
0455:                if (!instanceOf(valueType.type(), castType)) {
0456:                    Assert.error(node, "castError", valueType.type(), castType);
0457:                }
0458:                return value;
0459:            }
0460:
0461:            /**
0462:             * Evaluates a postfix expression (i++). This evaluation does NOT modify the variable i as would be
0463:             * the case in the real life. It also does not check that the operand is a variable, thus 6++ is also legal.
0464:             * These checks are really not necessary here in the evaluator.
0465:             *
0466:             * @param node
0467:             * @param data
0468:             * @return
0469:             */
0470:            private Object visitPostfixExpression(SimpleNode node, Object data) {
0471:                Object value = node.jjtGetChild(0).jjtAccept(this , data);
0472:                Assert.assertAssignable(value, PrimitiveValue.class, node,
0473:                        "badOperandForPostfixOperator", value);
0474:                Assert.assertNotAssignable(value, BooleanValue.class, node,
0475:                        "badOperandForPostfixOperator", value);
0476:
0477:                Token operator = (Token) node.getAttribute("operator");
0478:                try {
0479:                    return operators.evaluate(operator, (PrimitiveValue) value);
0480:                } catch (IllegalArgumentException e) {
0481:                    return Assert.error(node, "postfixOperatorEvaluationError",
0482:                            operator, e);
0483:                }
0484:            }
0485:
0486:            /**
0487:             * Evaluates a prefix expression (++i). This evaluation does NOT modify the variable i as would be
0488:             * the case in the real life. It also does not check that the operand is a variable, thus ++6 is also legal.
0489:             * These checks are really not necessary here in the evaluator.
0490:             *
0491:             * @param node
0492:             * @param data
0493:             * @return
0494:             */
0495:            private Object visitPrefixExpression(SimpleNode node, Object data) {
0496:                Object value = node.jjtGetChild(0).jjtAccept(this , data);
0497:                Assert.assertAssignable(value, PrimitiveValue.class, node,
0498:                        "badOperandForPrefixOperator", value);
0499:                Assert.assertNotAssignable(value, BooleanValue.class, node,
0500:                        "badOperandForPrefixOperator", value);
0501:
0502:                Token operator = (Token) node.getAttribute("operator");
0503:                try {
0504:                    return operators.evaluate(operator, (PrimitiveValue) value);
0505:                } catch (IllegalArgumentException e) {
0506:                    return Assert.error(node, "prefixOperatorEvaluationError",
0507:                            operator, e);
0508:                }
0509:            }
0510:
0511:            private Object visitUnaryExpression(SimpleNode node, Object data) {
0512:
0513:                Object value = node.jjtGetChild(0).jjtAccept(this , data);
0514:                //        System.out.println("In visitUnaryExpression:");
0515:                //        System.out.println("value -> " + value);
0516:                //        System.out.println("value.class -> " + value.getClass());
0517:                //        System.out.println("PrimitiveValue.class -> " + PrimitiveValue.class);
0518:                //        System.out.println("BooleanValue.class -> " + BooleanValue.class);
0519:                //        System.out.println("Assignable ? " + BooleanValue.class.isAssignableFrom(value.getClass()));
0520:                Assert.assertAssignable(value, PrimitiveValue.class, node,
0521:                        "badOperandForUnaryOperator", value);
0522:                // Assert on next line is probably a mistake:
0523:                //Assert.assertNotAssignable(value, BooleanValue.class, node, "badOperandForUnaryOperator", value);
0524:
0525:                Token operator = (Token) node.getAttribute("operator");
0526:                try {
0527:                    return operators.evaluate(operator, (PrimitiveValue) value);
0528:                } catch (IllegalArgumentException e) {
0529:                    return Assert.error(node, "unaryOperatorEvaluationError",
0530:                            operator, e);
0531:                }
0532:            }
0533:
0534:            private Object visitIdentifier(SimpleNode node, Object data) {
0535:                return ((Token) node.getAttribute("token")).image;
0536:            }
0537:
0538:            private Object visitClassOrInterfaceType(SimpleNode node,
0539:                    Object data) {
0540:
0541:                StringBuffer fullName = new StringBuffer();
0542:
0543:                int n = node.jjtGetNumChildren();
0544:                for (int i = 0; i < n; i++) {
0545:                    String namePart = (String) node.jjtGetChild(i).jjtAccept(
0546:                            this , data);
0547:                    fullName.append('.');
0548:                    fullName.append(namePart);
0549:
0550:                    if (i < n - 1) {
0551:                        SimpleNode nextNode = (SimpleNode) node
0552:                                .jjtGetChild(i + 1);
0553:                        if (nextNode.jjtGetID() == JavaParserTreeConstants.JJTTYPEARGUMENTS) {
0554:                            i++;
0555:                        }
0556:                    }
0557:                }
0558:
0559:                String name = fullName.substring(1);
0560:                try {
0561:                    return resolveType(name);
0562:                } catch (IncompatibleThreadStateException e) {
0563:                    return Assert.error(node, "internalErrorResolvingType",
0564:                            name);
0565:                }
0566:            }
0567:
0568:            /**
0569:             * Resolving of types is slow.
0570:             *
0571:             * @param name
0572:             * @return
0573:             * @throws IncompatibleThreadStateException
0574:             */
0575:            private ReferenceType resolveType(String name)
0576:                    throws IncompatibleThreadStateException {
0577:                ReferenceType type;
0578:
0579:                if (name.charAt(0) == '[') {
0580:                    if ((type = getClass(name)) != null)
0581:                        return type;
0582:                    Assert.error(currentNode, "unknownType", name);
0583:                }
0584:
0585:                String innerName = frame.location().declaringType().name()
0586:                        + "$" + name;
0587:                if ((type = getClass(innerName)) != null)
0588:                    return type;
0589:
0590:                int idx = name.lastIndexOf('.');
0591:                if (idx == -1) {
0592:                    if ((type = getClass(currentPackage + name)) != null)
0593:                        return type;
0594:                } else {
0595:                    if ((type = getClass(name)) != null)
0596:                        return type;
0597:                }
0598:
0599:                if (idx != -1) {
0600:                    innerName = name.substring(0, idx) + "$"
0601:                            + name.substring(idx + 1);
0602:                    if (innerName.indexOf('.') == -1)
0603:                        innerName = currentPackage + innerName;
0604:                    if ((type = getClass(innerName)) != null)
0605:                        return type;
0606:                }
0607:
0608:                List imports = evaluationContext.getImports();
0609:                for (Iterator i = imports.iterator(); i.hasNext();) {
0610:                    String importStatement = (String) i.next();
0611:                    int ix = importStatement.lastIndexOf('.');
0612:                    String qualifier = importStatement.substring(ix + 1);
0613:                    if (!qualifier.equals("*") && !qualifier.equals(name))
0614:                        continue;
0615:                    String fullName = importStatement.substring(0, ix + 1)
0616:                            + name;
0617:                    type = getClass(fullName);
0618:                    if (type != null)
0619:                        return type;
0620:                }
0621:
0622:                Assert.error(currentNode, "unknownType", name);
0623:                return null;
0624:            }
0625:
0626:            private ReferenceType getClass(String typeName)
0627:                    throws IncompatibleThreadStateException {
0628:
0629:                List classes = vm.classesByName(typeName);
0630:                if (classes.size() != 0) {
0631:                    return (ReferenceType) classes.get(0);
0632:                }
0633:
0634:                //        if (forName == null) {
0635:                //            try {
0636:                //                ClassObjectReference executingClass = frame.location().declaringType().classObject();
0637:                //                ClassType currentClass = (ClassType) executingClass.referenceType();
0638:                //                forName = currentClass.concreteMethodByName("forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
0639:                //            } catch (Exception e) {
0640:                //                // The should not happen
0641:                //            }
0642:                //        }
0643:                //
0644:                //        try {
0645:                //            ClassLoaderReference executingClassloader = frame.location().declaringType().classLoader();
0646:                //            ClassObjectReference executingClass = frame.location().declaringType().classObject();
0647:                //            List args = new ArrayList();
0648:                //            args.add(vm.mirrorOf(typeName));
0649:                //            args.add(vm.mirrorOf(true));
0650:                //            args.add(executingClassloader);
0651:                //            if (verbose) {
0652:                //                throw new UnsupportedOperationException (NbBundle.getMessage (
0653:                //                    Evaluator.class, 
0654:                //                    "CTL_UnsupportedOperationException"
0655:                //                )); 
0656:                //            }
0657:                //            ClassObjectReference cor = (ClassObjectReference) executingClass.
0658:                //                invokeMethod (frameThread, forName, args, 0);
0659:                //            return cor.reflectedType();
0660:                //        } catch (Exception e) {
0661:                //            // The class cannot be loaded, return null
0662:                //        } finally {
0663:                //            // the stack frame may have been invalidated by invoking the forName method
0664:                //            frame = frameThread.frame(frameIndex);
0665:                //        }
0666:                return null;
0667:            }
0668:
0669:            private Object visitReferenceType(SimpleNode node, Object data) {
0670:                Type baseType = (Type) node.jjtGetChild(0)
0671:                        .jjtAccept(this , data);
0672:                int dimensions = ((Integer) node.getAttribute("arrayCount"))
0673:                        .intValue();
0674:                if (dimensions > 0) {
0675:                    try {
0676:                        return resolveType(brackets(dimensions)
0677:                                + baseType.signature().replace('/', '.'));
0678:                    } catch (IncompatibleThreadStateException e) {
0679:                        Assert.error(node, "internalError");
0680:                    }
0681:                }
0682:                return baseType;
0683:            }
0684:
0685:            private Object visitInstanceOfExpression(SimpleNode node,
0686:                    Object data) {
0687:
0688:                Object leftOper = node.jjtGetChild(0).jjtAccept(this , data);
0689:                if (leftOper == null)
0690:                    return vm.mirrorOf(false);
0691:                Assert.assertAssignable(leftOper, ObjectReference.class, node,
0692:                        "instanceOfLeftOperandNotAReference", leftOper);
0693:
0694:                ReferenceType left = ((ObjectReference) leftOper)
0695:                        .referenceType(); // org.netbeans.Sucks
0696:                ReferenceType right = (ReferenceType) node.jjtGetChild(1)
0697:                        .jjtAccept(this , data); // int []
0698:
0699:                return vm.mirrorOf(instanceOf(left, right));
0700:            }
0701:
0702:            private boolean instanceOf(Type left, Type right) {
0703:                if (left == null)
0704:                    return false;
0705:                if (left.equals(right))
0706:                    return true;
0707:
0708:                if (right instanceof  ArrayType) {
0709:                    if (!(left instanceof  ArrayType)) {
0710:                        return false;
0711:                    } else {
0712:                        ArrayType leftArray = (ArrayType) left;
0713:                        ArrayType rightArray = (ArrayType) right;
0714:                        Type leftType;
0715:                        Type rightType;
0716:                        try {
0717:                            leftType = leftArray.componentType();
0718:                            rightType = rightArray.componentType();
0719:                        } catch (ClassNotLoadedException e) {
0720:                            // TODO: load missing classes
0721:                            return false;
0722:                        }
0723:                        return instanceOf(leftType, rightType);
0724:                    }
0725:                }
0726:
0727:                if (left instanceof  ClassType) {
0728:                    ClassType classLeft = (ClassType) left;
0729:                    if (right instanceof  InterfaceType) {
0730:                        List ifaces = classLeft.allInterfaces();
0731:                        for (Iterator i = ifaces.iterator(); i.hasNext();) {
0732:                            InterfaceType type = (InterfaceType) i.next();
0733:                            if (type.equals(right))
0734:                                return true;
0735:                        }
0736:                        return false;
0737:                    } else { // right instanceof ClassType
0738:                        for (;;) {
0739:                            classLeft = classLeft.super class();
0740:                            if (classLeft == null)
0741:                                return false;
0742:                            if (classLeft.equals(right))
0743:                                return true;
0744:                        }
0745:                    }
0746:                }
0747:
0748:                return false;
0749:            }
0750:
0751:            private Object visitConditionalOrAndExpression(SimpleNode node,
0752:                    Object data) {
0753:
0754:                Token operator = (Token) node.getAttribute("operator");
0755:
0756:                int n = node.jjtGetNumChildren();
0757:                for (int i = 0; i < n; i++) {
0758:                    Object value = node.jjtGetChild(i).jjtAccept(this , data);
0759:                    Assert.assertAssignable(value, BooleanValue.class, node,
0760:                            "conditionalOrAndBooleanOperandRequired", value);
0761:                    boolean val = ((BooleanValue) value).booleanValue();
0762:                    if (operator.kind == JavaParserConstants.SC_OR && val
0763:                            || operator.kind == JavaParserConstants.SC_AND
0764:                            && !val) {
0765:                        return value;
0766:                    }
0767:                }
0768:                return vm.mirrorOf(operator.kind == JavaParserConstants.SC_AND);
0769:            }
0770:
0771:            private Object visitConditionalExpression(SimpleNode node,
0772:                    Object data) {
0773:
0774:                Object condition = node.jjtGetChild(0).jjtAccept(this , data);
0775:                Assert.assertAssignable(condition, BooleanValue.class, node,
0776:                        "conditionalQuestionMarkBooleanOperandRequired",
0777:                        condition);
0778:
0779:                boolean val = ((BooleanValue) condition).booleanValue();
0780:
0781:                if (val) {
0782:                    return node.jjtGetChild(1).jjtAccept(this , data);
0783:                } else {
0784:                    return node.jjtGetChild(2).jjtAccept(this , data);
0785:                }
0786:            }
0787:
0788:            private Object visitBooleanLiteral(SimpleNode node, Object data) {
0789:                Token token = (Token) node.getAttribute("token");
0790:                return vm.mirrorOf(token.kind == JavaParserConstants.TRUE);
0791:            }
0792:
0793:            private Object visitName(SimpleNode node, Object data) {
0794:                Object[] tokens = node.getAttributes("token");
0795:                StringBuffer name = new StringBuffer();
0796:                for (int i = 0; i < tokens.length; i++) {
0797:                    name.append('.');
0798:                    name.append(tokens[i]);
0799:                }
0800:                return name.substring(1);
0801:            }
0802:
0803:            private Object visitPrimaryPrefix(SimpleNode node, Object data) {
0804:
0805:                if (node.jjtGetNumChildren() == 0) {
0806:                    ObjectReference this Object = frame.this Object();
0807:                    if (this Object == null) {
0808:                        Assert.error(node, "thisObjectUnavailable");
0809:                    }
0810:
0811:                    if (node.getAttribute("this") != null)
0812:                        return this Object; // this
0813:
0814:                    // (X.)*super.X?
0815:                    String qualifier = (String) node.getAttribute("qualifier");
0816:                    String identifier = (String) node
0817:                            .getAttribute("identifier");
0818:
0819:                    return new Identifier((ObjectReference) this Object,
0820:                            identifier, qualifier);
0821:                }
0822:
0823:                SimpleNode first = (SimpleNode) node.jjtGetChild(0);
0824:                switch (first.jjtGetID()) {
0825:
0826:                case JavaParserTreeConstants.JJTLITERAL:
0827:                    return visit(first, data);
0828:
0829:                case JavaParserTreeConstants.JJTEXPRESSION:
0830:                    return visit(first, data);
0831:
0832:                case JavaParserTreeConstants.JJTNAME: {
0833:                    String identifier = (String) visit(first, data);
0834:                    if (identifier.indexOf('.') == -1) {
0835:                        return new Identifier(true, frame.this Object(), frame
0836:                                .location().declaringType(), identifier);
0837:                    }
0838:
0839:                    // check for variable dereference:  var.toString
0840:                    int idx = identifier.indexOf('.');
0841:                    String name = identifier.substring(0, idx);
0842:
0843:                    ObjectReference member = null;
0844:                    try {
0845:                        Value variable = evaluateVariable(new Identifier(true,
0846:                                frame.this Object(), frame.location()
0847:                                        .declaringType(), name));
0848:                        Assert.assertAssignable(variable,
0849:                                ObjectReference.class, node,
0850:                                "objectReferenceRequiredOnDereference",
0851:                                variable);
0852:                        member = (ObjectReference) variable;
0853:                    } catch (EvaluationException e) {
0854:                        // not a variable
0855:                    }
0856:
0857:                    ReferenceType type = null;
0858:                    if (member == null) {
0859:                        // type declaration first: System.out, or java.lang.System.out.println
0860:                        for (;;) {
0861:                            try {
0862:                                type = resolveType(name);
0863:                                break;
0864:                            } catch (EvaluationException e) {
0865:                                // unknown type
0866:                            } catch (IncompatibleThreadStateException e) {
0867:                                Assert.error(node, "internalError");
0868:                            }
0869:                            idx = identifier.indexOf('.', idx + 1);
0870:                            if (idx == -1)
0871:                                break;
0872:                            name = identifier.substring(0, idx);
0873:                        }
0874:                        if (type == null)
0875:                            Assert.error(node, "unknownType", identifier);
0876:                    }
0877:
0878:                    // resolve dereferences until the last name component
0879:                    for (;;) {
0880:                        int idx2 = identifier.indexOf('.', idx + 1);
0881:                        int idx22 = idx2;
0882:                        if (idx2 == -1) {
0883:                            idx2 = identifier.length();
0884:                        }
0885:                        Identifier ident;
0886:                        if (member != null) {
0887:                            ident = new Identifier(false, member, identifier
0888:                                    .substring(idx + 1, idx2));
0889:                        } else {
0890:                            ident = new Identifier(false, type, identifier
0891:                                    .substring(idx + 1, idx2));
0892:                        }
0893:                        if (idx22 == -1)
0894:                            return ident;
0895:                        Value variable = evaluateVariable(ident);
0896:                        Assert.assertAssignable(variable,
0897:                                ObjectReference.class, node,
0898:                                "objectReferenceRequiredOnDereference",
0899:                                variable);
0900:                        member = (ObjectReference) variable;
0901:                        idx = idx2;
0902:                    }
0903:                }
0904:                case JavaParserTreeConstants.JJTRESULTTYPE:
0905:                    Object type = first.jjtAccept(this , data);
0906:                    if (type instanceof  ReferenceType) {
0907:                        return ((ReferenceType) type).classObject();
0908:                    } else {
0909:                        return type;
0910:                    }
0911:
0912:                default:
0913:                    return first.jjtAccept(this , data);
0914:                }
0915:            }
0916:
0917:            private Object visitArgumentList(SimpleNode node, Object data) {
0918:                int n = node.jjtGetNumChildren();
0919:                Value[] argValues = new Value[n];
0920:                for (int i = 0; i < n; i++) {
0921:                    Object val = node.jjtGetChild(i).jjtAccept(this , data);
0922:                    if (val != null)
0923:                        Assert.assertAssignable(val, Value.class, node,
0924:                                "badArgument", val);
0925:                    argValues[i] = (Value) val;
0926:                }
0927:                return argValues;
0928:            }
0929:
0930:            private class MethodCall {
0931:                ReferenceType typeContext;
0932:                ObjectReference instanceContext;
0933:                Method method;
0934:                List<Value> args;
0935:
0936:                public MethodCall(ReferenceType typeContext,
0937:                        ObjectReference instanceContext, Method method,
0938:                        List<Value> args) {
0939:                    this .typeContext = typeContext;
0940:                    this .instanceContext = instanceContext;
0941:                    this .method = method;
0942:                    this .args = args;
0943:                }
0944:            }
0945:
0946:            private Object visitArguments(SimpleNode node, Object data) {
0947:                Assert.assertAssignable(data, Identifier.class, node,
0948:                        "argumentsBadSyntax", data);
0949:                Identifier ctx = (Identifier) data;
0950:
0951:                Value[] args;
0952:                if (node.jjtGetNumChildren() > 0) {
0953:                    args = (Value[]) node.jjtGetChild(0).jjtAccept(this , null);
0954:                } else {
0955:                    args = new Value[0];
0956:                }
0957:
0958:                MethodCall method;
0959:                try {
0960:                    method = getConcreteMethod(ctx, args);
0961:                } catch (UnsupportedOperationException uoex) {
0962:                    return Assert.error(node, "calleeException", uoex, ctx);
0963:                }
0964:
0965:                if (method.instanceContext != null) {
0966:                    try {
0967:                        if (verbose)
0968:                            throw new UnsupportedOperationException(
0969:                                    NbBundle
0970:                                            .getMessage(Evaluator.class,
0971:                                                    "CTL_UnsupportedOperationException"));
0972:                        if (!evaluationContext.canInvokeMethods()) {
0973:                            return Assert.error(node, "calleeException",
0974:                                    new UnsupportedOperationException(), ctx);
0975:                        }
0976:                        evaluationContext.methodToBeInvoked();
0977:                        if (loggerMethod.isLoggable(Level.FINE)) {
0978:                            loggerMethod.fine("STARTED : "
0979:                                    + method.instanceContext + "."
0980:                                    + method.method + " (" + method.args
0981:                                    + ") in thread " + frameThread);
0982:                        }
0983:                        return method.instanceContext.invokeMethod(frameThread,
0984:                                method.method, method.args,
0985:                                ObjectReference.INVOKE_SINGLE_THREADED
0986:                                        | ObjectReference.INVOKE_NONVIRTUAL);
0987:                    } catch (InvalidTypeException e) {
0988:                        Assert.error(node, "callException", e, ctx);
0989:                    } catch (ClassNotLoadedException e) {
0990:                        // TODO: load the class
0991:                        Assert.error(node, "callException", e, ctx);
0992:                    } catch (IncompatibleThreadStateException e) {
0993:                        Assert.error(node, "callException", e, ctx);
0994:                    } catch (InvocationException e) {
0995:                        Assert.error(node, "calleeException", e, ctx);
0996:                    } catch (UnsupportedOperationException e) {
0997:                        evaluationContext.setCanInvokeMethods(false);
0998:                        Assert.error(node, "calleeException", e, ctx);
0999:                    } finally {
1000:                        if (loggerMethod.isLoggable(Level.FINE)) {
1001:                            loggerMethod.fine("FINISHED: "
1002:                                    + method.instanceContext + "."
1003:                                    + method.method + " (" + method.args
1004:                                    + ") in thread " + frameThread);
1005:                        }
1006:                        try {
1007:                            evaluationContext.methodInvokeDone();
1008:                        } catch (IncompatibleThreadStateException itsex) {
1009:                            InvalidExpressionException ieex = new InvalidExpressionException(
1010:                                    itsex);
1011:                            ieex.initCause(itsex);
1012:                            throw new IllegalStateException(ieex);
1013:                        }
1014:                        try {
1015:                            frame = frameThread.frame(frameIndex);
1016:                        } catch (IncompatibleThreadStateException e) {
1017:                            Assert.error(node, "callException", e, ctx);
1018:                        }
1019:                    }
1020:                }
1021:
1022:                if (method.typeContext instanceof  ClassType) {
1023:                    ClassType classContext = (ClassType) method.typeContext;
1024:                    try {
1025:                        if (method.method.isConstructor()) {
1026:                            if (verbose)
1027:                                throw new UnsupportedOperationException(
1028:                                        NbBundle
1029:                                                .getMessage(Evaluator.class,
1030:                                                        "CTL_UnsupportedOperationException"));
1031:                            try {
1032:                                return classContext.newInstance(frameThread,
1033:                                        method.method, method.args,
1034:                                        ClassType.INVOKE_SINGLE_THREADED);
1035:                            } catch (UnsupportedOperationException uoex) {
1036:                                return Assert.error(node, "calleeException",
1037:                                        uoex, ctx);
1038:                            }
1039:                        } else {
1040:                            if (verbose)
1041:                                throw new UnsupportedOperationException(
1042:                                        NbBundle
1043:                                                .getMessage(Evaluator.class,
1044:                                                        "CTL_UnsupportedOperationException"));
1045:                            if (!evaluationContext.canInvokeMethods()) {
1046:                                return Assert.error(node, "calleeException",
1047:                                        new UnsupportedOperationException(),
1048:                                        ctx);
1049:                            }
1050:                            evaluationContext.methodToBeInvoked();
1051:                            return classContext.invokeMethod(frameThread,
1052:                                    method.method, method.args,
1053:                                    ClassType.INVOKE_SINGLE_THREADED);
1054:                        }
1055:                    } catch (InvalidTypeException e) {
1056:                        Assert.error(node, "callException", e, ctx);
1057:                    } catch (ClassNotLoadedException e) {
1058:                        // TODO: load the class
1059:                        Assert.error(node, "callException", e, ctx);
1060:                    } catch (IncompatibleThreadStateException e) {
1061:                        Assert.error(node, "callException", e, ctx);
1062:                    } catch (InvocationException e) {
1063:                        Assert.error(node, "calleeException", e, ctx);
1064:                    } catch (IllegalArgumentException e) {
1065:                        Assert.error(node, "callException", e, ctx);
1066:                    } catch (UnsupportedOperationException e) {
1067:                        evaluationContext.setCanInvokeMethods(false);
1068:                        Assert.error(node, "calleeException", e, ctx);
1069:                    } finally {
1070:                        try {
1071:                            evaluationContext.methodInvokeDone();
1072:                        } catch (IncompatibleThreadStateException itsex) {
1073:                            InvalidExpressionException ieex = new InvalidExpressionException(
1074:                                    itsex);
1075:                            ieex.initCause(itsex);
1076:                            throw new IllegalStateException(ieex);
1077:                        }
1078:                        try {
1079:                            frame = frameThread.frame(frameIndex);
1080:                        } catch (IncompatibleThreadStateException e) {
1081:                            Assert.error(node, "callException", e, ctx);
1082:                        }
1083:                    }
1084:                }
1085:
1086:                return Assert.error(node, "noSuchMethod", ctx);
1087:            }
1088:
1089:            private boolean isAccessible(TypeComponent member) {
1090:                if (member.isPublic())
1091:                    return true;
1092:
1093:                ReferenceType callerType = frame.location().declaringType();
1094:                ReferenceType calleeType = member.declaringType();
1095:
1096:                if (member.isPrivate()) {
1097:                    if (callerType.equals(calleeType))
1098:                        return true;
1099:                    if (isNested(calleeType, callerType)
1100:                            || isNested(callerType, calleeType))
1101:                        return true;
1102:                    return false;
1103:                }
1104:
1105:                String callerName = callerType.name();
1106:                String calleeName = calleeType.name();
1107:                int idx1 = callerName.lastIndexOf('.');
1108:                int idx2 = calleeName.lastIndexOf('.');
1109:
1110:                if (idx1 * idx2 < 0)
1111:                    return false;
1112:                if (idx1 + idx2 == -2)
1113:                    return true;
1114:
1115:                if (callerName.substring(0, idx1).equals(
1116:                        calleeName.substring(0, idx2)))
1117:                    return true;
1118:                if (member.isProtected()) {
1119:                    return instanceOf(callerType, calleeType);
1120:                }
1121:
1122:                return false;
1123:            }
1124:
1125:            private boolean isNested(ReferenceType outter, ReferenceType inner) {
1126:                List nestedTypes = outter.nestedTypes();
1127:                for (Iterator i = nestedTypes.iterator(); i.hasNext();) {
1128:                    ReferenceType type = (ReferenceType) i.next();
1129:                    if (type.equals(inner) || isNested(type, inner))
1130:                        return true;
1131:                }
1132:                return false;
1133:            }
1134:
1135:            private MethodCall getConcreteMethod(Identifier ctx, Value[] args) {
1136:                ReferenceType type = ctx.typeContext;
1137:                ObjectReference object = ctx.instanceContext;
1138:
1139:                if (ctx.super Qualifier != null) {
1140:                    if (!(ctx.typeContext instanceof  ClassType))
1141:                        Assert.error(currentNode, "superUsedOnNonClass", ctx);
1142:                    if (ctx.super Qualifier.length() > 0) {
1143:                        object = getEnclosingObject(ctx.instanceContext,
1144:                                ctx.super Qualifier);
1145:                        Assert.assertNotNull(object, currentNode,
1146:                                "notEnclosingType", ctx);
1147:                    }
1148:                    ClassType cls = (ClassType) object.referenceType();
1149:                    type = cls.super class();
1150:                }
1151:
1152:                if (ctx.typeContext == null) {
1153:                    Assert.error(currentNode, "methodCallOnNull",
1154:                            ctx.identifier);
1155:                }
1156:
1157:                List<Method> methods = getMethodsByName(type, ctx.identifier);
1158:
1159:                //Try outer classes
1160:                ReferenceType origType = type;
1161:                ObjectReference origObject = object;
1162:
1163:                while (methods.size() == 0) {
1164:                    Field outerRef = type.fieldByName("this$0");
1165:                    if (outerRef == null) {
1166:                        //System.out.println("No outerRef.");
1167:                        type = origType;
1168:                        object = origObject;
1169:                        break; //No outer reference
1170:                    }
1171:                    if (loggerValue.isLoggable(Level.FINE)) {
1172:                        loggerValue.fine("STARTED : " + object + ".getValue("
1173:                                + outerRef + ")");
1174:                    }
1175:                    object = (ObjectReference) object.getValue(outerRef);
1176:                    if (loggerValue.isLoggable(Level.FINE)) {
1177:                        loggerValue.fine("FINISHED: getValue(" + outerRef
1178:                                + ") = " + object);
1179:                    }
1180:                    type = object.referenceType();
1181:                    methods = getMethodsByName(type, ctx.identifier);
1182:
1183:                }
1184:
1185:                //Static Imports
1186:                if (ctx.localContext && methods.size() == 0) {
1187:                    for (Iterator i = staticImportsIterator(ctx.identifier); i
1188:                            .hasNext();) {
1189:                        String typeName = (String) i.next();
1190:                        try {
1191:                            ReferenceType importedType = resolveType(typeName);
1192:                            methods = getMethodsByName(importedType,
1193:                                    ctx.identifier);
1194:                            if (methods.size() > 0) {
1195:                                type = importedType;
1196:                                object = null;
1197:                                break;
1198:                            }
1199:                        } catch (Exception e) {
1200:                            // no such method
1201:                            continue;
1202:                        }
1203:                    }
1204:                }
1205:
1206:                List<MethodCall> possibleMethods = new ArrayList<MethodCall>();
1207:
1208:                for (Iterator<Method> i = methods.iterator(); i.hasNext();) {
1209:                    Method method = i.next();
1210:                    if (!isAccessible(method))
1211:                        continue;
1212:
1213:                    List argTypes = null;
1214:                    try {
1215:                        argTypes = method.argumentTypes();
1216:                    } catch (ClassNotLoadedException e) {
1217:                        // TODO: load class
1218:                        continue;
1219:                    } catch (ObjectCollectedException ocex) {
1220:                        continue;
1221:                    }
1222:
1223:                    // TODO: probably incomplete handling of an implicit constructor of a nested type
1224:                    if (args.length == 0 && "<init>".equals(ctx.identifier)
1225:                            && argTypes.size() == 1) {
1226:                        if (frame.this Object() != null
1227:                                && argTypes.get(0).equals(
1228:                                        frame.location().declaringType())) {
1229:                            args = new Value[] { frame.this Object() };
1230:                        }
1231:                    }
1232:
1233:                    List<Value> newArgs = prepareArguments(args, argTypes);
1234:                    if (newArgs == null)
1235:                        continue;
1236:                    possibleMethods.add(new MethodCall(type, object, method,
1237:                            newArgs));
1238:                }
1239:                Assert.assertNonEmpty(possibleMethods, currentNode,
1240:                        "noSuchMethod", ctx);
1241:                MethodCall call = mostSpecific(possibleMethods, args);
1242:                Assert.assertNotNull(call, currentNode, "ambigousMethod", ctx);
1243:                call = findConcrete(call);
1244:                return call;
1245:            }
1246:
1247:            private static List<Method> getMethodsByName(ReferenceType type,
1248:                    String name) {
1249:                if (type instanceof  ArrayType) { // There are no methods by JDI definition ?!?
1250:                    type = type.classObject().referenceType();
1251:                    if ("toString".equals(name)) { // NOI18N
1252:                        // We have to get the super class' toString() method for some strange reason...
1253:                        type = ((ClassType) type).super class();
1254:                    }
1255:                }
1256:                List<Method> methods = type.methodsByName(name);
1257:                return methods;
1258:            }
1259:
1260:            private MethodCall mostSpecific(List<MethodCall> possibleMethods,
1261:                    Value[] args) {
1262:                if (possibleMethods.size() == 0)
1263:                    return null;
1264:                if (possibleMethods.size() == 1)
1265:                    return possibleMethods.get(0);
1266:
1267:                MethodCall mostSpecific = null;
1268:                int conversions = Integer.MAX_VALUE;
1269:                for (Iterator<MethodCall> i = possibleMethods.iterator(); i
1270:                        .hasNext();) {
1271:                    MethodCall methodCall = i.next();
1272:                    List methodArguments = null;
1273:                    try {
1274:                        methodArguments = methodCall.method.argumentTypes();
1275:                    } catch (ClassNotLoadedException e) {
1276:                        continue;
1277:                    } catch (ObjectCollectedException ocex) {
1278:                        continue;
1279:                    }
1280:                    int cc = conversionsCount(methodArguments, args);
1281:                    if (cc == 0)
1282:                        return methodCall;
1283:                    if (cc == conversions) {
1284:                        return null;
1285:                    }
1286:                    if (cc < conversions) {
1287:                        conversions = cc;
1288:                        mostSpecific = methodCall;
1289:                    }
1290:                }
1291:                return mostSpecific;
1292:            }
1293:
1294:            private int conversionsCount(List argumentTypes, Value[] args) {
1295:                int idx = 0;
1296:                int cc = 0;
1297:                for (Iterator i = argumentTypes.iterator(); i.hasNext(); idx++) {
1298:                    Type argType = (Type) i.next();
1299:                    if (args[idx] == null)
1300:                        continue;
1301:                    if (representSameType(argType, args[idx].type()))
1302:                        continue;
1303:                    cc++;
1304:                }
1305:                return cc;
1306:            }
1307:
1308:            private boolean representSameType(Type t1, Type t2) {
1309:                String t1s = t1.signature();
1310:                String t2s = t2.signature();
1311:
1312:                if (t1s.equals(t2s))
1313:                    return true;
1314:                if (t1s.length() == 1 && t2s.length() == 1 || t1s.length() > 1
1315:                        && t2s.length() > 1)
1316:                    return false;
1317:
1318:                String primitiveType = t1s.length() == 1 ? t1s : t2s;
1319:                String classType = t1s.length() > 1 ? t1s : t2s;
1320:
1321:                return wrapperSignature(primitiveType.charAt(0)).equals(
1322:                        classType);
1323:            }
1324:
1325:            private MethodCall findConcrete(MethodCall call) {
1326:                if (call.method.isAbstract()) {
1327:                    ReferenceType type = call.instanceContext.referenceType();
1328:                    if (type instanceof  ClassType) {
1329:                        Method m = ((ClassType) type).concreteMethodByName(
1330:                                call.method.name(), call.method.signature());
1331:                        if (m != null) {
1332:                            call.method = m;
1333:                            call.typeContext = type;
1334:                        }
1335:                    }
1336:                }
1337:                return call;
1338:            }
1339:
1340:            private List<Value> prepareArguments(Value[] args, List argTypes) {
1341:
1342:                boolean ellipsis;
1343:                try {
1344:                    ellipsis = argTypes.size() > 0
1345:                            && argTypes.get(argTypes.size() - 1) instanceof  ArrayType
1346:                            && (args.length == 0
1347:                                    || args[args.length - 1] == null || isConvertible(
1348:                                    ((ArrayType) argTypes
1349:                                            .get(argTypes.size() - 1))
1350:                                            .componentType(),
1351:                                    args[args.length - 1]));
1352:                } catch (ClassNotLoadedException e) {
1353:                    // TODO: load the offending class?
1354:                    return null;
1355:                }
1356:                if (ellipsis) {
1357:                    if (args.length < argTypes.size() - 1)
1358:                        return null;
1359:                } else {
1360:                    if (args.length != argTypes.size())
1361:                        return null;
1362:                }
1363:
1364:                List<Value> newArgs = new ArrayList<Value>();
1365:                int idx = 0;
1366:                for (Iterator i = argTypes.iterator(); i.hasNext(); idx++) {
1367:                    Type type = (Type) i.next();
1368:                    if (ellipsis && !i.hasNext())
1369:                        continue;
1370:                    if (!isConvertible(type, args[idx]))
1371:                        return null;
1372:                    newArgs.add(boxUnboxIfNeeded(args[idx], type));
1373:                }
1374:
1375:                if (ellipsis) {
1376:                    // JDI will handle vararg calls, we just need to check argument types
1377:                    ArrayType elipsisType = (ArrayType) argTypes.get(argTypes
1378:                            .size() - 1);
1379:                    if (args.length == argTypes.size() - 1) {
1380:                        // nothing to check
1381:                    } else {
1382:                        Type componentType = null;
1383:                        try {
1384:                            componentType = elipsisType.componentType();
1385:                        } catch (ClassNotLoadedException e) {
1386:                            // TODO: load the offending class
1387:                            return null;
1388:                        }
1389:                        if (args.length == argTypes.size()) {
1390:                            if (args[args.length - 1] != null
1391:                                    && !elipsisType
1392:                                            .equals(args[args.length - 1]
1393:                                                    .type())) {
1394:                                if (!isConvertible(componentType,
1395:                                        args[args.length - 1]))
1396:                                    return null;
1397:                            }
1398:                            newArgs.add(boxUnboxIfNeeded(args[args.length - 1],
1399:                                    componentType));
1400:                        } else if (args.length > argTypes.size()) {
1401:                            for (int i = argTypes.size() - 1; i < args.length; i++) {
1402:                                if (!isConvertible(componentType, args[i]))
1403:                                    return null;
1404:                                newArgs.add(boxUnboxIfNeeded(args[i],
1405:                                        componentType));
1406:                            }
1407:                        }
1408:                    }
1409:                }
1410:
1411:                return newArgs;
1412:            }
1413:
1414:            private Value boxUnboxIfNeeded(Value value, Type type) {
1415:                if (value instanceof  ObjectReference
1416:                        && type instanceof  PrimitiveType) {
1417:                    return unbox((ObjectReference) value, type);
1418:                } else if (value instanceof  PrimitiveValue
1419:                        && type instanceof  ClassType) {
1420:                    return box((PrimitiveValue) value, (ClassType) type);
1421:                } else {
1422:                    return value;
1423:                }
1424:            }
1425:
1426:            /**
1427:             * Wraps the passed primitive value to an object of the given type. The class type of the object must be
1428:             * wider than the primitive value type. For example, it is not possible to wrap a long value to a Short object.
1429:             *
1430:             * @param primitiveValue
1431:             * @param type
1432:             * @return
1433:             */
1434:            private ObjectReference box(PrimitiveValue primitiveValue,
1435:                    ClassType type) {
1436:                try {
1437:                    if (type instanceof  Object) {
1438:                        type = wrapperType((PrimitiveType) primitiveValue
1439:                                .type());
1440:                    }
1441:                    return newInstance(type, new Value[] { primitiveValue });
1442:                } catch (Exception e) {
1443:                    // this should never happen, indicates an internal error
1444:                    throw new RuntimeException(
1445:                            "Unexpected exception while invoking boxing method",
1446:                            e);
1447:                }
1448:            }
1449:
1450:            private ClassType wrapperType(PrimitiveType type)
1451:                    throws IncompatibleThreadStateException {
1452:                char sig = type.signature().charAt(0);
1453:                return (ClassType) resolveType(wrapperClassname(sig));
1454:            }
1455:
1456:            private String wrapperSignature(char primitiveSignature) {
1457:                switch (primitiveSignature) {
1458:                case 'Z':
1459:                    return "Ljava/lang/Boolean;";
1460:                case 'B':
1461:                    return "Ljava/lang/Byte;";
1462:                case 'C':
1463:                    return "Ljava/lang/Character;";
1464:                case 'S':
1465:                    return "Ljava/lang/Short;";
1466:                case 'I':
1467:                    return "Ljava/lang/Integer;";
1468:                case 'J':
1469:                    return "Ljava/lang/Long;";
1470:                case 'F':
1471:                    return "Ljava/lang/Float;";
1472:                case 'D':
1473:                    return "Ljava/lang/Double;";
1474:                }
1475:                throw new RuntimeException(); // never happens
1476:            }
1477:
1478:            private String wrapperClassname(char primitiveSignature) {
1479:                switch (primitiveSignature) {
1480:                case 'Z':
1481:                    return "java.lang.Boolean";
1482:                case 'B':
1483:                    return "java.lang.Byte";
1484:                case 'C':
1485:                    return "java.lang.Character";
1486:                case 'S':
1487:                    return "java.lang.Short";
1488:                case 'I':
1489:                    return "java.lang.Integer";
1490:                case 'J':
1491:                    return "java.lang.Long";
1492:                case 'F':
1493:                    return "java.lang.Float";
1494:                case 'D':
1495:                    return "java.lang.Double";
1496:                }
1497:                throw new RuntimeException(); // never happens
1498:            }
1499:
1500:            private ObjectReference newInstance(ClassType type,
1501:                    Value[] constructorArgs) throws InvocationException,
1502:                    ClassNotLoadedException, IncompatibleThreadStateException,
1503:                    InvalidTypeException {
1504:
1505:                MethodCall method = getConcreteMethod(new Identifier(type,
1506:                        "<init>"), constructorArgs);
1507:                try {
1508:                    return type
1509:                            .newInstance(frameThread, method.method,
1510:                                    method.args,
1511:                                    ObjectReference.INVOKE_SINGLE_THREADED);
1512:                } finally {
1513:                    frame = frameThread.frame(frameIndex);
1514:                }
1515:            }
1516:
1517:            private PrimitiveValue unbox(ObjectReference val, Type type) {
1518:
1519:                if (type instanceof  BooleanType)
1520:                    return invokeUnboxingMethod(val, "booleanValue");
1521:                if (type instanceof  ByteType)
1522:                    return invokeUnboxingMethod(val, "byteValue");
1523:                if (type instanceof  CharType)
1524:                    return invokeUnboxingMethod(val, "charValue");
1525:                if (type instanceof  ShortType)
1526:                    return invokeUnboxingMethod(val, "shortValue");
1527:                if (type instanceof  IntegerType)
1528:                    return invokeUnboxingMethod(val, "intValue");
1529:                if (type instanceof  LongType)
1530:                    return invokeUnboxingMethod(val, "longValue");
1531:                if (type instanceof  FloatType)
1532:                    return invokeUnboxingMethod(val, "floatValue");
1533:                if (type instanceof  DoubleType)
1534:                    return invokeUnboxingMethod(val, "doubleValue");
1535:                throw new RuntimeException("Invalid type while unboxing: "
1536:                        + type.signature()); // never happens
1537:            }
1538:
1539:            private PrimitiveValue invokeUnboxingMethod(
1540:                    ObjectReference reference, String methodName) {
1541:                Method toCall = (Method) reference.referenceType()
1542:                        .methodsByName(methodName).get(0);
1543:                try {
1544:                    if (verbose)
1545:                        throw new UnsupportedOperationException(NbBundle
1546:                                .getMessage(Evaluator.class,
1547:                                        "CTL_UnsupportedOperationException"));
1548:                    if (!evaluationContext.canInvokeMethods()) {
1549:                        throw new UnsupportedOperationException();
1550:                    }
1551:                    evaluationContext.methodToBeInvoked();
1552:                    if (loggerMethod.isLoggable(Level.FINE)) {
1553:                        loggerMethod.fine("STARTED : " + reference + "."
1554:                                + toCall + " () in thread " + frameThread);
1555:                    }
1556:                    return (PrimitiveValue) reference.invokeMethod(frameThread,
1557:                            toCall, new ArrayList<Value>(0),
1558:                            ObjectReference.INVOKE_SINGLE_THREADED);
1559:                } catch (UnsupportedOperationException uoex) {
1560:                    evaluationContext.setCanInvokeMethods(false);
1561:                    // this can happen on VMs that can not invoke methods...
1562:                    throw new RuntimeException(
1563:                            "Unexpected exception while invoking unboxing method",
1564:                            uoex);
1565:                } catch (Exception e) {
1566:                    // this should never happen, indicates an internal error
1567:                    throw new RuntimeException(
1568:                            "Unexpected exception while invoking unboxing method",
1569:                            e);
1570:                } finally {
1571:                    if (loggerMethod.isLoggable(Level.FINE)) {
1572:                        loggerMethod.fine("FINISHED: " + reference + "."
1573:                                + toCall + " () in thread " + frameThread);
1574:                    }
1575:                    try {
1576:                        evaluationContext.methodInvokeDone();
1577:                    } catch (IncompatibleThreadStateException itsex) {
1578:                        InvalidExpressionException ieex = new InvalidExpressionException(
1579:                                itsex);
1580:                        ieex.initCause(itsex);
1581:                        throw new IllegalStateException(ieex);
1582:                    }
1583:                    try {
1584:                        frame = frameThread.frame(frameIndex);
1585:                    } catch (IncompatibleThreadStateException e) {
1586:                        throw new RuntimeException(
1587:                                "Unexpected exception while invoking unboxing method",
1588:                                e);
1589:                    }
1590:                }
1591:            }
1592:
1593:            private static final String[] typeSignaturesSorted = {
1594:                    "Ljava/lang/Byte;", "B", "Ljava/lang/Character;", "C",
1595:                    "Ljava/lang/Short;", "S", "Ljava/lang/Integer;", "I",
1596:                    "Ljava/lang/Long;", "J", "Ljava/lang/Float;", "F",
1597:                    "Ljava/lang/Double;", "D" };
1598:
1599:            /**
1600:             * int      short
1601:             * double   float
1602:             * int      Integer
1603:             * Integer  int
1604:             * Runnable Thread
1605:             * Object   Socket
1606:             * <OREF>   null
1607:             *
1608:             * @param wideType
1609:             * @param value
1610:             */
1611:            private boolean isConvertible(Type wideType, Value value) {
1612:
1613:                if (value == null)
1614:                    return wideType instanceof  ReferenceType;
1615:
1616:                String narrow = value.type().signature();
1617:                String wide = wideType.signature();
1618:                if (wide.equals(narrow))
1619:                    return true;
1620:
1621:                if (wide.length() == 1) {
1622:                    if (wide.equals("Z"))
1623:                        return narrow.equals("Ljava/lang/Boolean;");
1624:                    for (int i = 0; i < typeSignaturesSorted.length; i++) {
1625:                        if (narrow.equals(typeSignaturesSorted[i]))
1626:                            return true;
1627:                        if (wide.equals(typeSignaturesSorted[i]))
1628:                            return false;
1629:                    }
1630:                    return false;
1631:                }
1632:
1633:                if (wide.equals("Ljava/lang/Object;"))
1634:                    return true;
1635:
1636:                if (narrow.length() == 1) {
1637:                    if (narrow.equals("Z"))
1638:                        return wide.equals("Ljava/lang/Boolean;");
1639:                    for (int i = 0; i < typeSignaturesSorted.length; i++) {
1640:                        if (narrow.equals(typeSignaturesSorted[i])) {
1641:                            for (int j = i - 1; j < typeSignaturesSorted.length; j++) {
1642:                                if (wide.equals(typeSignaturesSorted[j]))
1643:                                    return true;
1644:                            }
1645:                            return false;
1646:                        }
1647:                    }
1648:                }
1649:
1650:                return instanceOf(value.type(), wideType);
1651:            }
1652:
1653:            private Object visitPrimarySuffix(SimpleNode node, Object data) {
1654:                Token token = (Token) node.getAttribute("token");
1655:                if (token == null) {
1656:                    // AllocationExpression() | Arguments() | ReferenceTypeList()
1657:                    return node.jjtGetChild(0).jjtAccept(this , data);
1658:                }
1659:                switch (token.kind) {
1660:                case JavaParserConstants.IDENTIFIER:
1661:                    data = resolveVariable(data); // data may be an Identifier, object.field.anotherfield
1662:                    Assert.assertAssignable(data, ObjectReference.class, node,
1663:                            "identifierNotAReference", data);
1664:                    return new Identifier(false, (ObjectReference) data,
1665:                            token.image);
1666:
1667:                case JavaParserConstants.LBRACKET: {
1668:                    data = resolveVariable(data);
1669:                    Assert.assertAssignable(data, ArrayReference.class, node,
1670:                            "notarray", data, token);
1671:                    Object index = node.jjtGetChild(0).jjtAccept(this , data);
1672:                    Assert.assertAssignable(index, PrimitiveValue.class, node,
1673:                            "arrayIndexNAN", data, index);
1674:                    Assert.assertNotAssignable(index, BooleanValue.class, node,
1675:                            "arrayIndexNAN", data, index);
1676:                    int idx = ((PrimitiveValue) index).intValue();
1677:                    ArrayReference array = (ArrayReference) data;
1678:                    Assert.assertLess(idx, array.length(), node,
1679:                            "arrayIndexOutOfBounds", array, new Integer(idx));
1680:                    return array.getValue(idx);
1681:                }
1682:
1683:                case JavaParserConstants.THIS:
1684:                case JavaParserConstants.SUPER: {
1685:                    Identifier ctx = (Identifier) data;
1686:                    if (!vm.canGetSyntheticAttribute())
1687:                        Assert.error(node, "unknownType", ctx.identifier);
1688:
1689:                    ObjectReference enclosingObject = getEnclosingObject(frame
1690:                            .this Object(), ctx.identifier);
1691:                    Assert.assertNotNull(enclosingObject, node, "unknownType",
1692:                            ctx.identifier);
1693:                    return enclosingObject;
1694:                }
1695:                }
1696:                return Assert.error(node, "internalError");
1697:            }
1698:
1699:            private ObjectReference getEnclosingObject(ObjectReference obj,
1700:                    String typeQualifier) {
1701:                boolean done;
1702:                do {
1703:                    done = true;
1704:                    List fields = obj.referenceType().allFields();
1705:                    for (Iterator j = fields.iterator(); j.hasNext();) {
1706:                        Field field = (Field) j.next();
1707:                        if (field.isSynthetic()
1708:                                && field.name().startsWith("this$")) {
1709:                            if (loggerValue.isLoggable(Level.FINE)) {
1710:                                loggerValue.fine("STARTED : " + obj
1711:                                        + ".getValue(" + field + ")");
1712:                            }
1713:                            obj = (ObjectReference) obj.getValue(field);
1714:                            if (loggerValue.isLoggable(Level.FINE)) {
1715:                                loggerValue.fine("FINISHED: getValue(" + field
1716:                                        + ") = " + obj);
1717:                            }
1718:                            ClassType type = (ClassType) obj.referenceType();
1719:                            if (type.name().endsWith(typeQualifier)) {
1720:                                return obj;
1721:                            }
1722:                            done = false;
1723:                            break;
1724:                        }
1725:                    }
1726:                } while (!done);
1727:                return null;
1728:            }
1729:
1730:            private Value evaluateVariable(Identifier ctx) {
1731:
1732:                // local variable
1733:                if (ctx.localContext) {
1734:                    try {
1735:                        LocalVariable var = frame
1736:                                .visibleVariableByName(ctx.identifier);
1737:                        if (var != null)
1738:                            return frame.getValue(var);
1739:                    } catch (AbsentInformationException e) {
1740:                        // Try to get arguments
1741:                        try {
1742:                            org.netbeans.api.debugger.jpda.LocalVariable[] lvs;
1743:                            lvs = new CallStackFrameImpl(frame, 0,
1744:                                    evaluationContext.getDebugger())
1745:                                    .getMethodArguments();
1746:                            if (lvs != null) {
1747:                                for (org.netbeans.api.debugger.jpda.LocalVariable lv : lvs) {
1748:                                    if (ctx.identifier.equals(lv.getName())) {
1749:                                        return ((JDIVariable) lv).getJDIValue();
1750:                                    }
1751:                                }
1752:                            }
1753:                        } catch (NativeMethodException nmex) {
1754:                            // ignore - no arguments available
1755:                        }
1756:                    }
1757:                }
1758:
1759:                // field
1760:                if (ctx.instanceContext != null) {
1761:                    Field field = ctx.typeContext.fieldByName(ctx.identifier);
1762:                    if (field != null) {
1763:                        try {
1764:                            if (loggerValue.isLoggable(Level.FINE)) {
1765:                                loggerValue.fine("STARTED : "
1766:                                        + ctx.instanceContext + ".getValue("
1767:                                        + field + ")");
1768:                            }
1769:                            return ctx.instanceContext.getValue(field);
1770:                        } finally {
1771:                            if (loggerValue.isLoggable(Level.FINE)) {
1772:                                loggerValue.fine("FINISHED : "
1773:                                        + ctx.instanceContext + ".getValue("
1774:                                        + field + ")");
1775:                            }
1776:                        }
1777:                    }
1778:                    if (ctx.instanceContext instanceof  ArrayReference) {
1779:                        if (ctx.identifier.equals("length")) {
1780:                            return vm
1781:                                    .mirrorOf(((ArrayReference) ctx.instanceContext)
1782:                                            .length());
1783:                        }
1784:                    }
1785:                }
1786:
1787:                // field from static context
1788:                if (ctx.typeContext != null) {
1789:                    Field field = ctx.typeContext.fieldByName(ctx.identifier);
1790:                    try {
1791:                        if (field != null) {
1792:                            try {
1793:                                if (loggerValue.isLoggable(Level.FINE)) {
1794:                                    loggerValue.fine("STARTED : "
1795:                                            + ctx.typeContext + ".getValue("
1796:                                            + field + ")");
1797:                                }
1798:                                return ctx.typeContext.getValue(field);
1799:                            } finally {
1800:                                if (loggerValue.isLoggable(Level.FINE)) {
1801:                                    loggerValue.fine("FINISHED : "
1802:                                            + ctx.typeContext + ".getValue("
1803:                                            + field + ")");
1804:                                }
1805:                            }
1806:                        }
1807:                    } catch (IllegalArgumentException e) {
1808:                        Assert.error(currentNode,
1809:                                "accessInstanceVariableFromStaticContext", ctx);
1810:                    }
1811:                }
1812:
1813:                // local variable accessed from innerclass
1814:                if (ctx.instanceContext != null) {
1815:                    Field field = ctx.typeContext.fieldByName("val$"
1816:                            + ctx.identifier);
1817:                    if (field != null) {
1818:                        try {
1819:                            if (loggerValue.isLoggable(Level.FINE)) {
1820:                                loggerValue.fine("STARTED : "
1821:                                        + ctx.instanceContext + ".getValue("
1822:                                        + field + ")");
1823:                            }
1824:                            return ctx.instanceContext.getValue(field);
1825:                        } finally {
1826:                            if (loggerValue.isLoggable(Level.FINE)) {
1827:                                loggerValue.fine("FINISHED: "
1828:                                        + ctx.instanceContext + ".getValue("
1829:                                        + field + ")");
1830:                            }
1831:                        }
1832:                    }
1833:                }
1834:
1835:                // outer field accessed from innerclass
1836:                if (ctx.instanceContext != null) {
1837:                    Field helpField = ctx.typeContext.fieldByName("this$0");
1838:                    if (helpField != null) {
1839:                        if (loggerValue.isLoggable(Level.FINE)) {
1840:                            loggerValue.fine("STARTED : " + ctx.instanceContext
1841:                                    + ".getValue(" + helpField + ")");
1842:                        }
1843:                        ObjectReference or = (ObjectReference) ctx.instanceContext
1844:                                .getValue(helpField);
1845:                        if (loggerValue.isLoggable(Level.FINE)) {
1846:                            loggerValue.fine("FINISHED: " + ctx.instanceContext
1847:                                    + ".getValue(" + helpField + ") = " + or);
1848:                        }
1849:                        if (or != null) {
1850:                            Field field = or.referenceType().fieldByName(
1851:                                    ctx.identifier);
1852:                            if (field != null) {
1853:                                try {
1854:                                    if (loggerValue.isLoggable(Level.FINE)) {
1855:                                        loggerValue.fine("STARTED : " + or
1856:                                                + ".getValue(" + field + ")");
1857:                                    }
1858:                                    return or.getValue(field);
1859:                                } finally {
1860:                                    if (loggerValue.isLoggable(Level.FINE)) {
1861:                                        loggerValue.fine("FINISHED: " + or
1862:                                                + ".getValue(" + field + ")");
1863:                                    }
1864:                                }
1865:                            }
1866:                        }
1867:                    }
1868:                }
1869:
1870:                // static import
1871:                for (Iterator i = staticImportsIterator(ctx.identifier); i
1872:                        .hasNext();) {
1873:                    String typeName = (String) i.next();
1874:                    try {
1875:                        ReferenceType type = resolveType(typeName);
1876:                        Field field = type.fieldByName(ctx.identifier);
1877:                        if (field != null) {
1878:                            try {
1879:                                if (loggerValue.isLoggable(Level.FINE)) {
1880:                                    loggerValue.fine("STARTED : " + type
1881:                                            + ".getValue(" + field + ")");
1882:                                }
1883:                                return type.getValue(field);
1884:                            } finally {
1885:                                if (loggerValue.isLoggable(Level.FINE)) {
1886:                                    loggerValue.fine("FINISHED: " + type
1887:                                            + ".getValue(" + field + ")");
1888:                                }
1889:                            }
1890:                        }
1891:                    } catch (Exception e) {
1892:                        // no such type or field
1893:                    }
1894:                }
1895:
1896:                // class special variable
1897:                if (expression.classReplaced().equals(ctx.identifier)) {
1898:                    ReferenceType refType = frame.location().declaringType();
1899:                    JPDAClassType classType = evaluationContext.getDebugger()
1900:                            .getClassType(refType);
1901:                    return ((JDIVariable) classType.classObject())
1902:                            .getJDIValue();
1903:                }
1904:
1905:                // return special variable
1906:                if (expression.returnReplaced().equals(ctx.identifier)) {
1907:                    ThreadReference tr = frame.thread();
1908:                    JPDAThreadImpl thread = (JPDAThreadImpl) evaluationContext
1909:                            .getDebugger().getThread(tr);
1910:                    JDIVariable returnVar = (JDIVariable) thread
1911:                            .getReturnVariable();
1912:                    if (returnVar != null) {
1913:                        return returnVar.getJDIValue();
1914:                    } else {
1915:                        return null;
1916:                    }
1917:                }
1918:
1919:                return (Value) Assert
1920:                        .error(currentNode, "unknownVariable", ctx);
1921:            }
1922:
1923:            private Iterator<String> staticImportsIterator(String identifier) {
1924:                return iterator(evaluationContext.getStaticImports(),
1925:                        identifier);
1926:            }
1927:
1928:            private Iterator<String> iterator(List<String> imports,
1929:                    String identifier) {
1930:                List<String> filteredList = new ArrayList<String>();
1931:                for (Iterator<String> i = imports.iterator(); i.hasNext();) {
1932:                    String statement = i.next();
1933:                    int idx = statement.lastIndexOf('.');
1934:                    String qualifier = statement.substring(idx + 1);
1935:                    if (qualifier.equals("*") || qualifier.equals(identifier)) {
1936:                        filteredList.add(statement.substring(0, idx));
1937:                    }
1938:                }
1939:                return filteredList.iterator();
1940:            }
1941:
1942:            private Value resolveVariable(Object data) {
1943:                if (data == null || data instanceof  Value)
1944:                    return (Value) data;
1945:
1946:                Identifier name = (Identifier) data;
1947:                return evaluateVariable(name);
1948:            }
1949:
1950:            private Object visitPrimaryExpression(SimpleNode node, Object data) {
1951:
1952:                int n = node.jjtGetNumChildren();
1953:
1954:                Object value = node.jjtGetChild(0).jjtAccept(this , data);
1955:                for (int i = 1; i < n; i++) {
1956:                    value = node.jjtGetChild(i).jjtAccept(this , value);
1957:                }
1958:
1959:                if (value instanceof  Identifier) {
1960:                    Identifier ctx = (Identifier) value;
1961:                    return evaluateVariable(ctx);
1962:                }
1963:
1964:                return value;
1965:            }
1966:
1967:            private Object visitExpression(SimpleNode node, Object data) {
1968:                int n = node.jjtGetNumChildren();
1969:                if (n == 1) {
1970:                    // conditionalExpression
1971:                    return node.jjtGetChild(0).jjtAccept(this , data);
1972:                } else {
1973:                    // assignmentoperator conditionalExpression
1974:                    return node.jjtGetChild(2).jjtAccept(this , data);
1975:                }
1976:            }
1977:
1978:            private Object visitLiteral(SimpleNode node, Object data) {
1979:                Token token = (Token) node.getAttribute("token");
1980:                if (token == null)
1981:                    return node.jjtGetChild(0).jjtAccept(this , data);
1982:
1983:                try {
1984:                    switch (token.kind) {
1985:
1986:                    case JavaParser.INTEGER_LITERAL:
1987:                        // XXX might be simpler to use Long.decode()
1988:                        String name = token.image.toLowerCase();
1989:                        boolean isLong = name.endsWith("l");
1990:                        long value;
1991:
1992:                        if (isLong) {
1993:                            name = name.substring(0, name.length() - 1);
1994:                        }
1995:
1996:                        if (name.startsWith("0x")) {
1997:                            value = Long.parseLong(name.substring(2), 16);
1998:                        } else if (name.length() > 1 && name.charAt(0) == '0') {
1999:                            value = Long.parseLong(name.substring(1), 8);
2000:                        } else {
2001:                            value = Long.parseLong(name);
2002:                        }
2003:
2004:                        if (isLong) {
2005:                            return vm.mirrorOf(value);
2006:                        } else {
2007:                            if (value > Integer.MAX_VALUE
2008:                                    || value < Integer.MIN_VALUE) {
2009:                                Assert
2010:                                        .error(node, "integerLiteralTooBig",
2011:                                                name);
2012:                            } else {
2013:                                return vm.mirrorOf((int) value);
2014:                            }
2015:                        }
2016:
2017:                    case JavaParser.FLOATING_POINT_LITERAL:
2018:                        char spec = token.image
2019:                                .charAt(token.image.length() - 1);
2020:                        if (spec == 'f' || spec == 'F') {
2021:                            return vm.mirrorOf(Float.parseFloat(token.image));
2022:                        } else {
2023:                            return vm.mirrorOf(Double.parseDouble(token.image));
2024:                        }
2025:
2026:                    case JavaParser.STRING_LITERAL:
2027:                        return vm.mirrorOf(resolveString(token.image.substring(
2028:                                1, token.image.length() - 1)));
2029:
2030:                    case JavaParser.CHARACTER_LITERAL:
2031:                        return vm.mirrorOf(resolveString(
2032:                                token.image.substring(1,
2033:                                        token.image.length() - 1)).charAt(0));
2034:
2035:                    default:
2036:                        return Assert.error(node, "unknownLiteralType",
2037:                                token.image);
2038:                    }
2039:                } catch (NumberFormatException e) {
2040:                    return Assert.error(node, "badFormatOfIntegerLiteral",
2041:                            token.image);
2042:                }
2043:            }
2044:
2045:            private String resolveString(String input) {
2046:                String result = "";
2047:                int index = 0;
2048:                while (index < input.length()) {
2049:                    if (input.charAt(index) != '\\')
2050:                        result = result + input.charAt(index);
2051:                    else { // resolve an escape sequence
2052:                        index++;
2053:                        char c;
2054:                        switch (input.charAt(index)) {
2055:                        case 'b':
2056:                            c = '\b';
2057:                            break;
2058:                        case 't':
2059:                            c = '\t';
2060:                            break;
2061:                        case 'n':
2062:                            c = '\n';
2063:                            break;
2064:                        case 'f':
2065:                            c = '\f';
2066:                            break;
2067:                        case 'r':
2068:                            c = '\r';
2069:                            break;
2070:                        case '\"':
2071:                            c = '\"';
2072:                            break;
2073:                        case '\'':
2074:                            c = '\'';
2075:                            break;
2076:                        case '\\':
2077:                            c = '\\';
2078:                            break;
2079:
2080:                        default:
2081:                            // resolve octal value
2082:                            c = 0;
2083:                            while ((index < input.length())
2084:                                    && (input.charAt(index) >= '0')
2085:                                    && (input.charAt(index) <= '7')
2086:                                    && (c * 8 + input.charAt(index) - '0' < 256)) {
2087:                                c = (char) (c * 8 + (input.charAt(index) - '0'));
2088:                                index++;
2089:                            } // while
2090:                            index--;
2091:                        } // switch
2092:                        result = result + c;
2093:                    } // else
2094:                    index++;
2095:                } // while
2096:                return result;
2097:            }
2098:
2099:            private Object visitBinaryExpression(SimpleNode node, Object data) {
2100:                Object[] operators = node.getAttributes("operator");
2101:                int n = node.jjtGetNumChildren();
2102:
2103:                Value value = (Value) node.jjtGetChild(0).jjtAccept(this , data);
2104:                for (int i = 1; i < n; i++) {
2105:                    Value next = (Value) node.jjtGetChild(i).jjtAccept(this ,
2106:                            data);
2107:                    try {
2108:                        value = this .operators.evaluate(value,
2109:                                (Token) operators[i - 1], next);
2110:                    } catch (IllegalArgumentException e) {
2111:                        return Assert.error(node, "evaluateError", value,
2112:                                ((Token) operators[i - 1]).image, next);
2113:                    }
2114:                }
2115:                return value;
2116:            }
2117:
2118:            public static Value invokeVirtual(ObjectReference objectReference,
2119:                    Method method, ThreadReference evaluationThread,
2120:                    List<Value> args) throws InvalidExpressionException {
2121:
2122:                if (verbose)
2123:                    throw new UnsupportedOperationException(NbBundle
2124:                            .getMessage(Evaluator.class,
2125:                                    "CTL_UnsupportedOperationException"));
2126:                try {
2127:                    if (loggerMethod.isLoggable(Level.FINE)) {
2128:                        loggerMethod.fine("STARTED : " + objectReference + "."
2129:                                + method + " (" + args + ") in thread "
2130:                                + evaluationThread);
2131:                    }
2132:                    Value value = objectReference.invokeMethod(
2133:                            evaluationThread, method, args,
2134:                            ObjectReference.INVOKE_SINGLE_THREADED);
2135:                    if (loggerMethod.isLoggable(Level.FINE)) {
2136:                        loggerMethod.fine("   return = " + value);
2137:                    }
2138:                    return value;
2139:                } catch (InvalidTypeException itex) {
2140:                    throw new InvalidExpressionException(itex);
2141:                } catch (ClassNotLoadedException cnlex) {
2142:                    throw new InvalidExpressionException(cnlex);
2143:                } catch (IncompatibleThreadStateException itsex) {
2144:                    InvalidExpressionException ieex = new InvalidExpressionException(
2145:                            itsex);
2146:                    ieex.initCause(itsex);
2147:                    throw ieex;
2148:                } catch (InvocationException iex) {
2149:                    InvalidExpressionException ieex = new InvalidExpressionException(
2150:                            iex);
2151:                    ieex.initCause(iex);
2152:                    throw ieex;
2153:                } catch (UnsupportedOperationException uoex) {
2154:                    InvalidExpressionException ieex = new InvalidExpressionException(
2155:                            uoex);
2156:                    ieex.initCause(uoex);
2157:                    throw ieex;
2158:                } catch (ObjectCollectedException ocex) {
2159:                    throw new InvalidExpressionException(NbBundle.getMessage(
2160:                            Evaluator.class, "CTL_EvalError_collected"));
2161:                } finally {
2162:                    if (loggerMethod.isLoggable(Level.FINE)) {
2163:                        loggerMethod.fine("FINISHED: " + objectReference + "."
2164:                                + method + " (" + args + ") in thread "
2165:                                + evaluationThread);
2166:                    }
2167:                }
2168:            }
2169:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.