Source for gnu.classpath.jdwp.processor.PacketProcessor

   1: /* PacketProcessor.java -- a thread which processes command packets
   2:    from the debugger
   3:    Copyright (C) 2005, 2006 Free Software Foundation
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: terms of your choice, provided that you also meet, for each linked
  33: independent module, the terms and conditions of the license of that
  34: module.  An independent module is a module which is not derived from
  35: or based on this library.  If you modify this library, you may extend
  36: this exception to your version of the library, but you are not
  37: obligated to do so.  If you do not wish to do so, delete this
  38: exception statement from your version. */
  39: 
  40: 
  41: package gnu.classpath.jdwp.processor;
  42: 
  43: import gnu.classpath.jdwp.Jdwp;
  44: import gnu.classpath.jdwp.JdwpConstants;
  45: import gnu.classpath.jdwp.exception.JdwpException;
  46: import gnu.classpath.jdwp.transport.JdwpCommandPacket;
  47: import gnu.classpath.jdwp.transport.JdwpConnection;
  48: import gnu.classpath.jdwp.transport.JdwpPacket;
  49: import gnu.classpath.jdwp.transport.JdwpReplyPacket;
  50: 
  51: import java.io.ByteArrayOutputStream;
  52: import java.io.DataOutputStream;
  53: import java.io.IOException;
  54: import java.nio.ByteBuffer;
  55: import java.security.PrivilegedAction;
  56: 
  57: /**
  58:  * This class is responsible for processing packets from the
  59:  * debugger. It waits for an available packet from the connection
  60:  * ({@link gnu.classpath.jdwp.transport.JdwpConnection}) and then
  61:  * processes the packet and any reply.
  62:  *
  63:  * @author Keith Seitz (keiths@redhat.com)
  64:  */
  65: public class PacketProcessor
  66:   implements PrivilegedAction
  67: {
  68:   // The connection to the debugger
  69:   private JdwpConnection _connection;
  70: 
  71:   // Shutdown this thread?
  72:   private boolean _shutdown;
  73: 
  74:   // A Mapping of the command set (Byte) to the specific CommandSet
  75:   private CommandSet[] _sets;
  76: 
  77:   // Contents of the ReplyPackets data field
  78:   private ByteArrayOutputStream _outputBytes;
  79: 
  80:   // Output stream around _outputBytes
  81:   private DataOutputStream _os;
  82: 
  83:   /**
  84:    * Constructs a new <code>PacketProcessor</code> object
  85:    * Connection must be validated before getting here!
  86:    *
  87:    * @param con  the connection
  88:    */
  89:   public PacketProcessor (JdwpConnection con)
  90:   {
  91:     _connection = con;
  92:     _shutdown = false;
  93: 
  94:     // MAXIMUM is the value of the largest command set we may receive
  95:     _sets = new CommandSet[JdwpConstants.CommandSet.MAXIMUM + 1];
  96:     _outputBytes = new ByteArrayOutputStream();
  97:     _os = new DataOutputStream (_outputBytes);
  98: 
  99:     // Create all the Command Sets and add them to our array
 100:     _sets[JdwpConstants.CommandSet.VirtualMachine.CS_VALUE] =
 101:       new VirtualMachineCommandSet();
 102:     _sets[JdwpConstants.CommandSet.ReferenceType.CS_VALUE] =
 103:       new ReferenceTypeCommandSet();
 104:     _sets[JdwpConstants.CommandSet.ClassType.CS_VALUE] =
 105:       new ClassTypeCommandSet();
 106:     _sets[JdwpConstants.CommandSet.ArrayType.CS_VALUE] =
 107:       new ArrayTypeCommandSet();
 108:     _sets[JdwpConstants.CommandSet.InterfaceType.CS_VALUE] =
 109:       new InterfaceTypeCommandSet();
 110:     _sets[JdwpConstants.CommandSet.Method.CS_VALUE] =
 111:       new MethodCommandSet();
 112:     _sets[JdwpConstants.CommandSet.Field.CS_VALUE] =
 113:       new FieldCommandSet();
 114:     _sets[JdwpConstants.CommandSet.ObjectReference.CS_VALUE] =
 115:       new ObjectReferenceCommandSet();
 116:     _sets[JdwpConstants.CommandSet.StringReference.CS_VALUE] =
 117:       new StringReferenceCommandSet();
 118:     _sets[JdwpConstants.CommandSet.ThreadReference.CS_VALUE] =
 119:       new ThreadReferenceCommandSet();
 120:     _sets[JdwpConstants.CommandSet.ThreadGroupReference.CS_VALUE] =
 121:       new ThreadGroupReferenceCommandSet();
 122:     _sets[JdwpConstants.CommandSet.ArrayReference.CS_VALUE] =
 123:       new ArrayReferenceCommandSet();
 124:     _sets[JdwpConstants.CommandSet.ClassLoaderReference.CS_VALUE] =
 125:       new ClassLoaderReferenceCommandSet();
 126:     _sets[JdwpConstants.CommandSet.EventRequest.CS_VALUE] =
 127:       new EventRequestCommandSet();
 128:     _sets[JdwpConstants.CommandSet.StackFrame.CS_VALUE] =
 129:       new StackFrameCommandSet();
 130:     _sets[JdwpConstants.CommandSet.ClassObjectReference.CS_VALUE] =
 131:       new ClassObjectReferenceCommandSet();
 132:   }
 133: 
 134:   /**
 135:    * Main run routine for this thread. Will loop getting packets
 136:    * from the connection and processing them.
 137:    */
 138:   public Object run ()
 139:   {
 140:     // Notify initialization thread (gnu.classpath.jdwp.Jdwp) that
 141:     // the PacketProcessor thread is ready.
 142:     Jdwp.getDefault().subcomponentInitialized ();
 143: 
 144:     try
 145:       {
 146:         while (!_shutdown)
 147:           {
 148:             _processOnePacket ();
 149:           }
 150:       }
 151:     catch (Exception ex)
 152:       {
 153:         ex.printStackTrace();
 154:       }
 155:     // Time to shutdown, tell Jdwp to shutdown
 156:     Jdwp.getDefault().shutdown();
 157:     return null;
 158:   }
 159: 
 160:   /**
 161:    * Shutdown the packet processor
 162:    */
 163:   public void shutdown ()
 164:   {
 165:     _shutdown = true;
 166:   }
 167: 
 168:   // Helper function which actually does all the work of waiting
 169:   // for a packet and getting it processed.
 170:   private void _processOnePacket ()
 171:     throws IOException
 172:   {
 173:     JdwpPacket pkt = _connection.getPacket ();
 174: 
 175:     if (!(pkt instanceof JdwpCommandPacket))
 176:       {
 177:         // We're not supposed to get these from the debugger!
 178:         // Drop it on the floor
 179:         return;
 180:       }
 181: 
 182:     if (pkt != null)
 183:       {
 184:         JdwpCommandPacket commandPkt = (JdwpCommandPacket) pkt;
 185:         JdwpReplyPacket reply = new JdwpReplyPacket(commandPkt);
 186: 
 187:         // Reset our output stream
 188:         _outputBytes.reset();
 189: 
 190:         // Create a ByteBuffer around the command packet
 191:         ByteBuffer bb = ByteBuffer.wrap(commandPkt.getData());
 192:         byte command = commandPkt.getCommand();
 193:         byte commandSet = commandPkt.getCommandSet();
 194: 
 195:         CommandSet set = null;
 196:         try
 197:           {
 198:             // There is no command set with value 0
 199:             if (commandSet > 0 && commandSet < _sets.length)
 200:               {
 201:                 set = _sets[commandPkt.getCommandSet()];
 202:               }
 203:             if (set != null)
 204:               {
 205:                 _shutdown = set.runCommand(bb, _os, command);
 206:                 reply.setData(_outputBytes.toByteArray());
 207:               }
 208:             else
 209:               {
 210:                 // This command set wasn't in our tree
 211:                 reply.setErrorCode(JdwpConstants.Error.NOT_IMPLEMENTED);
 212:               }
 213:           }
 214:           catch (JdwpException ex)
 215:             {
 216:             reply.setErrorCode(ex.getErrorCode ());
 217:             }
 218:           _connection.sendPacket (reply);
 219:       }
 220:   }
 221: }