This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[RFA/JDWP] CommandSet interface and PacketProcessor
- From: Aaron Luchko <aluchko at redhat dot com>
- To: GCJ Patches <java-patches at gcc dot gnu dot org>
- Cc: classpath patches <classpath-patches at gnu dot org>
- Date: Wed, 22 Jun 2005 15:02:41 -0400
- Subject: [RFA/JDWP] CommandSet interface and PacketProcessor
Hello, I've been working with Keith Seitz to help with jdwp. This patch
adds the functionality for PacketProcessor to act on a given packet from
the debugger via CommandSet objects along with the CommandSet interface.
I've left the commented out list of different CommandSets added to the
HashTable in the constructor to demonstrate how they will be stored.
The CommandSet objects will carry out all the work associated with a
given command (ie finding values of variables, setting event requests)
then write the data for the response to the output stream.
The reason for runCommand returning a boolean to indicate a transport
layer shutdown is the commands
http://java.sun.com/j2se/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Dispose
and
http://java.sun.com/j2se/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Exit
require the transport layer to be shutdown and a reply packet to still
be sent. After receiving sending the shutdown reply packet it will first
shutdown the transport layer, and then its own thread. At this point the
intent is that the appropriate CommandSet will take care of all the
other associated actions such as canceling event requests and shutting
down other threads in the VM.
Questions or Comments?
Aaron
ChangeLog
2005-06-22 Aaron Luchko <aluchko@redhat.com>
* gnu/classpath/jdwp/processor/CommandSet.java: New file.
* gnu/classpath/jdwp/processor/PacketProcessor.java: Use CommandSets to
handle JdwpCommandPackets.
--- /dev/null 2005-06-09 16:29:11.371620296 -0400
+++ gnu/classpath/jdwp/processor/CommandSet.java 2005-06-22 13:46:00.000000000 -0400
@@ -0,0 +1,73 @@
+/* CommandSet.java -- An interface defining JDWP Command Sets
+ Copyright (C) 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.classpath.jdwp.processor;
+
+import gnu.classpath.jdwp.exception.JdwpException;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * A class representing a JDWP Command Set. This class serves as a generic
+ * interface for all Command Sets types used by JDWP.
+ *
+ * @author Aaron Luchko <aluchko@redhat.com>
+ */
+public interface CommandSet
+{
+ /**
+ * Runs the given command with the data in distr and writes the data for the
+ * reply packet to ostr.
+ *
+ * @param distr holds the data portion of the Command Packet
+ * @param ostr data portion of the Reply Packet will be written here
+ * @param command the command field of the Command Packet
+ * @return true if the JDWP layer should shut down in response to this packet
+ * @throws JdwpException command wasn't carried out successfully
+ */
+ public boolean runCommand(DataInputStream distr, DataOutputStream ostr,
+ byte command)
+ throws JdwpException;
+
+ /**
+ * Get the Byte which identifies this CommandSet.
+ */
+ public Byte getCommandSet();
+}
Index: gnu/classpath/jdwp/processor/PacketProcessor.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/classpath/jdwp/processor/PacketProcessor.java,v
retrieving revision 1.1
diff -u -p -r1.1 PacketProcessor.java
--- gnu/classpath/jdwp/processor/PacketProcessor.java 15 Jun 2005 03:10:31 -0000 1.1
+++ gnu/classpath/jdwp/processor/PacketProcessor.java 22 Jun 2005 18:51:47 -0000
@@ -40,15 +40,19 @@ exception statement from your version. *
package gnu.classpath.jdwp.processor;
-import gnu.classpath.jdwp.Jdwp;
-import gnu.classpath.jdwp.event.Event;
+import gnu.classpath.jdwp.JdwpConstants;
import gnu.classpath.jdwp.exception.JdwpException;
-import gnu.classpath.jdwp.transport.JdwpConnection;
import gnu.classpath.jdwp.transport.JdwpCommandPacket;
+import gnu.classpath.jdwp.transport.JdwpConnection;
import gnu.classpath.jdwp.transport.JdwpPacket;
import gnu.classpath.jdwp.transport.JdwpReplyPacket;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.IOException;
+import java.util.Hashtable;
/**
* This class is responsible for processing packets from the
@@ -66,7 +70,10 @@ public class PacketProcessor
// Shutdown this thread?
private boolean _shutdown;
-
+
+ // A Mapping of the command set (Byte) to the specific CommandSet
+ private Hashtable _sets;
+
/**
* Constructs a new <code>PacketProcessor</code> object
* Connection must be validated before getting here!
@@ -77,8 +84,43 @@ public class PacketProcessor
{
_connection = con;
_shutdown = false;
+ _sets = new Hashtable();
+ CommandSet set;
+ // Create all the Command Sets and add them to our hashtable
+// set = new ArrayReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ArrayTypeCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ClassLoaderReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ClassObjectReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ClassTypeCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new EventRequestCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new FieldCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new InterfaceTypeCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new MethodCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ObjectReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ReferenceTypeCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new StackFrameCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new StringReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ThreadGroupReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new ThreadReferenceCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
+// set = new VirtualMachineCommandSet(con);
+// _sets.put(set.getCommandSet(), set);
}
-
+
/**
* Main run routine for this thread. Will loop getting packets
* from the connection and processing them.
@@ -87,10 +129,12 @@ public class PacketProcessor
{
while (!_shutdown)
{
- _processOnePacket ();
+ _processOnePacket ();
}
+ // Time to shutdown, tell the _connection thread to stop reading
+ _connection.shutdown();
}
-
+
/**
* Shutdown the packet processor
*/
@@ -99,40 +143,56 @@ public class PacketProcessor
_shutdown = true;
interrupt ();
}
-
+
// Helper function which actually does all the work of waiting
// for a packet and getting it processed.
private void _processOnePacket ()
{
JdwpPacket pkt = _connection.getPacket ();
- if (pkt instanceof JdwpReplyPacket)
+
+ if (!(pkt instanceof JdwpCommandPacket))
{
- // We're not supposed to get these from the debugger!
- // Drop it on the floor
- return;
+ // We're not supposed to get these from the debugger!
+ // Drop it on the floor
+ return;
}
-
+
if (pkt != null)
{
- JdwpReplyPacket reply;
- try
- {
- // !! process packet here !!
- reply = new JdwpReplyPacket (pkt, (short) 0);
- }
- catch (JdwpException ex)
- {
- reply = new JdwpReplyPacket (pkt, ex.getErrorCode ());
- }
-
- try
- {
- _connection.sendPacket (reply);
- }
- catch (IOException ioe)
- {
- // Not much we can do...
- }
+ JdwpCommandPacket commandPkt = (JdwpCommandPacket) pkt;
+ JdwpReplyPacket reply = new JdwpReplyPacket(commandPkt, (short)0);
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ DataOutputStream ostr = new DataOutputStream (bytes);
+ DataInputStream distr = new DataInputStream(new ByteArrayInputStream(commandPkt.getData()));
+ byte command = commandPkt.getCommand();
+ CommandSet set = (CommandSet)_sets.get(new Byte(commandPkt.getCommandSet()));
+
+ try
+ {
+ try
+ {
+ if (set != null)
+ {
+ _shutdown = set.runCommand(distr, ostr, command);
+ reply.setData(bytes.toByteArray());
+ }
+ else
+ {
+ // This command set wasn't in our tree
+ reply.setErrorCode(JdwpConstants.Error.NOT_IMPLEMENTED);
+ }
+ }
+ catch (JdwpException ex)
+ {
+ reply.setErrorCode(ex.getErrorCode ());
+ }
+ _connection.sendPacket (reply);
+ }
+ catch (IOException ioe)
+ {
+ // Not much we can do...
+ }
}
}
}