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