/******************************************************************************* * Copyright (c) 2012 Pivotal Software, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.groovy.debug.core.evaluation; import groovy.lang.Closure; import groovy.lang.GString; import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.Script; import groovy.util.Proxy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.ast.ClassCodeVisitorSupport; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.expr.ClassExpression; import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.ConstructorCallExpression; import org.codehaus.groovy.ast.expr.ListExpression; import org.codehaus.groovy.ast.expr.MapEntryExpression; import org.codehaus.groovy.ast.expr.MapExpression; import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; import org.codehaus.groovy.control.SourceUnit; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.debug.core.IJavaArray; import org.eclipse.jdt.debug.core.IJavaArrayType; import org.eclipse.jdt.debug.core.IJavaClassObject; import org.eclipse.jdt.debug.core.IJavaClassType; import org.eclipse.jdt.debug.core.IJavaDebugTarget; import org.eclipse.jdt.debug.core.IJavaFieldVariable; import org.eclipse.jdt.debug.core.IJavaObject; import org.eclipse.jdt.debug.core.IJavaPrimitiveValue; import org.eclipse.jdt.debug.core.IJavaReferenceType; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.eclipse.jdt.debug.core.IJavaThread; import org.eclipse.jdt.debug.core.IJavaType; import org.eclipse.jdt.debug.core.IJavaValue; import org.eclipse.jdt.debug.core.JDIDebugModel; import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue; import org.grails.ide.eclipse.groovy.debug.core.GroovyDebugCoreActivator; import com.sun.jdi.VMDisconnectedException; /** * This class provides some useful operations to perform on * the {@link IJavaDebugTarget}. * @author Andrew Eisenberg * @since 2.5.1 */ public class JDITargetDelegate { /** * * @author Andrew Eisenberg * @created Nov 12, 2010 */ private final class JDIProxy extends Proxy { @Override public String toString() { // strip quotes if exists // not right...what if quotes really exist??? String s = this.getAdaptee().toString(); if (s.charAt(0) == '"') { s = s.substring(1); } if (s.charAt(s.length()-1) == '"') { s = s.substring(0, s.length()-1); } return s; } } /** * Visits the script used for evaluation and looks for all class references * these references will then have their meta classes changed. */ class ClassStoreVisitor extends ClassCodeVisitorSupport { Set<Class<?>> referencedClasses; private final JDIGroovyClassLoader loader; ClassStoreVisitor(JDIGroovyClassLoader loader) { this.loader = loader; } Set<Class<?>> doVisit(ClassNode node) { referencedClasses = new HashSet<Class<?>>(); node.visitContents(this); return referencedClasses; } protected SourceUnit getSourceUnit() { return null; } private void storeClass(ClassNode classNode) { try { Class<?> typeClass = classNode.getTypeClass(); if (typeClass != null) { referencedClasses.add(typeClass); } } catch (GroovyBugError e) { // could be that this is a class reference of a class defined in the // script. if (classNode.getModule().getDescription().equals(GroovyJDIEvaluator.SCRIPT_FILE_NAME) && ! classNode.getName().equals(syntheticScriptName)) { // try to load it (but don't try to load the generated script class) try { Class<?> typeClass = loader.loadClass(classNode.getName()); if (typeClass != null) { referencedClasses.add(typeClass); } } catch (ClassNotFoundException cnfe) { // can ignore } } } } public void visitStaticMethodCallExpression( StaticMethodCallExpression expression) { storeClass(expression.getType()); super.visitStaticMethodCallExpression(expression); } public void visitClassExpression(ClassExpression expression) { storeClass(expression.getType()); super.visitClassExpression(expression); } public void visitConstantExpression(ConstantExpression expression) { storeClass(expression.getType()); super.visitConstantExpression(expression); } public void visitConstructorCallExpression( ConstructorCallExpression expression) { storeClass(expression.getType()); super.visitConstructorCallExpression(expression); } public void visitMapExpression(MapExpression expression) { storeClass(expression.getType()); super.visitMapExpression(expression); } public void visitMapEntryExpression(MapEntryExpression expression) { storeClass(expression.getType()); super.visitMapEntryExpression(expression); } public void visitListExpression(ListExpression expression) { storeClass(expression.getType()); super.visitListExpression(expression); } } private final IJavaDebugTarget target; private final IJavaThread thread; private Set<MetaClass> cachedOriginalMetaClasses; private String syntheticScriptName; // keep track of values that we have turned off garbage collection for private List<IJavaObject> permStorage; public JDITargetDelegate(IJavaDebugTarget target, IJavaThread thread) { super(); this.target = target; this.thread = thread; this.permStorage = new ArrayList<IJavaObject>(); } public void initialize(JDIGroovyClassLoader loader, String syntheticScriptName) throws DebugException { this.syntheticScriptName = syntheticScriptName; cachedOriginalMetaClasses = new HashSet<MetaClass>(); // need to determine which classes are statically referenced // so parse the class and visit all types // do we need to visit imports? ClassStoreVisitor visitor = new ClassStoreVisitor(loader); Set<Class<?>> allClasses = visitor.doVisit(loader.getTheClass()); // force metaclasses for each of the types that can be referenced as literals for (Class<?> clazz : allClasses) { createMetaClassFor(loader, clazz); } } private void createMetaClassFor(ClassLoader loader, Class<?> clazz) throws DebugException { MetaClass meta = GroovySystem.getMetaClassRegistry().getMetaClass(clazz); JDIMetaClass jidMetaClass = new JDIMetaClass(meta, this); GroovySystem.getMetaClassRegistry().setMetaClass(clazz, jidMetaClass); cachedOriginalMetaClasses.add(meta); if (clazz.isPrimitive()) { // also create metaclass for boxed type if (clazz == int.class) { createMetaClassFor(loader, Integer.class); } else if (clazz == double.class) { createMetaClassFor(loader, Double.class); } else if (clazz == boolean.class) { createMetaClassFor(loader, Boolean.class); } else if (clazz == char.class) { createMetaClassFor(loader, Character.class); } else if (clazz == short.class) { createMetaClassFor(loader, Short.class); } else if (clazz == byte.class) { createMetaClassFor(loader, Byte.class); } else if (clazz == long.class) { createMetaClassFor(loader, Long.class); } else if (clazz == float.class) { createMetaClassFor(loader, Float.class); } else if (clazz == void.class) { createMetaClassFor(loader, Void.class); } } } public void cleanup() { // will only be null if there was an error during initialization if (cachedOriginalMetaClasses != null) { for (MetaClass meta : cachedOriginalMetaClasses) { GroovySystem.getMetaClassRegistry().removeMetaClass(meta.getTheClass()); } } // now release garbage collected objects if (permStorage != null) { for (IJavaObject object : permStorage) { try { object.enableCollection(); } catch (CoreException e) { // don't worry about GC if the VM has terminated if ((e.getStatus().getException() instanceof VMDisconnectedException)) { break; } GroovyDebugCoreActivator.log(e); } } permStorage = null; } } public void disableCollection(IJavaObject object) { try { object.disableCollection(); permStorage.add(object); } catch (CoreException e) { GroovyDebugCoreActivator.log(e); } } public Proxy createProxyFor(IJavaValue value) throws DebugException { Proxy proxyObj = new JDIProxy(); if (value instanceof JDIObjectValue) { if (!value.isNull() && value.getJavaType().getName().equals("groovy.lang.Reference")) { JDIObjectValue object = (JDIObjectValue) value; value = object.sendMessage("get", "()Ljava/lang/Object;", new IJavaValue[0], getThread(), false); } } proxyObj.setMetaClass(new JDIMetaClass(null, getMetaClass(value), this)); proxyObj.setAdaptee(value); return proxyObj; } public IJavaObject getMetaClass(IJavaValue object) throws DebugException { if (object.isNull()) { IJavaReferenceType nullObjectClass = (IJavaReferenceType) getType("org.codehaus.groovy.runtime.NullObject"); return invokeStaticMethod("org.codehaus.groovy.runtime.InvokerHelper", "getMetaClass", "(Ljava/lang/Class;)Lgroovy/lang/MetaClass;", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ new IJavaValue[] { nullObjectClass.getClassObject() }, thread); } else if (object instanceof IJavaObject) { IJavaFieldVariable var = ((IJavaObject) object).getField("metaClass", false); //$NON-NLS-1$ if (var != null) { return (IJavaObject) var.getValue(); } } // probably doesn't have groovy object support. use InvokerHelper return invokeStaticMethod("org.codehaus.groovy.runtime.InvokerHelper", "getMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ new IJavaValue[] { object }, thread); } public IJavaObject invokeStaticMethod(String className, String methodName, String methodSignature, IJavaValue[] args, IJavaThread thread) throws DebugException { IJavaType type = getType(className); if (type instanceof IJavaClassType) { IJavaValue[] newargs = new IJavaValue[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] instanceof IJavaPrimitiveValue) { newargs[i] = convertToJDIBoxedType(args[i]); } else { newargs[i] = args[i]; } } return (IJavaObject) ((IJavaClassType) type).sendMessage(methodName, methodSignature, newargs, thread); } else { return throwInvalidObjectException(type); } } public IJavaType getType(String className) throws DebugException { IJavaType[] types = target.getJavaTypes(className); IJavaType classClass = null; if (types != null && types.length > 0) { classClass = types[0]; } if (classClass == null) { // try to forcibly load the class getClassObject(className); types = target.getJavaTypes(className); if (types != null && types.length > 0) { classClass = types[0]; } if (classClass == null) { throwInvalidObjectException(className); } } return classClass; } /** * Constructs and returns a new instance of the specified * class on the target VM. Assumes that a no-arg constructor exists * * @param className fully qualified class name * @return a new instance on the target, as an <code>IJavaValue</code> * @exception DebugException if creation fails */ protected IJavaObject newInstance(String className) throws DebugException { IJavaClassObject classObject = getClassObject(className); IJavaObject object = (IJavaObject) classObject.sendMessage("newInstance", "()Ljava/lang/Object;", null, thread, false); //$NON-NLS-2$ //$NON-NLS-1$ return object; } protected IJavaArray newArrayInstance(String className, int size) throws DebugException { IJavaClassObject classObject = getClassObject(className); IJavaArrayType arrayType = (IJavaArrayType) classObject.getInstanceType(); IJavaArray object = arrayType.newInstance(size); disableCollection(object); return object; } public IJavaClassObject getClassObject(String className) throws DebugException { // Force the load of the class. IJavaClassType classClass = (IJavaClassType) getType("java.lang.Class"); //$NON-NLS-1$ IJavaValue[] args = new IJavaValue[] { target.newValue(className)}; disableCollection((IJavaObject) args[0]); IJavaClassObject classObject = (IJavaClassObject) classClass.sendMessage("forName", "(Ljava/lang/String;)Ljava/lang/Class;", args, thread); //$NON-NLS-2$ //$NON-NLS-1$ return classObject; } /** * Recursively converts an object to its JDI equivalent. * {@link Proxy} objects return their adaptee * Array objects return a JDI array where each array element is converted to a JDI Object * Literals (eg- primitives, strings, lists, and maps) are also converted * @param o * @return * @throws DebugException if the object passed in is not a valid object that can be converted to * JDI */ public IJavaValue toJDIObject(Object o) throws DebugException { if (o instanceof Proxy) { Proxy p = (Proxy) o; Object adaptee = p.getAdaptee(); if (adaptee instanceof IJavaObject) { IJavaObject adapteeJDI = (IJavaObject) adaptee; return adapteeJDI; } else if (adaptee instanceof IJavaPrimitiveValue) { return convertToJDIBoxedType(adaptee); } else { return throwInvalidObjectException(o); } } else if (o instanceof Object[]) { Object[] arr = (Object[]) o; IJavaArray arrayObject = newArrayInstance(arr.getClass().getName(), arr.length); //$NON-NLS-1$ for (int i = 0; i < arr.length; i++) { arrayObject.setValue(i, toJDIObject(arr[i])); } return arrayObject; } else if (o instanceof IJavaValue) { return (IJavaValue) o; } else if (o instanceof Script) { // return the currently executing object // if currently executing frame is static, then return // the java.lang.Class for the frame. IJavaObject thiz = getThis(); return thiz; } else if (o == null) { return target.nullValue(); } else if (o instanceof Class) { return ((IJavaReferenceType) getType(((Class<?>) o).getName())).getClassObject(); } else { // probably coming from a literal if (o instanceof Integer || o instanceof Boolean || o instanceof Double || o instanceof Float || o instanceof Byte || o instanceof Character || o instanceof Short || o instanceof Long) { return convertToJDIBoxedType(o); // other non-primitives that can be specified as constants } else if (o instanceof String) { return target.newValue((String) o); } else if (o instanceof List) { // create an ArrayList in the debugged application and add each of the elements return newJDIList((List<?>) o); } else if (o instanceof Map) { // create a HashMap in the debugged application and put each of the entries in it return newJDIMap((Map<?, ?>) o); } else if (o instanceof GString) { // create a GString in the debugged application return newJDIGString((GString) o); } else if (o instanceof Closure) { // hmmmmm....this is not working // create Closure in the debugged application return newJDIClosure((Closure) o); } else { return throwInvalidObjectException(o); } } } /** * Creates a GString in the debugged application * @param strings * @param values * @return * @throws DebugException */ private IJavaValue newJDIGString(GString gstring) throws DebugException { String[] strings = gstring.getStrings(); Object[] values = gstring.getValues(); IJavaClassObject classObject = getClassObject("org.codehaus.groovy.runtime.GStringImpl"); // returns the 2-arg constructor IJavaArray constructors = (IJavaArray) classObject.sendMessage("getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;", null, thread, false); //$NON-NLS-2$ //$NON-NLS-1$ IJavaObject constructor = (IJavaObject) constructors.getValue(0); IJavaArray args = newArrayInstance("[Ljava.lang.Object;", 2); // note that here we need to use '.' instead of '/' to create the array args.setValue(0, toJDIObject(values)); args.setValue(1, toJDIObject(strings)); return constructor.sendMessage("newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", new IJavaValue[] { args }, thread, false); } /** * @return 'this', the currently executing object on the current stack * frame. Or returns the class object if a static frame. * @throws DebugException */ protected IJavaObject getThis() throws DebugException { IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame(); IJavaObject thisObj = frame.getThis(); if (thisObj != null) { return thisObj; } else { // in a static frame return frame.getReferenceType().getClassObject(); } } /** * Converts a boxed primitive object type to a JDI boxed type * @param o the object to convert * @return a JDI object corresponding to the boxed type * @throws DebugException */ protected IJavaValue convertToJDIBoxedType(Object o) throws DebugException { IJavaClassType type; if (o instanceof IJavaPrimitiveValue) { IJavaPrimitiveValue val = (IJavaPrimitiveValue) o; type = getBoxedClassTypeForPrimitive(val.getSignature()); } else { String className = o.getClass().getName(); type = (IJavaClassType) getType(className); } IJavaValue primitiveValue; String sig = null; // first convert to JDI primitive if (o instanceof Integer) { primitiveValue = target.newValue((Integer) o); } else if (o instanceof Boolean) { primitiveValue = target.newValue((Boolean) o); } else if (o instanceof Double) { primitiveValue = target.newValue((Double) o); } else if (o instanceof Float) { primitiveValue = target.newValue((Float) o); } else if (o instanceof Byte) { primitiveValue = target.newValue((Byte) o); } else if (o instanceof Character) { primitiveValue = target.newValue((Character) o); } else if (o instanceof Short) { primitiveValue = target.newValue((Short) o); } else if (o instanceof Long) { primitiveValue = target.newValue((Long) o); } else if (o instanceof IJavaPrimitiveValue) { primitiveValue = (IJavaPrimitiveValue) o; } else { // shouldn't get here primitiveValue = null; throw new DebugException(new Status(IStatus.ERROR, GroovyDebugCoreActivator.PLUGIN_ID, "(Groovy) Cannot convert object " + o + " into a primitive")); } // now find the signature of the valueOf method to use if (primitiveValue != null) { if (primitiveValue.getSignature().equals("I")) { sig = "(I)Ljava/lang/Integer;"; } else if (primitiveValue.getSignature().equals("Z")) { sig = "(Z)Ljava/lang/Boolean;"; } else if (primitiveValue.getSignature().equals("D")) { sig = "(D)Ljava/lang/Double;"; } else if (primitiveValue.getSignature().equals("F")) { sig = "(F)Ljava/lang/Float;"; } else if (primitiveValue.getSignature().equals("B")) { sig = "(B)Ljava/lang/Byte;"; } else if (primitiveValue.getSignature().equals("C")) { sig = "(C)Ljava/lang/Character;"; } else if (primitiveValue.getSignature().equals("S")) { sig = "(S)Ljava/lang/Short;"; } else if (primitiveValue.getSignature().equals("J")) { sig = "(J)Ljava/lang/Long;"; } } // now extract the primitive from the boxed value return type.sendMessage("valueOf", sig, new IJavaValue[] { primitiveValue }, thread); //$NON-NLS-1$ //$NON-NLS-2$ } public IJavaPrimitiveValue convertToUnboxedType(IJavaValue value) throws DebugException { if (value instanceof IJavaPrimitiveValue) { return (IJavaPrimitiveValue) value; } String methodNameToInvoke; String methodSignatureToInvoke; if (value.getJavaType().getName().equals("java.lang.Integer")) { methodNameToInvoke = "intValue"; methodSignatureToInvoke = "()I"; } else if (value.getJavaType().getName().equals("java.lang.Boolean")) { methodNameToInvoke = "booleanValue"; methodSignatureToInvoke = "()Z"; } else if (value.getJavaType().getName().equals("java.lang.Double")) { methodNameToInvoke = "doubleValue"; methodSignatureToInvoke = "()D"; } else if (value.getJavaType().getName().equals("java.lang.Float")) { methodNameToInvoke = "floatValue"; methodSignatureToInvoke = "()F"; } else if (value.getJavaType().getName().equals("java.lang.Byte")) { methodNameToInvoke = "byteValue"; methodSignatureToInvoke = "()B"; } else if (value.getJavaType().getName().equals("java.lang.Character")) { methodNameToInvoke = "charValue"; methodSignatureToInvoke = "()C"; } else if (value.getJavaType().getName().equals("java.lang.Short")) { methodNameToInvoke = "shortValue"; methodSignatureToInvoke = "()S"; } else if (value.getJavaType().getName().equals("java.lang.Long")) { methodNameToInvoke = "longValue"; methodSignatureToInvoke = "()J"; } else { methodNameToInvoke = null; methodSignatureToInvoke = null; throw new DebugException(new Status(IStatus.ERROR, GroovyDebugCoreActivator.PLUGIN_ID, "(Groovy) Cannot convert object " + value + " into a primitive")); } return (IJavaPrimitiveValue) ((IJavaObject) value).sendMessage(methodNameToInvoke, methodSignatureToInvoke, new IJavaValue[0], thread, false); } protected IJavaClassType getBoxedClassTypeForPrimitive( String primitiveSignature) throws DebugException { IJavaClassType type; String className; if (primitiveSignature.equals("I")) { className = "java.lang.Integer"; } else if (primitiveSignature.equals("Z")) { className = "java.lang.Boolean"; } else if (primitiveSignature.equals("D")) { className = "java.lang.Double"; } else if (primitiveSignature.equals("F")) { className = "java.lang.Float"; } else if (primitiveSignature.equals("B")) { className = "java.lang.Byte"; } else if (primitiveSignature.equals("C")) { className = "java.lang.Character"; } else if (primitiveSignature.equals("S")) { className = "java.lang.Short"; } else if (primitiveSignature.equals("J")) { className = "java.lang.Long"; } else { className = "java.lang.Void"; } type = (IJavaClassType) getType(className); return type; } // this is not working private IJavaObject newJDIClosure(Closure c) throws DebugException { IJavaClassType methodClosureClass = (IJavaClassType) getType("org.codehaus.groovy.runtime.MethodClosure"); //$NON-NLS-1$ IJavaClassType closureClass = (IJavaClassType) getType("groovy.lang.Closure"); //$NON-NLS-1$ IJavaObject jdiOwner = closureClass.getClassObject(); IJavaValue jdiMethodName = toJDIObject("call"); //$NON-NLS-1$ return methodClosureClass.newInstance("(Ljava/lang/Object;Ljava/lang/String;)V", //$NON-NLS-1$ new IJavaValue[] { jdiOwner, jdiMethodName}, thread); } private IJavaObject newJDIList(List<?> list) throws DebugException { IJavaObject jdiList = newInstance("java.util.ArrayList"); //$NON-NLS-1$ for (Iterator<?> iterator = list.iterator(); iterator.hasNext();) { Object o = iterator.next(); IJavaValue jdiObject = toJDIObject(o); jdiList.sendMessage("add", "(Ljava/lang/Object;)Z", new IJavaValue[] { jdiObject }, thread, false); //$NON-NLS-1$ //$NON-NLS-2$ } return jdiList; } private IJavaObject newJDIMap(Map<?, ?> map) throws DebugException { IJavaObject jdiMap = newInstance("java.util.HashMap"); //$NON-NLS-1$ for (Iterator<?> iterator = map.entrySet().iterator(); iterator.hasNext();) { Entry<?, ?> e = (Entry<?, ?>) iterator.next(); IJavaValue jdiKey = toJDIObject(e.getKey()); IJavaValue jdiValue = toJDIObject(e.getValue()); jdiMap.sendMessage("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", new IJavaValue[] { jdiKey, jdiValue }, thread, false); //$NON-NLS-1$ //$NON-NLS-2$ } return jdiMap; } /** * @param o * @throws DebugException */ private IJavaObject throwInvalidObjectException(Object o) throws DebugException { throw new DebugException( new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), DebugException.REQUEST_FAILED, "(Groovy) Invalid object " + o, null) //$NON-NLS-1$ ); } public IJavaThread getThread() { return thread; } public IJavaDebugTarget getTarget() { return target; } /** * Converts a meta class over here to a meta class over there * @param metaClass * @return * @throws DebugException */ public IJavaObject createMetaClassInDebuggedApplication(MetaClass metaClass) throws DebugException { IJavaClassType groovySystemType = (IJavaClassType) getType("groovy.lang.GroovySystem"); //$NON-NLS-1$ IJavaObject registry = (IJavaObject) groovySystemType.getField("META_CLASS_REGISTRY").getValue(); //$NON-NLS-1$ Class<?> theClass = metaClass.getTheClass(); IJavaType type; if (theClass.isPrimitive()) { type = getBoxedClassTypeForPrimitive(Signature.createTypeSignature(theClass.getName(), true)); } else { type = getType(theClass.getName()); } return (IJavaObject) registry.sendMessage("getMetaClass", "(Ljava/lang/Class;)Lgroovy/lang/MetaClass;", new IJavaValue[] { ((IJavaReferenceType) type).getClassObject() }, thread, false); //$NON-NLS-1$ //$NON-NLS-2$ } /** * When the asBoolean method is called, it is likely an implicit conversion to * Boolean as part of an if statement, etc. * @param result * @return * @throws DebugException */ public static Boolean convertToBoolean(IJavaValue result) throws DebugException { try { if (result instanceof IJavaPrimitiveValue) { return ((IJavaPrimitiveValue) result).getBooleanValue(); } else { return Boolean.valueOf(((JDIObjectValue) result).getField("value", false).getValue().getValueString()); } } catch (Exception e) { if (!(e instanceof DebugException)) { throw new DebugException(new Status(IStatus.ERROR, GroovyDebugCoreActivator.PLUGIN_ID, "(Groovy) Should have had a Boolean result", e)); } else { throw (DebugException) e; } } } public Integer convertToInteger(IJavaValue result) throws DebugException { try { if (result instanceof IJavaPrimitiveValue) { return ((IJavaPrimitiveValue) result).getIntValue(); } else { return Integer.valueOf(((JDIObjectValue) result).getField("value", false).getValue().getValueString()); } } catch (Exception e) { if (!(e instanceof DebugException)) { throw new DebugException(new Status(IStatus.ERROR, GroovyDebugCoreActivator.PLUGIN_ID, "(Groovy) Should have had a Boolean result", e)); } else { throw (DebugException) e; } } } /** * Likely an implicit call to iterator as part of a for loop * @param result * @return */ public Iterator<Proxy> convertToIterator(IJavaValue result, JDIMetaClass metaClass) throws DebugException { return new JDIIterator((IJavaObject) result, this); } }