001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Micro//S ystems, Inc. Portions Copyright 1997-2007 Sun
028: * Micro//S ystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.debugger.jpda.expr;
043:
044: import com.sun.jdi.ClassNotLoadedException;
045: import com.sun.jdi.IncompatibleThreadStateException;
046: import com.sun.jdi.InvalidTypeException;
047: import com.sun.jdi.InvocationException;
048: import com.sun.jdi.Location;
049: import com.sun.jdi.Method;
050: import com.sun.jdi.Mirror;
051: import com.sun.jdi.ObjectCollectedException;
052: import com.sun.jdi.ObjectReference;
053: import com.sun.jdi.StackFrame;
054: import com.sun.jdi.ThreadReference;
055: import com.sun.jdi.Value;
056: import com.sun.jdi.VirtualMachine;
057:
058: import java.util.List;
059: import java.util.logging.Level;
060: import java.util.logging.Logger;
061: import org.netbeans.api.debugger.jpda.InvalidExpressionException;
062:
063: import org.netbeans.modules.debugger.jpda.EditorContextBridge;
064: import org.openide.util.NbBundle;
065:
066: /**
067: *
068: * @author Martin Entlicher
069: */
070: public class TreeEvaluator {
071:
072: private Expression2 expression;
073: private EvaluationContext evaluationContext;
074:
075: private StackFrame frame;
076: private VirtualMachine vm;
077: private ThreadReference frameThread;
078: private int frameIndex;
079: private String currentPackage;
080: private Operators operators;
081:
082: private static final Logger loggerMethod = Logger
083: .getLogger("org.netbeans.modules.debugger.jpda.invokeMethod"); // NOI18N
084:
085: TreeEvaluator(Expression2 expression, EvaluationContext context) {
086: this .expression = expression;
087: this .evaluationContext = context;
088: }
089:
090: /**
091: * Evaluates the expression for which it was created.
092: *
093: * @return the result of evaluating the expression as a JDI Value object.
094: * It returns null if the result itself is null.
095: * @throws EvaluationException if the expression cannot be evaluated for whatever reason
096: * @throws IncompatibleThreadStateException if the context thread is in an
097: * incompatible state (running, dead)
098: */
099: public Value evaluate() throws EvaluationException2,
100: IncompatibleThreadStateException,
101: InvalidExpressionException {
102: frame = evaluationContext.getFrame();
103: vm = evaluationContext.getFrame().virtualMachine();
104: frameThread = frame.thread();
105: frameIndex = indexOf(frameThread.frames(), frame);
106: if (frameIndex == -1) {
107: throw new IncompatibleThreadStateException(
108: "Thread does not contain current frame");
109: }
110: currentPackage = evaluationContext.getFrame().location()
111: .declaringType().name();
112: int idx = currentPackage.lastIndexOf('.');
113: currentPackage = (idx > 0) ? currentPackage.substring(0,
114: idx + 1) : "";
115: operators = new Operators(vm);
116: int line = frame.location().lineNumber();
117: String url = evaluationContext.getDebugger().getEngineContext()
118: .getURL(frame, "Java");//evaluationContext.getDebugger().getSession().getCurrentLanguage());
119: /*try {
120: url = frame.location().sourcePath(expression.getLanguage());
121: } catch (AbsentInformationException ex) {
122: return null;
123: }*/
124: //Tree exprTree = EditorContextBridge.getExpressionTree(expression.getExpression(), url, line);
125: //if (exprTree == null) return null;
126: try {
127: Mirror mirror = EditorContextBridge.parseExpression(
128: expression.getExpression(), url, line,
129: new EvaluatorVisitor(), evaluationContext,
130: evaluationContext.getDebugger().getEngineContext()
131: .getContext());
132: if (mirror instanceof Value || mirror == null) {
133: return (Value) mirror;
134: } else {
135: throw new InvalidExpressionException(expression
136: .getExpression());
137: }
138: //return exprTree.accept(new EvaluatorVisitor(), evaluationContext);
139: } catch (IllegalStateException isex) {
140: Throwable thr = isex.getCause();
141: if (thr instanceof IncompatibleThreadStateException) {
142: throw (IncompatibleThreadStateException) thr;
143: }
144: if (thr instanceof InvalidExpressionException) {
145: throw (InvalidExpressionException) thr;
146: }
147: throw isex;
148: }
149: //return (Value) rootNode.jjtAccept(this, null);
150: //return null;
151: }
152:
153: private int indexOf(List<StackFrame> frames, StackFrame frame) {
154: int n = frames.size();
155: Location loc = frame.location();
156: for (int i = 0; i < n; i++) {
157: if (loc.equals(frames.get(i).location()))
158: return i;
159: }
160: return -1;
161: }
162:
163: public static Value invokeVirtual(ObjectReference objectReference,
164: Method method, ThreadReference evaluationThread,
165: List<Value> args) throws InvalidExpressionException {
166:
167: try {
168: if (loggerMethod.isLoggable(Level.FINE)) {
169: loggerMethod.fine("STARTED : " + objectReference + "."
170: + method + " (" + args + ") in thread "
171: + evaluationThread);
172: }
173: Value value = objectReference.invokeMethod(
174: evaluationThread, method, args,
175: ObjectReference.INVOKE_SINGLE_THREADED);
176: if (loggerMethod.isLoggable(Level.FINE)) {
177: loggerMethod.fine(" return = " + value);
178: }
179: return value;
180: } catch (InvalidTypeException itex) {
181: throw new InvalidExpressionException(itex);
182: } catch (ClassNotLoadedException cnlex) {
183: throw new InvalidExpressionException(cnlex);
184: } catch (IncompatibleThreadStateException itsex) {
185: InvalidExpressionException ieex = new InvalidExpressionException(
186: itsex);
187: ieex.initCause(itsex);
188: throw ieex;
189: } catch (InvocationException iex) {
190: InvalidExpressionException ieex = new InvalidExpressionException(
191: iex);
192: ieex.initCause(iex);
193: throw ieex;
194: } catch (UnsupportedOperationException uoex) {
195: InvalidExpressionException ieex = new InvalidExpressionException(
196: uoex);
197: ieex.initCause(uoex);
198: throw ieex;
199: } catch (ObjectCollectedException ocex) {
200: throw new InvalidExpressionException(NbBundle.getMessage(
201: TreeEvaluator.class, "CTL_EvalError_collected"));
202: } finally {
203: if (loggerMethod.isLoggable(Level.FINE)) {
204: loggerMethod.fine("FINISHED: " + objectReference + "."
205: + method + " (" + args + ") in thread "
206: + evaluationThread);
207: }
208: }
209: }
210: }
|