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 */ PacketProcessor(JdwpConnection con)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 */ run()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 */ shutdown()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. _processOnePacket()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 } 222