Source Code Cross Referenced for LValue.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » example » debug » 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 » 6.0 JDK Modules com.sun » tools » com.sun.tools.example.debug.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1998-2003 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.tools.example.debug.expr;
0027:
0028:        import com.sun.jdi.*;
0029:        import java.util.*;
0030:
0031:        abstract class LValue {
0032:
0033:            // The JDI Value object for this LValue.  Once we have this Value,
0034:            // we have to remember it since after we return the LValue object
0035:            // to the ExpressionParser, it might decide that it needs 
0036:            // the 'toString' value for the LValue in which case it will
0037:            // call getMassagedValue to get this toString value.  At that
0038:            // point, we don't want to call JDI a 2nd time to get the Value
0039:            // for the LValue.  This is especially wrong when the LValue
0040:            // represents a member function.  We would end up calling it
0041:            // a 2nd time.
0042:            //
0043:            // Unfortunately, there are several levels of calls to
0044:            // get/set values in this file.  To minimize confusion,
0045:            // jdiValue is set/tested at the lowest level - right
0046:            // next to the actual calls to JDI methods to get/set the
0047:            // value in the debuggee.  
0048:            protected Value jdiValue;
0049:
0050:            abstract Value getValue() throws InvocationException,
0051:                    IncompatibleThreadStateException, InvalidTypeException,
0052:                    ClassNotLoadedException, ParseException;
0053:
0054:            abstract void setValue0(Value value) throws ParseException,
0055:                    InvalidTypeException, ClassNotLoadedException;
0056:
0057:            abstract void invokeWith(List<Value> arguments)
0058:                    throws ParseException;
0059:
0060:            void setValue(Value value) throws ParseException {
0061:                try {
0062:                    setValue0(value);
0063:                } catch (InvalidTypeException exc) {
0064:                    throw new ParseException(
0065:                            "Attempt to set value of incorrect type" + exc);
0066:                } catch (ClassNotLoadedException exc) {
0067:                    throw new ParseException("Attempt to set value before "
0068:                            + exc.className() + " was loaded" + exc);
0069:                }
0070:            }
0071:
0072:            void setValue(LValue lval) throws ParseException {
0073:                setValue(lval.interiorGetValue());
0074:            }
0075:
0076:            LValue memberLValue(ExpressionParser.GetFrame frameGetter,
0077:                    String fieldName) throws ParseException {
0078:                try {
0079:                    return memberLValue(fieldName, frameGetter.get().thread());
0080:                } catch (IncompatibleThreadStateException exc) {
0081:                    throw new ParseException("Thread not suspended");
0082:                }
0083:            }
0084:
0085:            LValue memberLValue(String fieldName, ThreadReference thread)
0086:                    throws ParseException {
0087:
0088:                Value val = interiorGetValue();
0089:                if ((val instanceof  ArrayReference)
0090:                        && "length".equals(fieldName)) {
0091:                    return new LValueArrayLength((ArrayReference) val);
0092:                }
0093:                return new LValueInstanceMember(val, fieldName, thread);
0094:            }
0095:
0096:            // Return the Value for this LValue that would be used to concatenate
0097:            // to a String.  IE, if it is an Object, call toString in the debuggee.
0098:            Value getMassagedValue(ExpressionParser.GetFrame frameGetter)
0099:                    throws ParseException {
0100:                Value vv = interiorGetValue();
0101:
0102:                // If vv is an ObjectReference, then we have to
0103:                // do the implicit call to toString().
0104:                if (vv instanceof  ObjectReference
0105:                        && !(vv instanceof  StringReference)
0106:                        && !(vv instanceof  ArrayReference)) {
0107:                    StackFrame frame;
0108:                    try {
0109:                        frame = frameGetter.get();
0110:                    } catch (IncompatibleThreadStateException exc) {
0111:                        throw new ParseException("Thread not suspended");
0112:                    }
0113:
0114:                    ThreadReference thread = frame.thread();
0115:                    LValue toStringMember = memberLValue("toString", thread);
0116:                    toStringMember.invokeWith(new ArrayList<Value>());
0117:                    return toStringMember.interiorGetValue();
0118:                }
0119:                return vv;
0120:            }
0121:
0122:            Value interiorGetValue() throws ParseException {
0123:                Value value;
0124:                try {
0125:                    value = getValue();
0126:                } catch (InvocationException e) {
0127:                    throw new ParseException(
0128:                            "Unable to complete expression. Exception "
0129:                                    + e.exception() + " thrown");
0130:                } catch (IncompatibleThreadStateException itse) {
0131:                    throw new ParseException(
0132:                            "Unable to complete expression. Thread "
0133:                                    + "not suspended for method invoke");
0134:                } catch (InvalidTypeException ite) {
0135:                    throw new ParseException(
0136:                            "Unable to complete expression. Method "
0137:                                    + "argument type mismatch");
0138:                } catch (ClassNotLoadedException tnle) {
0139:                    throw new ParseException(
0140:                            "Unable to complete expression. Method "
0141:                                    + "argument type " + tnle.className()
0142:                                    + " not yet loaded");
0143:                }
0144:                return value;
0145:            }
0146:
0147:            LValue arrayElementLValue(LValue lval) throws ParseException {
0148:                Value indexValue = lval.interiorGetValue();
0149:                int index;
0150:                if ((indexValue instanceof  IntegerValue)
0151:                        || (indexValue instanceof  ShortValue)
0152:                        || (indexValue instanceof  ByteValue)
0153:                        || (indexValue instanceof  CharValue)) {
0154:                    index = ((PrimitiveValue) indexValue).intValue();
0155:                } else {
0156:                    throw new ParseException(
0157:                            "Array index must be a integer type");
0158:                }
0159:                return new LValueArrayElement(interiorGetValue(), index);
0160:            }
0161:
0162:            public String toString() {
0163:                try {
0164:                    return interiorGetValue().toString();
0165:                } catch (ParseException e) {
0166:                    return "<Parse Exception>";
0167:                }
0168:            }
0169:
0170:            static final int STATIC = 0;
0171:            static final int INSTANCE = 1;
0172:
0173:            static Field fieldByName(ReferenceType refType, String name,
0174:                    int kind) {
0175:                /*
0176:                 * TO DO: Note that this currently fails to find superclass
0177:                 * or implemented interface fields. This is due to a temporary
0178:                 * limititation of RefType.fieldByName. Once that method is 
0179:                 * fixed, superclass fields will be found.
0180:                 */
0181:                Field field = refType.fieldByName(name);
0182:                if (field != null) {
0183:                    boolean isStatic = field.isStatic();
0184:                    if (((kind == STATIC) && !isStatic)
0185:                            || ((kind == INSTANCE) && isStatic)) {
0186:                        field = null;
0187:                    }
0188:                }
0189:                /***
0190:                 System.err.println("fieldByName: " + refType.name() + " " +
0191:                 name + " " +
0192:                 kind + " " + 
0193:                 (field != null));
0194:                 ***/
0195:                return field;
0196:            }
0197:
0198:            static List methodsByName(ReferenceType refType, String name,
0199:                    int kind) {
0200:                List list = refType.methodsByName(name);
0201:                Iterator iter = list.iterator();
0202:                while (iter.hasNext()) {
0203:                    Method method = (Method) iter.next();
0204:                    boolean isStatic = method.isStatic();
0205:                    if (((kind == STATIC) && !isStatic)
0206:                            || ((kind == INSTANCE) && isStatic)) {
0207:                        iter.remove();
0208:                    }
0209:                }
0210:                return list;
0211:            }
0212:
0213:            static List<String> primitiveTypeNames = new ArrayList<String>();
0214:            static {
0215:                primitiveTypeNames.add("boolean");
0216:                primitiveTypeNames.add("byte");
0217:                primitiveTypeNames.add("char");
0218:                primitiveTypeNames.add("short");
0219:                primitiveTypeNames.add("int");
0220:                primitiveTypeNames.add("long");
0221:                primitiveTypeNames.add("float");
0222:                primitiveTypeNames.add("double");
0223:            }
0224:
0225:            static final int SAME = 0;
0226:            static final int ASSIGNABLE = 1;
0227:            static final int DIFFERENT = 2;
0228:
0229:            /*
0230:             * Return SAME, DIFFERENT or ASSIGNABLE.
0231:             * SAME means each arg type is the same as type of the corr. arg.
0232:             * ASSIGNABLE means that not all the pairs are the same, but
0233:             * for those that aren't, at least the argType is assignable
0234:             * from the type of the argument value.
0235:             * DIFFERENT means that in at least one pair, the
0236:             * argType is not assignable from the type of the argument value.
0237:             * IE, one is an Apple and the other is an Orange.
0238:             */
0239:            static int argumentsMatch(List argTypes, List arguments) {
0240:                if (argTypes.size() != arguments.size()) {
0241:                    return DIFFERENT;
0242:                }
0243:
0244:                Iterator typeIter = argTypes.iterator();
0245:                Iterator valIter = arguments.iterator();
0246:                int result = SAME;
0247:
0248:                // If any pair aren't the same, change the
0249:                // result to ASSIGNABLE.  If any pair aren't
0250:                // assignable, return DIFFERENT
0251:                while (typeIter.hasNext()) {
0252:                    Type argType = (Type) typeIter.next();
0253:                    Value value = (Value) valIter.next();
0254:                    if (value == null) {
0255:                        // Null values can be passed to any non-primitive argument
0256:                        if (primitiveTypeNames.contains(argType.name())) {
0257:                            return DIFFERENT;
0258:                        }
0259:                        // Else, we will assume that a null value
0260:                        // exactly matches an object type.
0261:                    }
0262:                    if (!value.type().equals(argType)) {
0263:                        if (isAssignableTo(value.type(), argType)) {
0264:                            result = ASSIGNABLE;
0265:                        } else {
0266:                            return DIFFERENT;
0267:                        }
0268:                    }
0269:                }
0270:                return result;
0271:            }
0272:
0273:            // These is...AssignableTo methods are based on similar code in the JDI
0274:            // implementations of ClassType, ArrayType, and InterfaceType
0275:
0276:            static boolean isComponentAssignable(Type fromType, Type toType) {
0277:                if (fromType instanceof  PrimitiveType) {
0278:                    // Assignment of primitive arrays requires identical
0279:                    // component types.
0280:                    return fromType.equals(toType);
0281:                }
0282:                if (toType instanceof  PrimitiveType) {
0283:                    return false;
0284:                }
0285:                // Assignment of object arrays requires availability
0286:                // of widening conversion of component types
0287:                return isAssignableTo(fromType, toType);
0288:            }
0289:
0290:            static boolean isArrayAssignableTo(ArrayType fromType, Type toType) {
0291:                if (toType instanceof  ArrayType) {
0292:                    try {
0293:                        Type toComponentType = ((ArrayType) toType)
0294:                                .componentType();
0295:                        return isComponentAssignable(fromType.componentType(),
0296:                                toComponentType);
0297:                    } catch (ClassNotLoadedException e) {
0298:                        // One or both component types has not yet been 
0299:                        // loaded => can't assign
0300:                        return false;
0301:                    }
0302:                }
0303:                if (toType instanceof  InterfaceType) {
0304:                    // Only valid InterfaceType assignee is Cloneable
0305:                    return toType.name().equals("java.lang.Cloneable");
0306:                }
0307:                // Only valid ClassType assignee is Object
0308:                return toType.name().equals("java.lang.Object");
0309:            }
0310:
0311:            static boolean isAssignableTo(Type fromType, Type toType) {
0312:                if (fromType.equals(toType)) {
0313:                    return true;
0314:                }
0315:
0316:                // If one is boolean, so must be the other.
0317:                if (fromType instanceof  BooleanType) {
0318:                    if (toType instanceof  BooleanType) {
0319:                        return true;
0320:                    }
0321:                    return false;
0322:                }
0323:                if (toType instanceof  BooleanType) {
0324:                    return false;
0325:                }
0326:
0327:                // Other primitive types are intermixable only with each other.
0328:                if (fromType instanceof  PrimitiveType) {
0329:                    if (toType instanceof  PrimitiveType) {
0330:                        return true;
0331:                    }
0332:                    return false;
0333:                }
0334:                if (toType instanceof  PrimitiveType) {
0335:                    return false;
0336:                }
0337:
0338:                // neither one is primitive.
0339:                if (fromType instanceof  ArrayType) {
0340:                    return isArrayAssignableTo((ArrayType) fromType, toType);
0341:                }
0342:                List interfaces;
0343:                if (fromType instanceof  ClassType) {
0344:                    ClassType super clazz = ((ClassType) fromType).super class();
0345:                    if ((super clazz != null)
0346:                            && isAssignableTo(super clazz, toType)) {
0347:                        return true;
0348:                    }
0349:                    interfaces = ((ClassType) fromType).interfaces();
0350:                } else {
0351:                    // fromType must be an InterfaceType
0352:                    interfaces = ((InterfaceType) fromType).super interfaces();
0353:                }
0354:                Iterator iter = interfaces.iterator();
0355:                while (iter.hasNext()) {
0356:                    InterfaceType interfaze = (InterfaceType) iter.next();
0357:                    if (isAssignableTo(interfaze, toType)) {
0358:                        return true;
0359:                    }
0360:                }
0361:                return false;
0362:            }
0363:
0364:            static Method resolveOverload(List overloads, List arguments)
0365:                    throws ParseException {
0366:
0367:                // If there is only one method to call, we'll just choose
0368:                // that without looking at the args.  If they aren't right
0369:                // the invoke will return a better error message than we
0370:                // could generate here.
0371:                if (overloads.size() == 1) {
0372:                    return (Method) overloads.get(0);
0373:                }
0374:
0375:                // Resolving overloads is beyond the scope of this exercise.
0376:                // So, we will look for a method that matches exactly the
0377:                // types of the arguments.  If we can't find one, then
0378:                // if there is exactly one method whose param types are assignable
0379:                // from the arg types, we will use that.  Otherwise,
0380:                // it is an error.  We won't guess which of multiple possible
0381:                // methods to call. And, since casts aren't implemented,
0382:                // the user can't use them to pick a particular overload to call.
0383:                // IE, the user is out of luck in this case.
0384:                Iterator iter = overloads.iterator();
0385:                Method retVal = null;
0386:                int assignableCount = 0;
0387:                while (iter.hasNext()) {
0388:                    Method mm = (Method) iter.next();
0389:                    List argTypes;
0390:                    try {
0391:                        argTypes = mm.argumentTypes();
0392:                    } catch (ClassNotLoadedException ee) {
0393:                        // This probably won't happen for the
0394:                        // method that we are really supposed to
0395:                        // call.
0396:                        continue;
0397:                    }
0398:                    int compare = argumentsMatch(argTypes, arguments);
0399:                    if (compare == SAME) {
0400:                        return mm;
0401:                    }
0402:                    if (compare == DIFFERENT) {
0403:                        continue;
0404:                    }
0405:                    // Else, it is assignable.  Remember it.
0406:                    retVal = mm;
0407:                    assignableCount++;
0408:                }
0409:
0410:                // At this point, we didn't find an exact match,
0411:                // but we found one for which the args are assignable.
0412:                // 
0413:                if (retVal != null) {
0414:                    if (assignableCount == 1) {
0415:                        return retVal;
0416:                    }
0417:                    throw new ParseException("Arguments match multiple methods");
0418:                }
0419:                throw new ParseException("Arguments match no method");
0420:            }
0421:
0422:            private static class LValueLocal extends LValue {
0423:                final StackFrame frame;
0424:                final LocalVariable var;
0425:
0426:                LValueLocal(StackFrame frame, LocalVariable var) {
0427:                    this .frame = frame;
0428:                    this .var = var;
0429:                }
0430:
0431:                Value getValue() {
0432:                    if (jdiValue == null) {
0433:                        jdiValue = frame.getValue(var);
0434:                    }
0435:                    return jdiValue;
0436:                }
0437:
0438:                void setValue0(Value val) throws InvalidTypeException,
0439:                        ClassNotLoadedException {
0440:                    frame.setValue(var, val);
0441:                    jdiValue = val;
0442:                }
0443:
0444:                void invokeWith(List<Value> arguments) throws ParseException {
0445:                    throw new ParseException(var.name() + " is not a method");
0446:                }
0447:            }
0448:
0449:            private static class LValueInstanceMember extends LValue {
0450:                final ObjectReference obj;
0451:                final ThreadReference thread;
0452:                final Field matchingField;
0453:                final List overloads;
0454:                Method matchingMethod = null;
0455:                List<Value> methodArguments = null;
0456:
0457:                LValueInstanceMember(Value value, String memberName,
0458:                        ThreadReference thread) throws ParseException {
0459:                    if (!(value instanceof  ObjectReference)) {
0460:                        throw new ParseException(
0461:                                "Cannot access field of primitive type: "
0462:                                        + value);
0463:                    }
0464:                    this .obj = (ObjectReference) value;
0465:                    this .thread = thread;
0466:                    ReferenceType refType = obj.referenceType();
0467:                    /*
0468:                     * Can't tell yet whether this LValue will be accessed as a
0469:                     * field or method, so we keep track of all the possibilities
0470:                     */
0471:                    matchingField = LValue.fieldByName(refType, memberName,
0472:                            LValue.INSTANCE);
0473:                    overloads = LValue.methodsByName(refType, memberName,
0474:                            LValue.INSTANCE);
0475:                    if ((matchingField == null) && overloads.size() == 0) {
0476:                        throw new ParseException(
0477:                                "No instance field or method with the name "
0478:                                        + memberName + " in " + refType.name());
0479:                    }
0480:                }
0481:
0482:                Value getValue() throws InvocationException,
0483:                        InvalidTypeException, ClassNotLoadedException,
0484:                        IncompatibleThreadStateException, ParseException {
0485:                    if (jdiValue != null) {
0486:                        return jdiValue;
0487:                    }
0488:                    if (matchingMethod == null) {
0489:                        if (matchingField == null) {
0490:                            throw new ParseException("No such field in "
0491:                                    + obj.referenceType().name());
0492:                        }
0493:                        return jdiValue = obj.getValue(matchingField);
0494:                    } else {
0495:                        return jdiValue = obj.invokeMethod(thread,
0496:                                matchingMethod, methodArguments, 0);
0497:                    }
0498:                }
0499:
0500:                void setValue0(Value val) throws ParseException,
0501:                        InvalidTypeException, ClassNotLoadedException {
0502:                    if (matchingMethod != null) {
0503:                        throw new ParseException(
0504:                                "Cannot assign to a method invocation");
0505:                    }
0506:                    obj.setValue(matchingField, val);
0507:                    jdiValue = val;
0508:                }
0509:
0510:                void invokeWith(List<Value> arguments) throws ParseException {
0511:                    if (matchingMethod != null) {
0512:                        throw new ParseException(
0513:                                "Invalid consecutive invocations");
0514:                    }
0515:                    methodArguments = arguments;
0516:                    matchingMethod = LValue.resolveOverload(overloads,
0517:                            arguments);
0518:                }
0519:            }
0520:
0521:            private static class LValueStaticMember extends LValue {
0522:                final ReferenceType refType;
0523:                final ThreadReference thread;
0524:                final Field matchingField;
0525:                final List overloads;
0526:                Method matchingMethod = null;
0527:                List<Value> methodArguments = null;
0528:
0529:                LValueStaticMember(ReferenceType refType, String memberName,
0530:                        ThreadReference thread) throws ParseException {
0531:                    this .refType = refType;
0532:                    this .thread = thread;
0533:                    /*
0534:                     * Can't tell yet whether this LValue will be accessed as a
0535:                     * field or method, so we keep track of all the possibilities
0536:                     */
0537:                    matchingField = LValue.fieldByName(refType, memberName,
0538:                            LValue.STATIC);
0539:                    overloads = LValue.methodsByName(refType, memberName,
0540:                            LValue.STATIC);
0541:                    if ((matchingField == null) && overloads.size() == 0) {
0542:                        throw new ParseException(
0543:                                "No static field or method with the name "
0544:                                        + memberName + " in " + refType.name());
0545:                    }
0546:                }
0547:
0548:                Value getValue() throws InvocationException,
0549:                        InvalidTypeException, ClassNotLoadedException,
0550:                        IncompatibleThreadStateException, ParseException {
0551:                    if (jdiValue != null) {
0552:                        return jdiValue;
0553:                    }
0554:                    if (matchingMethod == null) {
0555:                        return jdiValue = refType.getValue(matchingField);
0556:                    } else if (refType instanceof  ClassType) {
0557:                        ClassType clazz = (ClassType) refType;
0558:                        return jdiValue = clazz.invokeMethod(thread,
0559:                                matchingMethod, methodArguments, 0);
0560:                    } else {
0561:                        throw new InvalidTypeException(
0562:                                "Cannot invoke static method on "
0563:                                        + refType.name());
0564:                    }
0565:                }
0566:
0567:                void setValue0(Value val) throws ParseException,
0568:                        InvalidTypeException, ClassNotLoadedException {
0569:                    if (matchingMethod != null) {
0570:                        throw new ParseException(
0571:                                "Cannot assign to a method invocation");
0572:                    }
0573:                    if (!(refType instanceof  ClassType)) {
0574:                        throw new ParseException("Cannot set interface field: "
0575:                                + refType);
0576:                    }
0577:                    ((ClassType) refType).setValue(matchingField, val);
0578:                    jdiValue = val;
0579:                }
0580:
0581:                void invokeWith(List<Value> arguments) throws ParseException {
0582:                    if (matchingMethod != null) {
0583:                        throw new ParseException(
0584:                                "Invalid consecutive invocations");
0585:                    }
0586:                    methodArguments = arguments;
0587:                    matchingMethod = LValue.resolveOverload(overloads,
0588:                            arguments);
0589:                }
0590:            }
0591:
0592:            private static class LValueArrayLength extends LValue {
0593:                /*
0594:                 * Since one can code "int myLen = myArray.length;",
0595:                 * one might expect that these JDI calls would get a Value
0596:                 * object for the length of an array in the debugee:
0597:                 *    Field xxx = ArrayType.fieldByName("length")
0598:                 *    Value lenVal= ArrayReference.getValue(xxx)
0599:                 *
0600:                 * However, this doesn't work because the array length isn't
0601:                 * really stored as a field, and can't be accessed as such
0602:                 * via JDI.  Instead, the arrayRef.length() method has to be
0603:                 * used.
0604:                 */
0605:                final ArrayReference arrayRef;
0606:
0607:                LValueArrayLength(ArrayReference value) {
0608:                    this .arrayRef = value;
0609:                }
0610:
0611:                Value getValue() {
0612:                    if (jdiValue == null) {
0613:                        jdiValue = arrayRef.virtualMachine().mirrorOf(
0614:                                arrayRef.length());
0615:                    }
0616:                    return jdiValue;
0617:                }
0618:
0619:                void setValue0(Value value) throws ParseException {
0620:                    throw new ParseException("Cannot set constant: " + value);
0621:                }
0622:
0623:                void invokeWith(List<Value> arguments) throws ParseException {
0624:                    throw new ParseException("Array element is not a method");
0625:                }
0626:            }
0627:
0628:            private static class LValueArrayElement extends LValue {
0629:                final ArrayReference array;
0630:                final int index;
0631:
0632:                LValueArrayElement(Value value, int index)
0633:                        throws ParseException {
0634:                    if (!(value instanceof  ArrayReference)) {
0635:                        throw new ParseException("Must be array type: " + value);
0636:                    }
0637:                    this .array = (ArrayReference) value;
0638:                    this .index = index;
0639:                }
0640:
0641:                Value getValue() {
0642:                    if (jdiValue == null) {
0643:                        jdiValue = array.getValue(index);
0644:                    }
0645:                    return jdiValue;
0646:                }
0647:
0648:                void setValue0(Value val) throws InvalidTypeException,
0649:                        ClassNotLoadedException {
0650:                    array.setValue(index, val);
0651:                    jdiValue = val;
0652:                }
0653:
0654:                void invokeWith(List<Value> arguments) throws ParseException {
0655:                    throw new ParseException("Array element is not a method");
0656:                }
0657:            }
0658:
0659:            private static class LValueConstant extends LValue {
0660:                final Value value;
0661:
0662:                LValueConstant(Value value) {
0663:                    this .value = value;
0664:                }
0665:
0666:                Value getValue() {
0667:                    if (jdiValue == null) {
0668:                        jdiValue = value;
0669:                    }
0670:                    return jdiValue;
0671:                }
0672:
0673:                void setValue0(Value val) throws ParseException {
0674:                    throw new ParseException("Cannot set constant: " + value);
0675:                }
0676:
0677:                void invokeWith(List<Value> arguments) throws ParseException {
0678:                    throw new ParseException("Constant is not a method");
0679:                }
0680:            }
0681:
0682:            static LValue make(VirtualMachine vm, boolean val) {
0683:                return new LValueConstant(vm.mirrorOf(val));
0684:            }
0685:
0686:            static LValue make(VirtualMachine vm, byte val) {
0687:                return new LValueConstant(vm.mirrorOf(val));
0688:            }
0689:
0690:            static LValue make(VirtualMachine vm, char val) {
0691:                return new LValueConstant(vm.mirrorOf(val));
0692:            }
0693:
0694:            static LValue make(VirtualMachine vm, short val) {
0695:                return new LValueConstant(vm.mirrorOf(val));
0696:            }
0697:
0698:            static LValue make(VirtualMachine vm, int val) {
0699:                return new LValueConstant(vm.mirrorOf(val));
0700:            }
0701:
0702:            static LValue make(VirtualMachine vm, long val) {
0703:                return new LValueConstant(vm.mirrorOf(val));
0704:            }
0705:
0706:            static LValue make(VirtualMachine vm, float val) {
0707:                return new LValueConstant(vm.mirrorOf(val));
0708:            }
0709:
0710:            static LValue make(VirtualMachine vm, double val) {
0711:                return new LValueConstant(vm.mirrorOf(val));
0712:            }
0713:
0714:            static LValue make(VirtualMachine vm, String val)
0715:                    throws ParseException {
0716:                return new LValueConstant(vm.mirrorOf(val));
0717:            }
0718:
0719:            static LValue makeBoolean(VirtualMachine vm, Token token) {
0720:                return make(vm, token.image.charAt(0) == 't');
0721:            }
0722:
0723:            static LValue makeCharacter(VirtualMachine vm, Token token) {
0724:                return make(vm, token.image.charAt(1));
0725:            }
0726:
0727:            static LValue makeFloat(VirtualMachine vm, Token token) {
0728:                return make(vm, Float.valueOf(token.image).floatValue());
0729:            }
0730:
0731:            static LValue makeDouble(VirtualMachine vm, Token token) {
0732:                return make(vm, Double.valueOf(token.image).doubleValue());
0733:            }
0734:
0735:            static LValue makeInteger(VirtualMachine vm, Token token) {
0736:                return make(vm, Integer.parseInt(token.image));
0737:            }
0738:
0739:            static LValue makeShort(VirtualMachine vm, Token token) {
0740:                return make(vm, Short.parseShort(token.image));
0741:            }
0742:
0743:            static LValue makeLong(VirtualMachine vm, Token token) {
0744:                return make(vm, Long.parseLong(token.image));
0745:            }
0746:
0747:            static LValue makeByte(VirtualMachine vm, Token token) {
0748:                return make(vm, Byte.parseByte(token.image));
0749:            }
0750:
0751:            static LValue makeString(VirtualMachine vm, Token token)
0752:                    throws ParseException {
0753:                int len = token.image.length();
0754:                return make(vm, token.image.substring(1, len - 1));
0755:            }
0756:
0757:            static LValue makeNull(VirtualMachine vm, Token token)
0758:                    throws ParseException {
0759:                return new LValueConstant(null);
0760:            }
0761:
0762:            static LValue makeThisObject(VirtualMachine vm,
0763:                    ExpressionParser.GetFrame frameGetter, Token token)
0764:                    throws ParseException {
0765:                if (frameGetter == null) {
0766:                    throw new ParseException("No current thread");
0767:                } else {
0768:                    try {
0769:                        StackFrame frame = frameGetter.get();
0770:                        ObjectReference this Object = frame.this Object();
0771:
0772:                        if (this Object == null) {
0773:                            throw new ParseException(
0774:                                    "No 'this'.  In native or static method");
0775:                        } else {
0776:                            return new LValueConstant(this Object);
0777:                        }
0778:                    } catch (IncompatibleThreadStateException exc) {
0779:                        throw new ParseException("Thread not suspended");
0780:                    }
0781:                }
0782:            }
0783:
0784:            static LValue makeNewObject(VirtualMachine vm,
0785:                    ExpressionParser.GetFrame frameGetter, String className,
0786:                    List<Value> arguments) throws ParseException {
0787:                List classes = vm.classesByName(className);
0788:                if (classes.size() == 0) {
0789:                    throw new ParseException("No class named: " + className);
0790:                }
0791:
0792:                if (classes.size() > 1) {
0793:                    throw new ParseException("More than one class named: "
0794:                            + className);
0795:                }
0796:                ReferenceType refType = (ReferenceType) classes.get(0);
0797:
0798:                if (!(refType instanceof  ClassType)) {
0799:                    throw new ParseException(
0800:                            "Cannot create instance of interface " + className);
0801:                }
0802:
0803:                ClassType classType = (ClassType) refType;
0804:                List<Method> methods = new ArrayList<Method>(classType
0805:                        .methods()); // writable
0806:                Iterator iter = methods.iterator();
0807:                while (iter.hasNext()) {
0808:                    Method method = (Method) iter.next();
0809:                    if (!method.isConstructor()) {
0810:                        iter.remove();
0811:                    }
0812:                }
0813:                Method constructor = LValue.resolveOverload(methods, arguments);
0814:
0815:                ObjectReference newObject;
0816:                try {
0817:                    ThreadReference thread = frameGetter.get().thread();
0818:                    newObject = classType.newInstance(thread, constructor,
0819:                            arguments, 0);
0820:                } catch (InvocationException ie) {
0821:                    throw new ParseException("Exception in " + className
0822:                            + " constructor: "
0823:                            + ie.exception().referenceType().name());
0824:                } catch (IncompatibleThreadStateException exc) {
0825:                    throw new ParseException("Thread not suspended");
0826:                } catch (Exception e) {
0827:                    /*
0828:                     * TO DO: Better error handling
0829:                     */
0830:                    throw new ParseException("Unable to create " + className
0831:                            + " instance");
0832:                }
0833:                return new LValueConstant(newObject);
0834:            }
0835:
0836:            private static LValue nFields(LValue lval, StringTokenizer izer,
0837:                    ThreadReference thread) throws ParseException {
0838:                if (!izer.hasMoreTokens()) {
0839:                    return lval;
0840:                } else {
0841:                    return nFields(lval.memberLValue(izer.nextToken(), thread),
0842:                            izer, thread);
0843:                }
0844:            }
0845:
0846:            static LValue makeName(VirtualMachine vm,
0847:                    ExpressionParser.GetFrame frameGetter, String name)
0848:                    throws ParseException {
0849:                StringTokenizer izer = new StringTokenizer(name, ".");
0850:                String first = izer.nextToken();
0851:                // check local variables
0852:                if (frameGetter != null) {
0853:                    try {
0854:                        StackFrame frame = frameGetter.get();
0855:                        ThreadReference thread = frame.thread();
0856:                        LocalVariable var;
0857:                        try {
0858:                            var = frame.visibleVariableByName(first);
0859:                        } catch (AbsentInformationException e) {
0860:                            var = null;
0861:                        }
0862:                        if (var != null) {
0863:                            return nFields(new LValueLocal(frame, var), izer,
0864:                                    thread);
0865:                        } else {
0866:                            ObjectReference this Object = frame.this Object();
0867:                            if (this Object != null) {
0868:                                // check if it is a field of 'this'
0869:                                LValue this LValue = new LValueConstant(
0870:                                        this Object);
0871:                                LValue fv;
0872:                                try {
0873:                                    fv = this LValue.memberLValue(first, thread);
0874:                                } catch (ParseException exc) {
0875:                                    fv = null;
0876:                                }
0877:                                if (fv != null) {
0878:                                    return nFields(fv, izer, thread);
0879:                                }
0880:                            }
0881:                        }
0882:                        // check for class name
0883:                        while (izer.hasMoreTokens()) {
0884:                            List classes = vm.classesByName(first);
0885:                            if (classes.size() > 0) {
0886:                                if (classes.size() > 1) {
0887:                                    throw new ParseException(
0888:                                            "More than one class named: "
0889:                                                    + first);
0890:                                } else {
0891:                                    ReferenceType refType = (ReferenceType) classes
0892:                                            .get(0);
0893:                                    LValue lval = new LValueStaticMember(
0894:                                            refType, izer.nextToken(), thread);
0895:                                    return nFields(lval, izer, thread);
0896:                                }
0897:                            }
0898:                            first = first + '.' + izer.nextToken();
0899:                        }
0900:                    } catch (IncompatibleThreadStateException exc) {
0901:                        throw new ParseException("Thread not suspended");
0902:                    }
0903:                }
0904:                throw new ParseException("Name unknown: " + name);
0905:            }
0906:
0907:            static String stringValue(LValue lval,
0908:                    ExpressionParser.GetFrame frameGetter)
0909:                    throws ParseException {
0910:                Value val = lval.getMassagedValue(frameGetter);
0911:                if (val == null) {
0912:                    return "null";
0913:                }
0914:                if (val instanceof  StringReference) {
0915:                    return ((StringReference) val).value();
0916:                }
0917:                return val.toString(); // is this correct in all cases?
0918:            }
0919:
0920:            static LValue booleanOperation(VirtualMachine vm, Token token,
0921:                    LValue rightL, LValue leftL) throws ParseException {
0922:                String op = token.image;
0923:                Value right = rightL.interiorGetValue();
0924:                Value left = leftL.interiorGetValue();
0925:                if (!(right instanceof  PrimitiveValue)
0926:                        || !(left instanceof  PrimitiveValue)) {
0927:                    if (op.equals("==")) {
0928:                        return make(vm, right.equals(left));
0929:                    } else if (op.equals("!=")) {
0930:                        return make(vm, !right.equals(left));
0931:                    } else {
0932:                        throw new ParseException("Operands or '" + op
0933:                                + "' must be primitive");
0934:                    }
0935:                }
0936:                // can compare any numeric doubles
0937:                double rr = ((PrimitiveValue) right).doubleValue();
0938:                double ll = ((PrimitiveValue) left).doubleValue();
0939:                boolean res;
0940:                if (op.equals("<")) {
0941:                    res = rr < ll;
0942:                } else if (op.equals(">")) {
0943:                    res = rr > ll;
0944:                } else if (op.equals("<=")) {
0945:                    res = rr <= ll;
0946:                } else if (op.equals(">=")) {
0947:                    res = rr >= ll;
0948:                } else if (op.equals("==")) {
0949:                    res = rr == ll;
0950:                } else if (op.equals("!=")) {
0951:                    res = rr != ll;
0952:                } else {
0953:                    throw new ParseException("Unknown operation: " + op);
0954:                }
0955:                return make(vm, res);
0956:            }
0957:
0958:            static LValue operation(VirtualMachine vm, Token token,
0959:                    LValue rightL, LValue leftL,
0960:                    ExpressionParser.GetFrame frameGetter)
0961:                    throws ParseException {
0962:                String op = token.image;
0963:                Value right = rightL.interiorGetValue();
0964:                Value left = leftL.interiorGetValue();
0965:                if ((right instanceof  StringReference)
0966:                        || (left instanceof  StringReference)) {
0967:                    if (op.equals("+")) {
0968:                        // If one is an ObjectRef, we will need to invoke
0969:                        // toString on it, so we need the thread. 
0970:                        return make(vm, stringValue(rightL, frameGetter)
0971:                                + stringValue(leftL, frameGetter));
0972:                    }
0973:                }
0974:                if ((right instanceof  ObjectReference)
0975:                        || (left instanceof  ObjectReference)) {
0976:                    if (op.equals("==")) {
0977:                        return make(vm, right.equals(left));
0978:                    } else if (op.equals("!=")) {
0979:                        return make(vm, !right.equals(left));
0980:                    } else {
0981:                        throw new ParseException("Invalid operation '" + op
0982:                                + "' on an Object");
0983:                    }
0984:                }
0985:                if ((right instanceof  BooleanValue)
0986:                        || (left instanceof  BooleanValue)) {
0987:                    throw new ParseException("Invalid operation '" + op
0988:                            + "' on a Boolean");
0989:                }
0990:                // from here on, we know it is a integer kind of type
0991:                PrimitiveValue primRight = (PrimitiveValue) right;
0992:                PrimitiveValue primLeft = (PrimitiveValue) left;
0993:                if ((primRight instanceof  DoubleValue)
0994:                        || (primLeft instanceof  DoubleValue)) {
0995:                    double rr = primRight.doubleValue();
0996:                    double ll = primLeft.doubleValue();
0997:                    double res;
0998:                    if (op.equals("+")) {
0999:                        res = rr + ll;
1000:                    } else if (op.equals("-")) {
1001:                        res = rr - ll;
1002:                    } else if (op.equals("*")) {
1003:                        res = rr * ll;
1004:                    } else if (op.equals("/")) {
1005:                        res = rr / ll;
1006:                    } else {
1007:                        throw new ParseException("Unknown operation: " + op);
1008:                    }
1009:                    return make(vm, res);
1010:                }
1011:                if ((primRight instanceof  FloatValue)
1012:                        || (primLeft instanceof  FloatValue)) {
1013:                    float rr = primRight.floatValue();
1014:                    float ll = primLeft.floatValue();
1015:                    float res;
1016:                    if (op.equals("+")) {
1017:                        res = rr + ll;
1018:                    } else if (op.equals("-")) {
1019:                        res = rr - ll;
1020:                    } else if (op.equals("*")) {
1021:                        res = rr * ll;
1022:                    } else if (op.equals("/")) {
1023:                        res = rr / ll;
1024:                    } else {
1025:                        throw new ParseException("Unknown operation: " + op);
1026:                    }
1027:                    return make(vm, res);
1028:                }
1029:                if ((primRight instanceof  LongValue)
1030:                        || (primLeft instanceof  LongValue)) {
1031:                    long rr = primRight.longValue();
1032:                    long ll = primLeft.longValue();
1033:                    long res;
1034:                    if (op.equals("+")) {
1035:                        res = rr + ll;
1036:                    } else if (op.equals("-")) {
1037:                        res = rr - ll;
1038:                    } else if (op.equals("*")) {
1039:                        res = rr * ll;
1040:                    } else if (op.equals("/")) {
1041:                        res = rr / ll;
1042:                    } else {
1043:                        throw new ParseException("Unknown operation: " + op);
1044:                    }
1045:                    return make(vm, res);
1046:                } else {
1047:                    int rr = primRight.intValue();
1048:                    int ll = primLeft.intValue();
1049:                    int res;
1050:                    if (op.equals("+")) {
1051:                        res = rr + ll;
1052:                    } else if (op.equals("-")) {
1053:                        res = rr - ll;
1054:                    } else if (op.equals("*")) {
1055:                        res = rr * ll;
1056:                    } else if (op.equals("/")) {
1057:                        res = rr / ll;
1058:                    } else {
1059:                        throw new ParseException("Unknown operation: " + op);
1060:                    }
1061:                    return make(vm, res);
1062:                }
1063:            }
1064:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.