Major merge with Classpath.
Removed many duplicate files. * HACKING: Updated.x * classpath: Imported new directory. * standard.omit: New file. * Makefile.in, aclocal.m4, configure: Rebuilt. * sources.am: New file. * configure.ac: Run Classpath configure script. Moved code around to support. Disable xlib AWT peers (temporarily). * Makefile.am (SUBDIRS): Added 'classpath' (JAVAC): Removed. (AM_CPPFLAGS): Added more -I options. (BOOTCLASSPATH): Simplified. Completely redid how sources are built. Include sources.am. * include/Makefile.am (tool_include__HEADERS): Removed jni.h. * include/jni.h: Removed (in Classpath). * scripts/classes.pl: Updated to look at built classes. * scripts/makemake.tcl: New file. * testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added -I options. (gcj_jni_invocation_compile_c_to_binary): Likewise. From-SVN: r102082
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
/* 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.DataOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* 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 bb holds the data portion of the Command Packet
|
||||
* @param os 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(ByteBuffer bb, DataOutputStream os,
|
||||
byte command)
|
||||
throws JdwpException;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* FieldCommandSet.java -- class to implement the Field Command Set
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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
|
||||
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 gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A class representing the Field Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class FieldCommandSet implements CommandSet
|
||||
{
|
||||
/**
|
||||
* There are no commands for this CommandSet at this time so we just throw a
|
||||
* NotImplementedException whenever it's called.
|
||||
*
|
||||
* @throws JdwpException An exception will always be thrown
|
||||
*/
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"No commands for command set Field implemented.");
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* InterfaceTypeCommandSet.java -- class to implement the InterfaceType
|
||||
Command Set
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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
|
||||
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 gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A class representing the InterfaceType Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class InterfaceTypeCommandSet implements CommandSet
|
||||
{
|
||||
/**
|
||||
* There are no commands for this CommandSet at this time so we just throw a
|
||||
* NotImplementedException whenever it's called.
|
||||
*
|
||||
* @throws JdwpException An exception will always be thrown
|
||||
*/
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"No commands for command set InterfaceType implemented.");
|
||||
}
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
/* ObjectReferenceCommandSet.java -- lass to implement the ObjectReference
|
||||
Command Set
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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
|
||||
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.IVirtualMachine;
|
||||
import gnu.classpath.jdwp.Jdwp;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.exception.InvalidFieldException;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.IdManager;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
import gnu.classpath.jdwp.util.Value;
|
||||
import gnu.classpath.jdwp.util.MethodInvoker;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A class representing the ObjectReference Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class ObjectReferenceCommandSet implements CommandSet
|
||||
{
|
||||
// Our hook into the jvm
|
||||
private final IVirtualMachine vm = Jdwp.getIVirtualMachine();
|
||||
|
||||
// Manages all the different ids that are assigned by jdwp
|
||||
private final IdManager idMan = Jdwp.getIdManager();
|
||||
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case JdwpConstants.CommandSet.ObjectReference.REFERENCE_TYPE:
|
||||
executeReferenceType(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.GET_VALUES:
|
||||
executeGetValues(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.SET_VALUES:
|
||||
executeSetValues(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.MONITOR_INFO:
|
||||
executeMonitorInfo(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.INVOKE_METHOD:
|
||||
executeInvokeMethod(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.DISABLE_COLLECTION:
|
||||
executeDisableCollection(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.ENABLE_COLLECTION:
|
||||
executeEnableCollection(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ObjectReference.IS_COLLECTED:
|
||||
executeIsCollected(bb, os);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("Command " + command +
|
||||
" not found in String Reference Command Set.");
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// The DataOutputStream we're using isn't talking to a socket at all
|
||||
// So if we throw an IOException we're in serious trouble
|
||||
throw new JdwpInternalErrorException(ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeReferenceType(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
Object obj = oid.getObject();
|
||||
Class clazz = obj.getClass();
|
||||
ReferenceTypeId refId = idMan.getReferenceTypeId(clazz);
|
||||
refId.writeTagged(os);
|
||||
}
|
||||
|
||||
private void executeGetValues(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
Object obj = oid.getObject();
|
||||
|
||||
int numFields = bb.getInt();
|
||||
|
||||
os.writeInt(numFields); // Looks pointless but this is the protocol
|
||||
|
||||
for (int i = 0; i < numFields; i++)
|
||||
{
|
||||
Field field = (Field) idMan.readId(bb).getObject();
|
||||
Value.writeValueFromField(os, field, obj);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSetValues(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
Object obj = oid.getObject();
|
||||
|
||||
int numFields = bb.getInt();
|
||||
|
||||
for (int i = 0; i < numFields; i++)
|
||||
{
|
||||
Field field = (Field) idMan.readId(bb).getObject();
|
||||
Object value = Value.getObj(bb, field);
|
||||
try
|
||||
{
|
||||
field.set(obj, value);
|
||||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
// I suppose this would best qualify as an invalid field then
|
||||
throw new InvalidFieldException(ex);
|
||||
}
|
||||
catch (IllegalAccessException ex)
|
||||
{
|
||||
// We should be able to access any field
|
||||
throw new JdwpInternalErrorException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void executeMonitorInfo(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// This command is optional, determined by VirtualMachines CapabilitiesNew
|
||||
// so we'll leave it till later to implement
|
||||
throw new NotImplementedException(
|
||||
"Command ExecuteMonitorInfo not implemented.");
|
||||
|
||||
}
|
||||
|
||||
private void executeInvokeMethod(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
Object obj = oid.getObject();
|
||||
|
||||
ObjectId tid = idMan.readId(bb);
|
||||
Thread thread = (Thread) tid.getObject();
|
||||
|
||||
ReferenceTypeId rid = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = rid.getType();
|
||||
|
||||
ObjectId mid = idMan.readId(bb);
|
||||
Method method = (Method) mid.getObject();
|
||||
|
||||
int args = bb.getInt();
|
||||
Object[] values = new Object[args];
|
||||
|
||||
for (int i = 0; i < args; i++)
|
||||
{
|
||||
values[i] = Value.getObj(bb);
|
||||
}
|
||||
|
||||
int invokeOptions = bb.getInt();
|
||||
|
||||
if ((invokeOptions & JdwpConstants.InvokeOptions.INVOKE_SINGLE_THREADED) != 0)
|
||||
{ // We must suspend all other running threads first
|
||||
vm.suspendAllThreads();
|
||||
}
|
||||
boolean nonVirtual;
|
||||
if ((invokeOptions & JdwpConstants.InvokeOptions.INVOKE_NONVIRTUAL) != 0)
|
||||
nonVirtual = true;
|
||||
else
|
||||
nonVirtual = false;
|
||||
MethodInvoker vmi = new MethodInvoker(vm);
|
||||
|
||||
vmi.executeMethod(obj, thread, clazz, method, values, nonVirtual);
|
||||
Object value = vmi.getReturnedValue();
|
||||
ObjectId exceptionId = vmi.getExceptionId();
|
||||
|
||||
Value.writeValue(os, value);
|
||||
exceptionId.writeTagged(os);
|
||||
}
|
||||
|
||||
private void executeDisableCollection(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
oid.disableCollection();
|
||||
}
|
||||
|
||||
private void executeEnableCollection(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
oid.enableCollection();
|
||||
}
|
||||
|
||||
private void executeIsCollected(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = idMan.readId(bb);
|
||||
boolean collected = oid.isCollected();
|
||||
os.writeBoolean(collected);
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
/* PacketProcessor.java -- a thread which processes command packets
|
||||
from the debugger
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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.Jdwp;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
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.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* This class is responsible for processing packets from the
|
||||
* debugger. It waits for an available packet from the connection
|
||||
* ({@link gnu.classpath.jdwp.transport.JdwpConnection}) and then
|
||||
* processes the packet and any reply.
|
||||
*
|
||||
* @author Keith Seitz (keiths@redhat.com)
|
||||
*/
|
||||
public class PacketProcessor
|
||||
extends Thread
|
||||
{
|
||||
// The connection to the debugger
|
||||
private JdwpConnection _connection;
|
||||
|
||||
// Shutdown this thread?
|
||||
private boolean _shutdown;
|
||||
|
||||
// A Mapping of the command set (Byte) to the specific CommandSet
|
||||
private CommandSet[] _sets;
|
||||
|
||||
// Contents of the ReplyPackets data field
|
||||
private ByteArrayOutputStream _outputBytes;
|
||||
|
||||
// Output stream around _outputBytes
|
||||
private DataOutputStream _os;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>PacketProcessor</code> object
|
||||
* Connection must be validated before getting here!
|
||||
*
|
||||
* @param con the connection
|
||||
*/
|
||||
public PacketProcessor (JdwpConnection con)
|
||||
{
|
||||
_connection = con;
|
||||
_shutdown = false;
|
||||
|
||||
// MAXIMUM is the value of the largest command set we may receive
|
||||
_sets = new CommandSet[JdwpConstants.CommandSet.MAXIMUM + 1];
|
||||
_outputBytes = new ByteArrayOutputStream();
|
||||
_os = new DataOutputStream (_outputBytes);
|
||||
|
||||
// Create all the Command Sets and add them to our array
|
||||
_sets[JdwpConstants.CommandSet.VirtualMachine.CS_VALUE] =
|
||||
new VirtualMachineCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ReferenceType.CS_VALUE] =
|
||||
new ReferenceTypeCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ClassType.CS_VALUE] =
|
||||
new ClassTypeCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ArrayType.CS_VALUE] =
|
||||
new ArrayTypeCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.InterfaceType.CS_VALUE] =
|
||||
new InterfaceTypeCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.Method.CS_VALUE] =
|
||||
new MethodCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.Field.CS_VALUE] =
|
||||
new FieldCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ObjectReference.CS_VALUE] =
|
||||
new ObjectReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.StringReference.CS_VALUE] =
|
||||
new StringReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ThreadReference.CS_VALUE] =
|
||||
new ThreadReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ThreadGroupReference.CS_VALUE] =
|
||||
new ThreadGroupReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ArrayReference.CS_VALUE] =
|
||||
new ArrayReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ClassLoaderReference.CS_VALUE] =
|
||||
new ClassLoaderReferenceCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.EventRequest.CS_VALUE] =
|
||||
new EventRequestCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.StackFrame.CS_VALUE] =
|
||||
new StackFrameCommandSet();
|
||||
_sets[JdwpConstants.CommandSet.ClassObjectReference.CS_VALUE] =
|
||||
new ClassObjectReferenceCommandSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main run routine for this thread. Will loop getting packets
|
||||
* from the connection and processing them.
|
||||
*/
|
||||
public void run ()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!_shutdown)
|
||||
{
|
||||
_processOnePacket ();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
// Time to shutdown, tell Jdwp to shutdown
|
||||
Jdwp.getDefault().shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the packet processor
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
_shutdown = true;
|
||||
interrupt ();
|
||||
}
|
||||
|
||||
// Helper function which actually does all the work of waiting
|
||||
// for a packet and getting it processed.
|
||||
private void _processOnePacket ()
|
||||
throws IOException
|
||||
{
|
||||
JdwpPacket pkt = _connection.getPacket ();
|
||||
|
||||
if (!(pkt instanceof JdwpCommandPacket))
|
||||
{
|
||||
// We're not supposed to get these from the debugger!
|
||||
// Drop it on the floor
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkt != null)
|
||||
{
|
||||
JdwpCommandPacket commandPkt = (JdwpCommandPacket) pkt;
|
||||
JdwpReplyPacket reply = new JdwpReplyPacket(commandPkt);
|
||||
|
||||
// Reset our output stream
|
||||
_outputBytes.reset();
|
||||
|
||||
// Create a ByteBuffer around the command packet
|
||||
ByteBuffer bb = ByteBuffer.wrap(commandPkt.getData());
|
||||
byte command = commandPkt.getCommand();
|
||||
byte commandSet = commandPkt.getCommandSet();
|
||||
|
||||
CommandSet set = null;
|
||||
try
|
||||
{
|
||||
// There is no command set with value 0
|
||||
if (commandSet > 0 && commandSet < _sets.length)
|
||||
{
|
||||
set = _sets[commandPkt.getCommandSet()];
|
||||
}
|
||||
if (set != null)
|
||||
{
|
||||
_shutdown = set.runCommand(bb, _os, command);
|
||||
reply.setData(_outputBytes.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
/* ReferenceTypeCommandSet.java -- lass to implement the ReferenceType
|
||||
Command Set
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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
|
||||
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.IVirtualMachine;
|
||||
import gnu.classpath.jdwp.Jdwp;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.exception.InvalidFieldException;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.IdManager;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
import gnu.classpath.jdwp.util.JdwpString;
|
||||
import gnu.classpath.jdwp.util.Signature;
|
||||
import gnu.classpath.jdwp.util.Value;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A class representing the ReferenceType Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class ReferenceTypeCommandSet implements CommandSet
|
||||
{
|
||||
// Our hook into the jvm
|
||||
private final IVirtualMachine vm = Jdwp.getIVirtualMachine();
|
||||
|
||||
// Manages all the different ids that are assigned by jdwp
|
||||
private final IdManager idMan = Jdwp.getIdManager();
|
||||
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case JdwpConstants.CommandSet.ReferenceType.SIGNATURE:
|
||||
executeSignature(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.CLASS_LOADER:
|
||||
executeClassLoader(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.MODIFIERS:
|
||||
executeModifiers(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.FIELDS:
|
||||
executeFields(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.METHODS:
|
||||
executeMethods(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.GET_VALUES:
|
||||
executeGetValues(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.SOURCE_FILE:
|
||||
executeSourceFile(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.NESTED_TYPES:
|
||||
executeNestedTypes(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.STATUS:
|
||||
executeStatus(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.INTERFACES:
|
||||
executeInterfaces(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.CLASS_OBJECT:
|
||||
executeClassObject(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.SOURCE_DEBUG_EXTENSION:
|
||||
executeSourceDebugExtension(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.SIGNATURE_WITH_GENERIC:
|
||||
executeSignatureWithGeneric(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.FIELDS_WITH_GENERIC:
|
||||
executeFieldWithGeneric(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.ReferenceType.METHODS_WITH_GENERIC:
|
||||
executeMethodsWithGeneric(bb, os);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("Command " + command +
|
||||
" not found in String Reference Command Set.");
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// The DataOutputStream we're using isn't talking to a socket at all
|
||||
// So if we throw an IOException we're in serious trouble
|
||||
throw new JdwpInternalErrorException(ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeSignature(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
String sig = Signature.computeClassSignature(refId.getType());
|
||||
JdwpString.writeString(os, sig);
|
||||
}
|
||||
|
||||
private void executeClassLoader(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
|
||||
Class clazz = refId.getType();
|
||||
ClassLoader loader = clazz.getClassLoader();
|
||||
ObjectId oid = idMan.getId(loader);
|
||||
oid.write(os);
|
||||
}
|
||||
|
||||
private void executeModifiers(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
|
||||
Class clazz = refId.getType();
|
||||
os.writeInt(clazz.getModifiers());
|
||||
}
|
||||
|
||||
private void executeFields(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
Field[] fields = clazz.getFields();
|
||||
os.writeInt(fields.length);
|
||||
for (int i = 0; i < fields.length; i++)
|
||||
{
|
||||
Field field = fields[i];
|
||||
idMan.getId(field).write(os);
|
||||
JdwpString.writeString(os, field.getName());
|
||||
JdwpString.writeString(os, Signature.computeFieldSignature(field));
|
||||
os.writeInt(field.getModifiers());
|
||||
}
|
||||
}
|
||||
|
||||
private void executeMethods(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
Method[] methods = clazz.getMethods();
|
||||
os.writeInt(methods.length);
|
||||
for (int i = 0; i < methods.length; i++)
|
||||
{
|
||||
Method method = methods[i];
|
||||
idMan.getId(method).write(os);
|
||||
JdwpString.writeString(os, method.getName());
|
||||
JdwpString.writeString(os, Signature.computeMethodSignature(method));
|
||||
os.writeInt(method.getModifiers());
|
||||
}
|
||||
}
|
||||
|
||||
private void executeGetValues(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
int numFields = bb.getInt();
|
||||
os.writeInt(numFields); // Looks pointless but this is the protocol
|
||||
for (int i = 0; i < numFields; i++)
|
||||
{
|
||||
ObjectId fieldId = idMan.readId(bb);
|
||||
Field field = (Field) (fieldId.getObject());
|
||||
Class fieldClazz = field.getDeclaringClass();
|
||||
|
||||
// We don't actually need the clazz to get the field but we might as
|
||||
// well check that the debugger got it right
|
||||
if (fieldClazz.isAssignableFrom(clazz))
|
||||
Value.writeStaticValueFromField(os, field);
|
||||
else
|
||||
throw new InvalidFieldException(fieldId.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSourceFile(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
// We'll need to go into the jvm for this unless there's an easier way
|
||||
String sourceFileName = vm.getSourceFile(clazz);
|
||||
JdwpString.writeString(os, sourceFileName);
|
||||
// clazz.getProtectionDomain().getCodeSource().getLocation();
|
||||
}
|
||||
|
||||
private void executeNestedTypes(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
Class[] declaredClazzes = clazz.getDeclaredClasses();
|
||||
os.writeInt(declaredClazzes.length);
|
||||
for (int i = 0; i < declaredClazzes.length; i++)
|
||||
{
|
||||
Class decClazz = declaredClazzes[i];
|
||||
ReferenceTypeId clazzId = idMan.getReferenceTypeId(decClazz);
|
||||
clazzId.writeTagged(os);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeStatus(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
// I don't think there's any other way to get this
|
||||
int status = vm.getStatus(clazz);
|
||||
os.writeInt(status);
|
||||
}
|
||||
|
||||
private void executeInterfaces(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
Class[] interfaces = clazz.getInterfaces();
|
||||
os.writeInt(interfaces.length);
|
||||
for (int i = 0; i < interfaces.length; i++)
|
||||
{
|
||||
Class interfaceClass = interfaces[i];
|
||||
ReferenceTypeId intId = idMan.getReferenceTypeId(interfaceClass);
|
||||
intId.write(os);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeClassObject(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
ObjectId clazzObjectId = idMan.getId(clazz);
|
||||
clazzObjectId.write(os);
|
||||
}
|
||||
|
||||
private void executeSourceDebugExtension(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// This command is optional, determined by VirtualMachines CapabilitiesNew
|
||||
// so we'll leave it till later to implement
|
||||
throw new NotImplementedException(
|
||||
"Command SourceDebugExtension not implemented.");
|
||||
}
|
||||
|
||||
private void executeSignatureWithGeneric(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// We don't have generics yet
|
||||
throw new NotImplementedException(
|
||||
"Command SourceDebugExtension not implemented.");
|
||||
}
|
||||
|
||||
private void executeFieldWithGeneric(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// We don't have generics yet
|
||||
throw new NotImplementedException(
|
||||
"Command SourceDebugExtension not implemented.");
|
||||
}
|
||||
|
||||
private void executeMethodsWithGeneric(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// We don't have generics yet
|
||||
throw new NotImplementedException(
|
||||
"Command SourceDebugExtension not implemented.");
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/* StringReferenceCommandSet.java -- class to implement the StringReference
|
||||
Command Set
|
||||
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.Jdwp;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.util.JdwpString;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A class representing the StringReference Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class StringReferenceCommandSet implements CommandSet
|
||||
{
|
||||
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
// Although there's only a single command to choose from we still use
|
||||
// a switch to maintain consistency with the rest of the CommandSets
|
||||
switch (command)
|
||||
{
|
||||
case JdwpConstants.CommandSet.StringReference.VALUE:
|
||||
executeValue(bb, os);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("Command " + command +
|
||||
" not found in String Reference Command Set.");
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// The DataOutputStream we're using isn't talking to a socket at all
|
||||
// So if we throw an IOException we're in serious trouble
|
||||
throw new JdwpInternalErrorException(ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeValue(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = Jdwp.getIdManager().readId(bb);
|
||||
|
||||
String str = (String) oid.getObject();
|
||||
JdwpString.writeString(os, str);
|
||||
}
|
||||
}
|
||||
@@ -1,474 +0,0 @@
|
||||
/* VirtualMachineCommandSet.java -- class to implement the VirtualMachine
|
||||
Command Set
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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
|
||||
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.IVirtualMachine;
|
||||
import gnu.classpath.jdwp.Jdwp;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.IdManager;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
import gnu.classpath.jdwp.util.JdwpString;
|
||||
import gnu.classpath.jdwp.util.Signature;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A class representing the VirtualMachine Command Set.
|
||||
*
|
||||
* @author Aaron Luchko <aluchko@redhat.com>
|
||||
*/
|
||||
public class VirtualMachineCommandSet implements CommandSet
|
||||
{
|
||||
// Our hook into the jvm
|
||||
private final IVirtualMachine vm = Jdwp.getIVirtualMachine();
|
||||
|
||||
// Manages all the different ids that are assigned by jdwp
|
||||
private final IdManager idMan = Jdwp.getIdManager();
|
||||
|
||||
// The Jdwp object
|
||||
private final Jdwp jdwp = Jdwp.getDefault();
|
||||
|
||||
public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
|
||||
throws JdwpException
|
||||
{
|
||||
boolean keepRunning = true;
|
||||
try
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case JdwpConstants.CommandSet.VirtualMachine.VERSION:
|
||||
executeVersion(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.CLASSES_BY_SIGNATURE:
|
||||
executeClassesBySignature(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.ALL_CLASSES:
|
||||
executeAllClasses(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.ALL_THREADS:
|
||||
executeAllThreads(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.TOP_LEVEL_THREAD_GROUPS:
|
||||
executeTopLevelThreadGroups(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.IDSIZES:
|
||||
executeIDsizes(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.DISPOSE:
|
||||
keepRunning = false;
|
||||
executeDispose(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.SUSPEND:
|
||||
executeSuspend(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.RESUME:
|
||||
executeResume(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.EXIT:
|
||||
keepRunning = false;
|
||||
executeExit(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.CREATE_STRING:
|
||||
executeCreateString(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.CAPABILITIES:
|
||||
executeCapabilities(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.CLASS_PATHS:
|
||||
executeClassPaths(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.DISPOSE_OBJECTS:
|
||||
executeDisposeObjects(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.HOLD_EVENTS:
|
||||
executeHoldEvents(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.RELEASE_EVENTS:
|
||||
executeReleaseEvents(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.CAPABILITIES_NEW:
|
||||
executeCapabilitiesNew(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.REDEFINE_CLASSES:
|
||||
executeRedefineClasses(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.SET_DEFAULT_STRATUM:
|
||||
executeSetDefaultStratum(bb, os);
|
||||
break;
|
||||
case JdwpConstants.CommandSet.VirtualMachine.ALL_CLASSES_WITH_GENERIC:
|
||||
executeAllClassesWithGeneric(bb, os);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// The DataOutputStream we're using isn't talking to a socket at all
|
||||
// So if we throw an IOException we're in serious trouble
|
||||
throw new JdwpInternalErrorException(ex);
|
||||
}
|
||||
return keepRunning;
|
||||
}
|
||||
|
||||
private void executeVersion(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
|
||||
Properties props = System.getProperties();
|
||||
|
||||
int jdwpMajor = JdwpConstants.Version.MAJOR;
|
||||
int jdwpMinor = JdwpConstants.Version.MINOR;
|
||||
// The description field is pretty loosely defined
|
||||
String description = "JDWP version " + jdwpMajor + "." + jdwpMinor
|
||||
+ ", JVM version " + props.getProperty("java.vm.name")
|
||||
+ " " + props.getProperty("java.vm.version") + " "
|
||||
+ props.getProperty("java.version");
|
||||
String vmVersion = props.getProperty("java.version");
|
||||
String vmName = props.getProperty("java.vm.name");
|
||||
JdwpString.writeString(os, description);
|
||||
os.write(jdwpMajor);
|
||||
os.write(jdwpMinor);
|
||||
JdwpString.writeString(os, vmName);
|
||||
JdwpString.writeString(os, vmVersion);
|
||||
}
|
||||
|
||||
private void executeClassesBySignature(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
String sig = JdwpString.readString(bb);
|
||||
ArrayList allMatchingClasses = new ArrayList();
|
||||
|
||||
// This will be an Iterator over all loaded Classes
|
||||
Iterator iter = vm.getAllLoadedClasses();
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Class clazz = (Class) iter.next();
|
||||
String clazzSig = Signature.computeClassSignature(clazz);
|
||||
if (clazzSig.equals(sig))
|
||||
allMatchingClasses.add(clazz);
|
||||
}
|
||||
|
||||
os.writeInt(allMatchingClasses.size());
|
||||
for (int i = 0; i < allMatchingClasses.size(); i++)
|
||||
{
|
||||
Class clazz = (Class) allMatchingClasses.get(i);
|
||||
ReferenceTypeId id = idMan.getReferenceTypeId(clazz);
|
||||
id.writeTagged(os);
|
||||
int status = vm.getStatus(clazz);
|
||||
os.writeInt(status);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeAllClasses(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// Disable garbage collection while we're collecting the info on loaded
|
||||
// classes so we some classes don't get collected between the time we get
|
||||
// the count and the time we get the list
|
||||
vm.disableGarbageCollection();
|
||||
|
||||
int classCount = vm.getAllLoadedClassesCount();
|
||||
os.writeInt(classCount);
|
||||
|
||||
// This will be an Iterator over all loaded Classes
|
||||
Iterator iter = vm.getAllLoadedClasses();
|
||||
vm.enableGarbageCollection();
|
||||
int count = 0;
|
||||
|
||||
// Note it's possible classes were created since out classCount so make
|
||||
// sure we don't write more classes than we told the debugger
|
||||
while (iter.hasNext() && count++ < classCount)
|
||||
{
|
||||
Class clazz = (Class) iter.next();
|
||||
ReferenceTypeId id = idMan.getReferenceTypeId(clazz);
|
||||
id.writeTagged(os);
|
||||
String sig = Signature.computeClassSignature(clazz);
|
||||
JdwpString.writeString(os, sig);
|
||||
int status = vm.getStatus(clazz);
|
||||
os.writeInt(status);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeAllThreads(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ThreadGroup jdwpGroup = Thread.currentThread().getThreadGroup();
|
||||
ThreadGroup root = getRootThreadGroup(jdwpGroup);
|
||||
|
||||
int numThreads = root.activeCount();
|
||||
Thread allThreads[] = new Thread[numThreads];
|
||||
root.enumerate(allThreads, true);
|
||||
|
||||
// We need to loop through for the true count since some threads may have
|
||||
// been destroyed since we got
|
||||
// activeCount so those spots in the array will be null. As well we must
|
||||
// ignore any threads that belong to jdwp
|
||||
numThreads = 0;
|
||||
for (int i = 0; i < allThreads.length; i++)
|
||||
{
|
||||
Thread thread = allThreads[i];
|
||||
if (thread == null)
|
||||
break; // No threads after this point
|
||||
if (!thread.getThreadGroup().equals(jdwpGroup))
|
||||
numThreads++;
|
||||
}
|
||||
|
||||
os.writeInt(numThreads);
|
||||
|
||||
for (int i = 0; i < allThreads.length; i++)
|
||||
{
|
||||
Thread thread = allThreads[i];
|
||||
if (thread == null)
|
||||
break; // No threads after this point
|
||||
if (!thread.getThreadGroup().equals(jdwpGroup))
|
||||
idMan.getId(thread).write(os);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeTopLevelThreadGroups(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ThreadGroup jdwpGroup = jdwp.getJdwpThreadGroup();
|
||||
ThreadGroup root = getRootThreadGroup(jdwpGroup);
|
||||
|
||||
os.writeInt(1); // Just one top level group allowed?
|
||||
idMan.getId(root);
|
||||
}
|
||||
|
||||
private void executeDispose(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// resumeAllThreads isn't sufficient as a thread may have been
|
||||
// suspended multiple times, we likely need a way to keep track of how many
|
||||
// times a thread has been suspended or else a stronger resume method for
|
||||
// this purpose
|
||||
// vm.resumeAllThreadsExcept(jdwp.getJdwpThreadGroup());
|
||||
|
||||
// Simply shutting down the jdwp layer will take care of the rest of the
|
||||
// shutdown other than disabling debugging in the VM
|
||||
// vm.disableDebugging();
|
||||
|
||||
// Don't implement this until we're sure how to remove all the debugging
|
||||
// effects from the VM.
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.Dispose not implemented");
|
||||
|
||||
}
|
||||
|
||||
private void executeIDsizes(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ObjectId oid = new ObjectId();
|
||||
os.writeInt(oid.size()); // fieldId
|
||||
os.writeInt(oid.size()); // methodId
|
||||
os.writeInt(oid.size()); // objectId
|
||||
os.writeInt(new ReferenceTypeId((byte) 0x00).size()); // referenceTypeId
|
||||
os.writeInt(oid.size()); // frameId
|
||||
}
|
||||
|
||||
private void executeSuspend(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
vm.suspendAllThreadsExcept(jdwp.getJdwpThreadGroup());
|
||||
}
|
||||
|
||||
private void executeResume(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
vm.resumeAllThreadsExcept(jdwp.getJdwpThreadGroup());
|
||||
}
|
||||
|
||||
private void executeExit(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
int exitCode = bb.getInt();
|
||||
jdwp.setExit(exitCode);
|
||||
}
|
||||
|
||||
private void executeCreateString(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
String string = JdwpString.readString(bb);
|
||||
ObjectId stringId = Jdwp.getIdManager().getId(string);
|
||||
|
||||
// Since this string isn't referenced anywhere we'll disable garbage
|
||||
// collection on it so it's still around when the debugger gets back to it.
|
||||
stringId.disableCollection();
|
||||
stringId.write(os);
|
||||
}
|
||||
|
||||
private void executeCapabilities(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// Store these somewhere?
|
||||
os.writeBoolean(false); // canWatchFieldModification
|
||||
os.writeBoolean(false); // canWatchFieldAccess
|
||||
os.writeBoolean(false); // canGetBytecodes
|
||||
os.writeBoolean(false); // canGetSyntheticAttribute
|
||||
os.writeBoolean(false); // canGetOwnedMonitorInfo
|
||||
os.writeBoolean(false); // canGetCurrentContendedMonitor
|
||||
os.writeBoolean(false); // canGetMonitorInfo
|
||||
}
|
||||
|
||||
private void executeClassPaths(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
String baseDir = System.getProperty("user.dir");
|
||||
JdwpString.writeString(os, baseDir);
|
||||
|
||||
// Find and write the classpath
|
||||
String classPath = System.getProperty("java.class.path");
|
||||
String[] paths = classPath.split(":");
|
||||
|
||||
os.writeInt(paths.length);
|
||||
for (int i = 0; i < paths.length; i++)
|
||||
JdwpString.writeString(os, paths[i]);
|
||||
|
||||
// Now the bootpath
|
||||
String bootPath = System.getProperty("sun.boot.class.path");
|
||||
paths = bootPath.split(":");
|
||||
os.writeInt(paths.length);
|
||||
for (int i = 0; i < paths.length; i++)
|
||||
JdwpString.writeString(os, paths[i]);
|
||||
}
|
||||
|
||||
private void executeDisposeObjects(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// Instead of going through the list of objects they give us it's probably
|
||||
// better just to find the garbage collected objects ourselves
|
||||
idMan.update();
|
||||
}
|
||||
|
||||
private void executeHoldEvents(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// Going to have to implement a send queue somewhere and do this without
|
||||
// triggering events
|
||||
// Until then just don't implement
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.HoldEvents not implemented");
|
||||
}
|
||||
|
||||
// Opposite of executeHoldEvents
|
||||
private void executeReleaseEvents(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.ReleaseEvents not implemented");
|
||||
}
|
||||
|
||||
private void executeCapabilitiesNew(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
// Store these somewhere?
|
||||
final int CAPABILITIES_NEW_SIZE = 32;
|
||||
os.writeBoolean(false); // canWatchFieldModification
|
||||
os.writeBoolean(false); // canWatchFieldAccess
|
||||
os.writeBoolean(false); // canGetBytecodes
|
||||
os.writeBoolean(false); // canGetSyntheticAttribute
|
||||
os.writeBoolean(false); // canGetOwnedMonitorInfo
|
||||
os.writeBoolean(false); // canGetCurrentContendedMonitor
|
||||
os.writeBoolean(false); // canGetMonitorInfo
|
||||
os.writeBoolean(false); // canRedefineClasses
|
||||
os.writeBoolean(false); // canAddMethod
|
||||
os.writeBoolean(false); // canUnrestrictedlyRedefineClasses
|
||||
os.writeBoolean(false); // canPopFrames
|
||||
os.writeBoolean(false); // canUseInstanceFilters
|
||||
os.writeBoolean(false); // canGetSourceDebugExtension
|
||||
os.writeBoolean(false); // canRequestVMDeathEvent
|
||||
os.writeBoolean(false); // canSetDefaultStratum
|
||||
for (int i = 15; i < CAPABILITIES_NEW_SIZE; i++)
|
||||
// Future capabilities
|
||||
// currently unused
|
||||
os.writeBoolean(false); // Set to false
|
||||
}
|
||||
|
||||
private void executeRedefineClasses(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// Optional command, don't implement
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.RedefineClasses not implemented");
|
||||
}
|
||||
|
||||
private void executeSetDefaultStratum(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// Optional command, don't implement
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.SetDefaultStratum not implemented");
|
||||
}
|
||||
|
||||
private void executeAllClassesWithGeneric(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException
|
||||
{
|
||||
// We don't handle generics
|
||||
throw new NotImplementedException(
|
||||
"Command VirtualMachine.AllClassesWithGeneric not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the root ThreadGroup of this ThreadGroup
|
||||
*/
|
||||
private ThreadGroup getRootThreadGroup(ThreadGroup group)
|
||||
{
|
||||
ThreadGroup parent = group.getParent();
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
group = parent;
|
||||
parent = group.getParent();
|
||||
}
|
||||
return group; // This group was the root
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user