001: package org.drools.eclipse.debug.core;
002:
003: import java.util.ArrayList;
004: import java.util.Arrays;
005: import java.util.Comparator;
006: import java.util.Iterator;
007: import java.util.List;
008:
009: import org.drools.eclipse.DroolsEclipsePlugin;
010: import org.drools.eclipse.DRLInfo.RuleInfo;
011: import org.drools.eclipse.debug.DebugUtil;
012: import org.drools.eclipse.debug.VariableWrapper;
013: import org.eclipse.core.runtime.CoreException;
014: import org.eclipse.debug.core.DebugException;
015: import org.eclipse.debug.core.ILaunch;
016: import org.eclipse.debug.core.model.IDebugTarget;
017: import org.eclipse.debug.core.model.IValue;
018: import org.eclipse.debug.core.model.IVariable;
019: import org.eclipse.jdi.internal.StackFrameImpl;
020: import org.eclipse.jdt.debug.core.IJavaClassObject;
021: import org.eclipse.jdt.debug.core.IJavaFieldVariable;
022: import org.eclipse.jdt.debug.core.IJavaObject;
023: import org.eclipse.jdt.debug.core.IJavaReferenceType;
024: import org.eclipse.jdt.debug.core.IJavaValue;
025: import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable;
026: import org.eclipse.jdt.internal.debug.core.model.JDINullValue;
027: import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
028:
029: import com.sun.jdi.AbsentInformationException;
030: import com.sun.jdi.ArrayReference;
031: import com.sun.jdi.BooleanValue;
032: import com.sun.jdi.ClassNotLoadedException;
033: import com.sun.jdi.ClassType;
034: import com.sun.jdi.Field;
035: import com.sun.jdi.IncompatibleThreadStateException;
036: import com.sun.jdi.IntegerValue;
037: import com.sun.jdi.InvalidTypeException;
038: import com.sun.jdi.InvocationException;
039: import com.sun.jdi.LocalVariable;
040: import com.sun.jdi.Method;
041: import com.sun.jdi.ObjectReference;
042: import com.sun.jdi.ReferenceType;
043: import com.sun.jdi.StackFrame;
044: import com.sun.jdi.StringReference;
045: import com.sun.jdi.ThreadReference;
046: import com.sun.jdi.Value;
047:
048: /**
049: * Stack Frame for MVEL Dialect
050: *
051: * @author Ahti Kitsik
052: *
053: */
054: public class MVELStackFrame extends DroolsStackFrame {
055:
056: /**
057: * Dummy type with changed stratum to force debugger's LaunchView to show proper stackframe name
058: */
059: private static final IJavaReferenceType REF_TYPE = new IJavaReferenceType() {
060:
061: public String[] getAllFieldNames() throws DebugException {
062: return null;
063: }
064:
065: public String[] getAvailableStrata() throws DebugException {
066: return null;
067: }
068:
069: public IJavaObject getClassLoaderObject() throws DebugException {
070: return null;
071: }
072:
073: public IJavaClassObject getClassObject() throws DebugException {
074: return null;
075: }
076:
077: public String[] getDeclaredFieldNames() throws DebugException {
078: return null;
079: }
080:
081: public String getDefaultStratum() throws DebugException {
082: return "MVEL";
083: }
084:
085: public IJavaFieldVariable getField(String name)
086: throws DebugException {
087: return null;
088: }
089:
090: public String getGenericSignature() throws DebugException {
091: return null;
092: }
093:
094: public String getSourceName() throws DebugException {
095: return null;
096: }
097:
098: public String[] getSourceNames(String stratum)
099: throws DebugException {
100: return null;
101: }
102:
103: public String[] getSourcePaths(String stratum)
104: throws DebugException {
105: return null;
106: }
107:
108: public String getName() throws DebugException {
109: return null;
110: }
111:
112: public String getSignature() throws DebugException {
113: return null;
114: }
115:
116: public IDebugTarget getDebugTarget() {
117: return null;
118: }
119:
120: public ILaunch getLaunch() {
121: return null;
122: }
123:
124: public String getModelIdentifier() {
125: return null;
126: }
127:
128: public Object getAdapter(Class adapter) {
129: return null;
130: }
131:
132: };;
133:
134: public MVELStackFrame(DroolsThread thread, StackFrame frame,
135: int depth) {
136: super (thread, frame, depth);
137:
138: try {
139: Iterator i = thread.getUnderlyingThread().frames()
140: .iterator();
141: while (i.hasNext()) {
142: StackFrameImpl o = (StackFrameImpl) i.next();
143: }
144: } catch (IncompatibleThreadStateException e) {
145: DroolsEclipsePlugin.log(e);
146: }
147:
148: }
149:
150: public IVariable[] getVariables() throws DebugException {
151:
152: List result = new ArrayList(0);
153:
154: Method method = getUnderlyingMethod(); // onBreak
155: ReferenceType declaringType = method.declaringType(); // org.drools.base.mvel.MVELDebugHandler
156:
157: try {
158:
159: Object var = method.variables().get(0);
160: LocalVariable v2 = (LocalVariable) var;
161: DroolsLocalVariable frameLocal = new DroolsLocalVariable(
162: this , v2);
163:
164: IValue knownVars = DebugUtil
165: .getValueByExpression(
166: "return getFactory().getKnownVariables().toArray(new String[0]);",
167: frameLocal.getValue());
168:
169: IValue factory = DebugUtil.getValueByExpression(
170: "return getFactory();", frameLocal.getValue());
171:
172: JDIObjectValue vvv = (JDIObjectValue) knownVars;
173:
174: if (vvv != null) {
175: ArrayReference arr = (ArrayReference) vvv
176: .getUnderlyingObject();
177: Iterator varIter = arr.getValues().iterator();
178:
179: while (varIter.hasNext()) {
180: final String varName = ((StringReference) varIter
181: .next()).value();
182: IJavaValue val = (IJavaValue) DebugUtil
183: .getValueByExpression(
184: "return getVariableResolver(\""
185: + varName
186: + "\").getValue();",
187: factory);
188: if (val != null) {
189: final ObjectReference valRef = ((JDIObjectValue) val)
190: .getUnderlyingObject();
191: VariableWrapper local = new VariableWrapper(
192: varName, val);
193:
194: local.setPublic(true);
195: result.add(local);
196: } else {
197: DroolsEclipsePlugin.log(new Exception(
198: "Unable to get value for variable named '"
199: + varName + "'"));
200: }
201: }
202:
203: }
204:
205: IVariable[] vararr = (IVariable[]) result
206: .toArray(new IVariable[result.size()]);
207: return vararr;
208:
209: } catch (Throwable t) {
210: DroolsEclipsePlugin.log(t);
211: }
212:
213: IVariable[] vararr = (IVariable[]) result
214: .toArray(new IVariable[result.size()]);
215:
216: Arrays.sort(vararr, new Comparator() {
217:
218: public int compare(Object var1, Object var2) {
219: try {
220: return ((IVariable) var1).getName().compareTo(
221: ((IVariable) var2).getName());
222: } catch (DebugException e) {
223: return 0;
224: }
225: }
226:
227: });
228: return vararr;
229: }
230:
231: private boolean internalHasNext(Value iter)
232: throws InvalidTypeException, ClassNotLoadedException,
233: IncompatibleThreadStateException, InvocationException,
234: DebugException {
235: BooleanValue hasNext = (BooleanValue) runMethod(iter, "hasNext");
236: return hasNext.booleanValue();
237: }
238:
239: private Value fetchField(Value factoryVar, String fieldName)
240: throws ClassNotLoadedException, DebugException {
241: return fetchField((ObjectReference) factoryVar, fieldName);
242: }
243:
244: private Value runMethod(Value val, String methodName)
245: throws InvalidTypeException, ClassNotLoadedException,
246: IncompatibleThreadStateException, InvocationException,
247: DebugException {
248:
249: ObjectReference refObj = (ObjectReference) val;
250: ReferenceType t = refObj.referenceType();
251: Method m2 = (Method) t.methodsByName(methodName).iterator()
252: .next();
253: ThreadReference thread = ((DroolsThread) getThread())
254: .getUnderlyingThread();
255:
256: Value res = refObj.invokeMethod(thread, m2, new ArrayList(), 0);
257:
258: return res;
259: }
260:
261: private Value fetchField(DroolsLocalVariable frameLocal,
262: String fieldName) throws DebugException,
263: ClassNotLoadedException {
264: ObjectReference objRef = ((JDIObjectValue) frameLocal
265: .getValue()).getUnderlyingObject();
266: return fetchField(objRef, fieldName);
267: }
268:
269: private Value fetchField(ObjectReference ref, String fieldName)
270: throws ClassNotLoadedException, DebugException {
271: ClassType varType = (ClassType) ref.type();
272: Field field = varType.fieldByName(fieldName);
273: Value res = ref.getValue(field);
274: return res;
275: }
276:
277: protected DroolsStackFrame createNewDroolsFrame(StackFrame frame,
278: int depth) {
279: return new MVELStackFrame((DroolsThread) getThread(), frame,
280: depth);
281: }
282:
283: public int getLineNumber() throws DebugException {
284:
285: DroolsDebugTarget t = (DroolsDebugTarget) getDebugTarget();
286:
287: int lineNr = getBreakpointLineNumber();
288: String sourceName = getMVELName();
289:
290: DroolsLineBreakpoint bpoint = (DroolsLineBreakpoint) t
291: .getDroolsBreakpoint(sourceName, lineNr);
292:
293: if (bpoint == null) {
294: return -1;
295: }
296:
297: int line;
298:
299: try {
300: line = Integer.parseInt(bpoint.getFileRuleMappings().get(
301: sourceName).toString());
302: } catch (Throwable t2) {
303: DroolsEclipsePlugin.log(t2);
304: return -1;
305: }
306:
307: int fragmentLine = getBreakpointLineNumber(); // 4->5 for step over
308:
309: /* int delta = 0;
310: try {
311: delta = fragmentLine - bpoint.getLineNumber();
312: } catch ( CoreException e ) {
313: DroolsEclipsePlugin.log( e );
314: }
315: */int res = line + fragmentLine;
316: return res;
317: }
318:
319: public RuleInfo getExecutingRuleInfo() {
320: try {
321: String type = getDeclaringTypeName();
322:
323: return DroolsEclipsePlugin.getDefault().getRuleInfoByClass(
324: type);
325:
326: } catch (DebugException exc) {
327: DroolsEclipsePlugin.log(exc);
328: }
329: return null;
330: }
331:
332: public int getBreakpointLineNumber() {
333: try {
334: Object o = getRemoteVar("lineNumber");
335: if (o == null) {
336: return -1;
337: }
338: IntegerValue val = (IntegerValue) o;
339: return val.value();
340: } catch (Throwable e) {
341: DroolsEclipsePlugin.log(e);
342: }
343: return -1;
344: }
345:
346: public String getMVELName() {
347: try {
348: Object rem = getRemoteVar("sourceName");
349: if (rem == null) {
350: return null;
351: }
352: StringReference res = (StringReference) rem;
353: return res.value();
354: } catch (Throwable e) {
355: DroolsEclipsePlugin.log(e);
356: }
357:
358: return "Unavailable";
359: }
360:
361: private Object getRemoteVar(String methodName)
362: throws AbsentInformationException, ClassNotLoadedException,
363: DebugException, InvalidTypeException,
364: IncompatibleThreadStateException, InvocationException {
365:
366: //frame arg
367: Method method = getUnderlyingMethod(); // onBreak
368: ReferenceType declaringType = method.declaringType(); // org.drools.base.mvel.MVELDebugHandler
369:
370: LocalVariable var = (LocalVariable) method.variables().get(0);//frame
371:
372: JDILocalVariable jdivar = new JDILocalVariable(this ,
373: (LocalVariable) var);
374:
375: ClassType frameType = (ClassType) var.type();
376:
377: IValue value = jdivar.getValue();
378: if (value instanceof JDINullValue) {
379: return null;
380: }
381: ObjectReference o = (ObjectReference) ((JDIObjectValue) value)
382: .getUnderlyingObject();
383:
384: if (o == null) {
385: return null;
386: }
387: Field field = frameType.fieldByName(methodName);
388: Value val = o.getValue(field);
389:
390: return val;
391: }
392:
393: public String getSourcePath() throws DebugException {
394: return getMVELName();
395: }
396:
397: public boolean canStepInto() {
398: return false;
399: }
400:
401: public boolean canStepOver() {
402: return true;
403: }
404:
405: public boolean canDropToFrame() {
406: return false;
407: }
408:
409: public boolean canStepReturn() {
410: return false;
411: }
412:
413: public boolean canStepWithFilters() {
414: return false;
415: }
416:
417: public IJavaReferenceType getReferenceType() throws DebugException {
418: return REF_TYPE;
419: }
420:
421: public String getSourceName() throws DebugException {
422: return getMVELName();
423: }
424:
425: }
|