diff --git a/api.debugger.jpda/apichanges.xml b/api.debugger.jpda/apichanges.xml
--- a/api.debugger.jpda/apichanges.xml
+++ b/api.debugger.jpda/apichanges.xml
@@ -857,6 +857,24 @@
+
+
+ Add a way to create mirror objects in the target VM and execute static methods.
+
+
+
+
+
+ createMirrorVar() methods are introduced in JPDADebugger class. They
+ create a mirror object in the target virtual machine.
+
+ Similar to invokeMethod() method on ObjectVariable, invokeMethod()
+ is introduced on JPDAClassType for invocation of static methods.
+
+
+
+
+
diff --git a/api.debugger.jpda/manifest.mf b/api.debugger.jpda/manifest.mf
--- a/api.debugger.jpda/manifest.mf
+++ b/api.debugger.jpda/manifest.mf
@@ -1,6 +1,6 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.api.debugger.jpda/2
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/jpda/Bundle.properties
-OpenIDE-Module-Specification-Version: 2.46
+OpenIDE-Module-Specification-Version: 2.47
OpenIDE-Module-Package-Dependencies: com.sun.jdi[VirtualMachineManager]
diff --git a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAClassType.java b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAClassType.java
--- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAClassType.java
+++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAClassType.java
@@ -99,6 +99,25 @@
List staticFields();
/**
+ * Calls given static method in debugged JVM on this class and returns
+ * its value.
+ *
+ * @param methodName a name of method to be called
+ * @param signature a signature of method to be called
+ * @param arguments arguments to be used
+ *
+ * @return value of given method call on this instance
+ * @throws NoSuchMethodException when the method does not exist
+ * @throws InvalidExpressionException in case of execution problems
+ * @since 2.47
+ */
+ public abstract Variable invokeMethod (
+ String methodName,
+ String signature,
+ Variable[] arguments
+ ) throws NoSuchMethodException, InvalidExpressionException;
+
+ /**
* Retrieves the number of instances this class.
* Use {@link JPDADebugger#canGetInstanceInfo} to determine if this operation is supported.
* @return the number of instances.
diff --git a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java
--- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java
+++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java
@@ -51,6 +51,7 @@
import java.beans.PropertyChangeListener;
import java.io.File;
+import java.io.InvalidObjectException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -594,6 +595,32 @@
}
/**
+ * Create a mirror object in the target virtual machine
+ *
+ * @param obj the object to create the mirror from
+ * @return variable containing the mirror value
+ * @throws InvalidObjectException when the mirror operation fails
+ * @since 2.47
+ */
+ public Variable createMirrorVar(Object obj) throws InvalidObjectException {
+ return createMirrorVar(obj, false);
+ }
+
+ /**
+ * Create a mirror object in the target virtual machine
+ *
+ * @param obj the object to create the mirror from
+ * @param isPrimitive when true
and the object is an encapsulation
+ * of a primitive value, then primitive mirror is created.
+ * @return variable containing the mirror value
+ * @throws InvalidObjectException when the mirror operation fails
+ * @since 2.47
+ */
+ public Variable createMirrorVar(Object obj, boolean isPrimitive) throws InvalidObjectException {
+ throw new InvalidObjectException("Object "+obj+" not supported");
+ }
+
+ /**
* Retrieves the number of instances of each class in the list.
* Use {@link #canGetInstanceInfo} to determine if this operation is supported.
* @return an array of long
containing one instance counts for
diff --git a/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MethodInvocationTest.java b/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MethodInvocationTest.java
new file mode 100644
--- /dev/null
+++ b/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MethodInvocationTest.java
@@ -0,0 +1,105 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2013 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.api.debugger.jpda;
+
+import com.sun.jdi.ClassType;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.Value;
+import java.util.List;
+import java.util.Properties;
+import junit.framework.Test;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.debugger.jpda.expr.JDIVariable;
+
+/**
+ *
+ * @author Martin
+ */
+public class MethodInvocationTest extends NbTestCase {
+
+ private JPDASupport support;
+ private DebuggerManager dm = DebuggerManager.getDebuggerManager ();
+
+ public MethodInvocationTest(String s) {
+ super(s);
+ }
+
+ public static Test suite() {
+ return JPDASupport.createTestSuite(MethodInvocationTest.class);
+ }
+
+ public void testTargetMirrors() throws Exception {
+ try {
+ Utils.BreakPositions bp = Utils.getBreakPositions(System.getProperty ("test.dir.src") +
+ "org/netbeans/api/debugger/jpda/testapps/MirrorValuesApp.java");
+ LineBreakpoint lb = bp.getLineBreakpoints().get(0);
+ dm.addBreakpoint (lb);
+
+ support = JPDASupport.attach ("org.netbeans.api.debugger.jpda.testapps.MirrorValuesApp");
+
+ support.waitState (JPDADebugger.STATE_STOPPED); // breakpoint hit
+
+ JPDADebugger debugger = support.getDebugger();
+
+ List systemClasses = debugger.getClassesByName("java.lang.System");
+ assertEquals(systemClasses.size(), 1);
+ JPDAClassType systemClass = systemClasses.get(0);
+ Properties properties = System.getProperties();
+ Variable propertiesVar = systemClass.invokeMethod("getProperties", "()Ljava/util/Properties;", new Variable[]{});
+ Value pv = ((JDIVariable) propertiesVar).getJDIValue();
+ assertTrue("Properties "+pv, (pv instanceof ObjectReference) &&
+ Properties.class.getName().equals(((ClassType) pv.type()).name()));
+ String userHomeProperty = properties.getProperty("user.home");
+ Variable propVar = ((ObjectVariable) propertiesVar).invokeMethod("getProperty",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ new Variable[] { debugger.createMirrorVar("user.home") });
+ Value p = ((JDIVariable) propVar).getJDIValue();
+ assertTrue(p instanceof StringReference);
+ assertEquals(userHomeProperty, ((StringReference) p).value());
+ } finally {
+ support.doFinish ();
+ }
+ }
+}
diff --git a/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MirrorValuesTest.java b/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MirrorValuesTest.java
--- a/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MirrorValuesTest.java
+++ b/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/MirrorValuesTest.java
@@ -41,6 +41,10 @@
*/
package org.netbeans.api.debugger.jpda;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.IntegerValue;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.Value;
import java.awt.Color;
import java.awt.Point;
import java.beans.FeatureDescriptor;
@@ -58,6 +62,7 @@
import junit.framework.Test;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.debugger.jpda.expr.JDIVariable;
import org.openide.util.Exceptions;
/**
@@ -223,6 +228,43 @@
}
+ public void testTargetMirrors() throws Exception {
+ try {
+ Utils.BreakPositions bp = Utils.getBreakPositions(System.getProperty ("test.dir.src") +
+ "org/netbeans/api/debugger/jpda/testapps/MirrorValuesApp.java");
+ LineBreakpoint lb = bp.getLineBreakpoints().get(0);
+ dm.addBreakpoint (lb);
+
+ support = JPDASupport.attach (CLASS_NAME);
+
+ support.waitState (JPDADebugger.STATE_STOPPED); // breakpoint hit
+
+ JPDADebugger debugger = support.getDebugger();
+
+ Variable mirrorVar = debugger.createMirrorVar("Test");
+ Value v = ((JDIVariable) mirrorVar).getJDIValue();
+ assertTrue("Value "+v+" should be a String", v instanceof StringReference);
+ assertEquals("Test", ((StringReference) v).value());
+
+ Point p = new Point(-1, 1);
+ mirrorVar = debugger.createMirrorVar(p);
+ Object mp = mirrorVar.createMirrorObject();
+ assertTrue("Correct point was created: "+mp, p.equals(mp));
+
+ mirrorVar = debugger.createMirrorVar(1);
+ v = ((JDIVariable) mirrorVar).getJDIValue();
+ assertTrue("Value "+v+" should be an Integer object.",
+ (v.type() instanceof ClassType) && Integer.class.getName().equals(((ClassType) v.type()).name()));
+
+ mirrorVar = debugger.createMirrorVar(1, true);
+ v = ((JDIVariable) mirrorVar).getJDIValue();
+ assertTrue("Value "+v+" should be an int.", v instanceof IntegerValue);
+ assertEquals(((IntegerValue) v).value(), 1);
+ } finally {
+ support.doFinish ();
+ }
+ }
+
private static boolean compareArrays(Object arr1, Object arr2) {
if (arr1 instanceof Object[]) {
return Arrays.deepEquals((Object[]) arr1, (Object[]) arr2);