1 /* ReferenceTypeCommandSet.java -- class to implement the ReferenceType
2    Command Set
3    Copyright (C) 2005, 2006, 2007 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 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38 
39 
40 package gnu.classpath.jdwp.processor;
41 
42 import gnu.classpath.jdwp.JdwpConstants;
43 import gnu.classpath.jdwp.VMMethod;
44 import gnu.classpath.jdwp.VMVirtualMachine;
45 import gnu.classpath.jdwp.exception.InvalidFieldException;
46 import gnu.classpath.jdwp.exception.JdwpException;
47 import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
48 import gnu.classpath.jdwp.exception.NotImplementedException;
49 import gnu.classpath.jdwp.id.ObjectId;
50 import gnu.classpath.jdwp.id.ReferenceTypeId;
51 import gnu.classpath.jdwp.util.JdwpString;
52 import gnu.classpath.jdwp.util.Signature;
53 import gnu.classpath.jdwp.value.Value;
54 import gnu.classpath.jdwp.value.ValueFactory;
55 
56 import java.io.DataOutputStream;
57 import java.io.IOException;
58 import java.lang.reflect.Field;
59 import java.nio.ByteBuffer;
60 
61 /**
62  * A class representing the ReferenceType Command Set.
63  *
64  * @author Aaron Luchko <aluchko@redhat.com>
65  */
66 public class ReferenceTypeCommandSet
67   extends CommandSet
68 {
runCommand(ByteBuffer bb, DataOutputStream os, byte command)69   public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
70     throws JdwpException
71   {
72     try
73       {
74         switch (command)
75           {
76           case JdwpConstants.CommandSet.ReferenceType.SIGNATURE:
77             executeSignature(bb, os);
78             break;
79           case JdwpConstants.CommandSet.ReferenceType.CLASS_LOADER:
80             executeClassLoader(bb, os);
81             break;
82           case JdwpConstants.CommandSet.ReferenceType.MODIFIERS:
83             executeModifiers(bb, os);
84             break;
85           case JdwpConstants.CommandSet.ReferenceType.FIELDS:
86             executeFields(bb, os);
87             break;
88           case JdwpConstants.CommandSet.ReferenceType.METHODS:
89             executeMethods(bb, os);
90             break;
91           case JdwpConstants.CommandSet.ReferenceType.GET_VALUES:
92             executeGetValues(bb, os);
93             break;
94           case JdwpConstants.CommandSet.ReferenceType.SOURCE_FILE:
95             executeSourceFile(bb, os);
96             break;
97           case JdwpConstants.CommandSet.ReferenceType.NESTED_TYPES:
98             executeNestedTypes(bb, os);
99             break;
100           case JdwpConstants.CommandSet.ReferenceType.STATUS:
101             executeStatus(bb, os);
102             break;
103           case JdwpConstants.CommandSet.ReferenceType.INTERFACES:
104             executeInterfaces(bb, os);
105             break;
106           case JdwpConstants.CommandSet.ReferenceType.CLASS_OBJECT:
107             executeClassObject(bb, os);
108             break;
109           case JdwpConstants.CommandSet.ReferenceType.SOURCE_DEBUG_EXTENSION:
110             executeSourceDebugExtension(bb, os);
111             break;
112           case JdwpConstants.CommandSet.ReferenceType.SIGNATURE_WITH_GENERIC:
113             executeSignatureWithGeneric(bb, os);
114             break;
115           case JdwpConstants.CommandSet.ReferenceType.FIELDS_WITH_GENERIC:
116             executeFieldWithGeneric(bb, os);
117             break;
118           case JdwpConstants.CommandSet.ReferenceType.METHODS_WITH_GENERIC:
119             executeMethodsWithGeneric(bb, os);
120             break;
121           default:
122             throw new NotImplementedException("Command " + command +
123               " not found in ReferenceType Command Set.");
124           }
125       }
126     catch (IOException ex)
127       {
128         // The DataOutputStream we're using isn't talking to a socket at all
129         // So if we throw an IOException we're in serious trouble
130         throw new JdwpInternalErrorException(ex);
131       }
132 
133     return false;
134   }
135 
executeSignature(ByteBuffer bb, DataOutputStream os)136   private void executeSignature(ByteBuffer bb, DataOutputStream os)
137     throws JdwpException, IOException
138   {
139     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
140     String sig = Signature.computeClassSignature(refId.getType());
141     JdwpString.writeString(os, sig);
142   }
143 
executeClassLoader(ByteBuffer bb, DataOutputStream os)144   private void executeClassLoader(ByteBuffer bb, DataOutputStream os)
145     throws JdwpException, IOException
146   {
147     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
148 
149     Class clazz = refId.getType();
150     ClassLoader loader = clazz.getClassLoader();
151     ObjectId oid = idMan.getObjectId(loader);
152     oid.write(os);
153   }
154 
executeModifiers(ByteBuffer bb, DataOutputStream os)155   private void executeModifiers(ByteBuffer bb, DataOutputStream os)
156     throws JdwpException, IOException
157   {
158     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
159 
160     Class clazz = refId.getType();
161     os.writeInt(clazz.getModifiers());
162   }
163 
executeFields(ByteBuffer bb, DataOutputStream os)164   private void executeFields(ByteBuffer bb, DataOutputStream os)
165     throws JdwpException, IOException
166   {
167     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
168     Class clazz = refId.getType();
169 
170     Field[] fields = clazz.getFields();
171     os.writeInt(fields.length);
172     for (int i = 0; i < fields.length; i++)
173       {
174         Field field = fields[i];
175         idMan.getObjectId(field).write(os);
176         JdwpString.writeString(os, field.getName());
177         JdwpString.writeString(os, Signature.computeFieldSignature(field));
178         os.writeInt(field.getModifiers());
179       }
180   }
181 
executeMethods(ByteBuffer bb, DataOutputStream os)182   private void executeMethods(ByteBuffer bb, DataOutputStream os)
183     throws JdwpException, IOException
184   {
185     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
186     Class clazz = refId.getType();
187 
188     VMMethod[] methods = VMVirtualMachine.getAllClassMethods(clazz);
189     os.writeInt (methods.length);
190     for (int i = 0; i < methods.length; i++)
191       {
192         VMMethod method = methods[i];
193         method.writeId(os);
194         JdwpString.writeString(os, method.getName());
195         JdwpString.writeString(os, method.getSignature());
196         os.writeInt(method.getModifiers());
197       }
198   }
199 
executeGetValues(ByteBuffer bb, DataOutputStream os)200   private void executeGetValues(ByteBuffer bb, DataOutputStream os)
201     throws JdwpException, IOException
202   {
203     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
204     Class clazz = refId.getType();
205 
206     int numFields = bb.getInt();
207     os.writeInt(numFields); // Looks pointless but this is the protocol
208     for (int i = 0; i < numFields; i++)
209       {
210         ObjectId fieldId = idMan.readObjectId(bb);
211         Field field = (Field) (fieldId.getObject());
212         Class fieldClazz = field.getDeclaringClass();
213 
214         // We don't actually need the clazz to get the field but we might as
215         // well check that the debugger got it right
216         if (fieldClazz.isAssignableFrom(clazz))
217           {
218             try
219               {
220                 field.setAccessible(true); // Might be a private field
221                 Object value = field.get(null);
222                 Value val = ValueFactory.createFromObject(value,
223                                                           field.getType());
224                 val.writeTagged(os);
225               }
226             catch (IllegalArgumentException ex)
227               {
228                 // I suppose this would best qualify as an invalid field then
229                 throw new InvalidFieldException(ex);
230               }
231             catch (IllegalAccessException ex)
232               {
233                 // Since we set it as accessible this really shouldn't happen
234                 throw new JdwpInternalErrorException(ex);
235               }
236           }
237         else
238           throw new InvalidFieldException(fieldId.getId());
239       }
240   }
241 
executeSourceFile(ByteBuffer bb, DataOutputStream os)242   private void executeSourceFile(ByteBuffer bb, DataOutputStream os)
243     throws JdwpException, IOException
244   {
245     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
246     Class clazz = refId.getType();
247 
248     // We'll need to go into the jvm for this unless there's an easier way
249     String sourceFileName = VMVirtualMachine.getSourceFile(clazz);
250     JdwpString.writeString(os, sourceFileName);
251     // clazz.getProtectionDomain().getCodeSource().getLocation();
252   }
253 
executeNestedTypes(ByteBuffer bb, DataOutputStream os)254   private void executeNestedTypes(ByteBuffer bb, DataOutputStream os)
255     throws JdwpException, IOException
256   {
257     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
258     Class clazz = refId.getType();
259     Class[] declaredClazzes = clazz.getDeclaredClasses();
260     os.writeInt(declaredClazzes.length);
261     for (int i = 0; i < declaredClazzes.length; i++)
262       {
263         Class decClazz = declaredClazzes[i];
264         ReferenceTypeId clazzId = idMan.getReferenceTypeId(decClazz);
265         clazzId.writeTagged(os);
266       }
267   }
268 
executeStatus(ByteBuffer bb, DataOutputStream os)269   private void executeStatus(ByteBuffer bb, DataOutputStream os)
270     throws JdwpException, IOException
271   {
272     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
273     Class clazz = refId.getType();
274 
275     // I don't think there's any other way to get this
276     int status = VMVirtualMachine.getClassStatus(clazz);
277     os.writeInt(status);
278   }
279 
executeInterfaces(ByteBuffer bb, DataOutputStream os)280   private void executeInterfaces(ByteBuffer bb, DataOutputStream os)
281     throws JdwpException, IOException
282   {
283     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
284     Class clazz = refId.getType();
285     Class[] interfaces = clazz.getInterfaces();
286     os.writeInt(interfaces.length);
287     for (int i = 0; i < interfaces.length; i++)
288       {
289         Class interfaceClass = interfaces[i];
290         ReferenceTypeId intId = idMan.getReferenceTypeId(interfaceClass);
291         intId.write(os);
292       }
293   }
294 
executeClassObject(ByteBuffer bb, DataOutputStream os)295   private void executeClassObject(ByteBuffer bb, DataOutputStream os)
296     throws JdwpException, IOException
297   {
298     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
299     Class clazz = refId.getType();
300     ObjectId clazzObjectId = idMan.getObjectId(clazz);
301     clazzObjectId.write(os);
302   }
303 
executeSourceDebugExtension(ByteBuffer bb, DataOutputStream os)304   private void executeSourceDebugExtension(ByteBuffer bb, DataOutputStream os)
305     throws JdwpException, IOException
306   {
307     if (!VMVirtualMachine.canGetSourceDebugExtension)
308       {
309         String msg = "source debug extension is not supported";
310         throw new NotImplementedException(msg);
311       }
312 
313     ReferenceTypeId id = idMan.readReferenceTypeId(bb);
314     String ext = VMVirtualMachine.getSourceDebugExtension (id.getType());
315     JdwpString.writeString(os, ext);
316   }
317 
executeSignatureWithGeneric(ByteBuffer bb, DataOutputStream os)318   private void executeSignatureWithGeneric(ByteBuffer bb, DataOutputStream os)
319     throws JdwpException, IOException
320   {
321     // We don't have generics yet
322     throw new NotImplementedException(
323       "Command SignatureWithGeneric not implemented.");
324   }
325 
executeFieldWithGeneric(ByteBuffer bb, DataOutputStream os)326   private void executeFieldWithGeneric(ByteBuffer bb, DataOutputStream os)
327     throws JdwpException, IOException
328   {
329     // We don't have generics yet
330     throw new NotImplementedException(
331       "Command executeFieldWithGeneric not implemented.");
332   }
333 
executeMethodsWithGeneric(ByteBuffer bb, DataOutputStream os)334   private void executeMethodsWithGeneric(ByteBuffer bb, DataOutputStream os)
335     throws JdwpException, IOException
336   {
337     // We don't have generics yet
338     throw new NotImplementedException(
339       "Command executeMethodsWithGeneric not implemented.");
340   }
341 }
342