1 /* ObjectReferenceCommandSet.java -- class to implement the ObjectReference
2    Command Set
3    Copyright (C) 2005, 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.MethodResult;
52 import gnu.classpath.jdwp.util.MonitorInfo;
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 ObjectReference Command Set.
63  *
64  * @author Aaron Luchko <aluchko@redhat.com>
65  */
66 public class ObjectReferenceCommandSet
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.ObjectReference.REFERENCE_TYPE:
77             executeReferenceType(bb, os);
78             break;
79           case JdwpConstants.CommandSet.ObjectReference.GET_VALUES:
80             executeGetValues(bb, os);
81             break;
82           case JdwpConstants.CommandSet.ObjectReference.SET_VALUES:
83             executeSetValues(bb, os);
84             break;
85           case JdwpConstants.CommandSet.ObjectReference.MONITOR_INFO:
86             executeMonitorInfo(bb, os);
87             break;
88           case JdwpConstants.CommandSet.ObjectReference.INVOKE_METHOD:
89             executeInvokeMethod(bb, os);
90             break;
91           case JdwpConstants.CommandSet.ObjectReference.DISABLE_COLLECTION:
92             executeDisableCollection(bb, os);
93             break;
94           case JdwpConstants.CommandSet.ObjectReference.ENABLE_COLLECTION:
95             executeEnableCollection(bb, os);
96             break;
97           case JdwpConstants.CommandSet.ObjectReference.IS_COLLECTED:
98             executeIsCollected(bb, os);
99             break;
100           default:
101             throw new NotImplementedException("Command " + command +
102               " not found in ObjectReference Command Set.");
103           }
104       }
105     catch (IOException ex)
106       {
107         // The DataOutputStream we're using isn't talking to a socket at all
108         // So if we throw an IOException we're in serious trouble
109         throw new JdwpInternalErrorException(ex);
110       }
111 
112     return false;
113   }
114 
executeReferenceType(ByteBuffer bb, DataOutputStream os)115   private void executeReferenceType(ByteBuffer bb, DataOutputStream os)
116     throws JdwpException, IOException
117   {
118     ObjectId oid = idMan.readObjectId(bb);
119     Object obj = oid.getObject();
120     Class clazz = obj.getClass();
121     ReferenceTypeId refId = idMan.getReferenceTypeId(clazz);
122     refId.writeTagged(os);
123   }
124 
executeGetValues(ByteBuffer bb, DataOutputStream os)125   private void executeGetValues(ByteBuffer bb, DataOutputStream os)
126     throws JdwpException, IOException
127   {
128     ObjectId oid = idMan.readObjectId(bb);
129     Object obj = oid.getObject();
130 
131     int numFields = bb.getInt();
132 
133     os.writeInt(numFields); // Looks pointless but this is the protocol
134 
135     for (int i = 0; i < numFields; i++)
136       {
137         Field field = (Field) idMan.readObjectId(bb).getObject();
138         try
139           {
140             field.setAccessible(true); // Might be a private field
141             Object value = field.get(obj);
142             Value val = ValueFactory.createFromObject(value,
143                                                       field.getType());
144             val.writeTagged(os);
145           }
146         catch (IllegalArgumentException ex)
147           {
148             // I suppose this would best qualify as an invalid field then
149             throw new InvalidFieldException(ex);
150           }
151         catch (IllegalAccessException ex)
152           {
153             // Since we set it as accessible this really shouldn't happen
154             throw new JdwpInternalErrorException(ex);
155           }
156       }
157   }
158 
executeSetValues(ByteBuffer bb, DataOutputStream os)159   private void executeSetValues(ByteBuffer bb, DataOutputStream os)
160     throws JdwpException, IOException
161   {
162     ObjectId oid = idMan.readObjectId(bb);
163     Object obj = oid.getObject();
164 
165     int numFields = bb.getInt();
166 
167     for (int i = 0; i < numFields; i++)
168       {
169         Field field = (Field) idMan.readObjectId(bb).getObject();
170         Object value = Value.getUntaggedObject(bb, field.getType());
171         try
172           {
173             field.setAccessible(true); // Might be a private field
174             field.set(obj, value);
175           }
176         catch (IllegalArgumentException ex)
177           {
178             // I suppose this would best qualify as an invalid field then
179             throw new InvalidFieldException(ex);
180           }
181         catch (IllegalAccessException ex)
182           {
183             // Since we set it as accessible this really shouldn't happen
184             throw new JdwpInternalErrorException(ex);
185           }
186       }
187   }
188 
executeMonitorInfo(ByteBuffer bb, DataOutputStream os)189   private void executeMonitorInfo(ByteBuffer bb, DataOutputStream os)
190     throws JdwpException, IOException
191   {
192     if (!VMVirtualMachine.canGetMonitorInfo)
193       {
194         String msg = "getting monitor info not supported";
195         throw new NotImplementedException(msg);
196       }
197 
198     ObjectId oid = idMan.readObjectId(bb);
199     Object obj = oid.getObject();
200     MonitorInfo info = VMVirtualMachine.getMonitorInfo(obj);
201     info.write(os);
202   }
203 
executeInvokeMethod(ByteBuffer bb, DataOutputStream os)204   private void executeInvokeMethod(ByteBuffer bb, DataOutputStream os)
205     throws JdwpException, IOException
206   {
207     ObjectId oid = idMan.readObjectId(bb);
208     Object obj = oid.getObject();
209 
210     ObjectId tid = idMan.readObjectId(bb);
211     Thread thread = (Thread) tid.getObject();
212 
213     ReferenceTypeId rid = idMan.readReferenceTypeId(bb);
214     Class clazz = rid.getType();
215 
216     VMMethod method = VMMethod.readId(clazz, bb);
217 
218     int args = bb.getInt();
219     Value[] values = new Value[args];
220 
221     for (int i = 0; i < args; i++)
222       values[i] = ValueFactory.createFromTagged(bb);
223 
224     int invokeOptions = bb.getInt();
225     MethodResult mr = VMVirtualMachine.executeMethod(obj, thread,
226                                                      clazz, method,
227                                                      values, invokeOptions);
228     Throwable exception = mr.getThrownException();
229     ObjectId eId = idMan.getObjectId(exception);
230     mr.getReturnedValue().writeTagged(os);
231     eId.writeTagged(os);
232   }
233 
executeDisableCollection(ByteBuffer bb, DataOutputStream os)234   private void executeDisableCollection(ByteBuffer bb, DataOutputStream os)
235     throws JdwpException, IOException
236   {
237     ObjectId oid = idMan.readObjectId(bb);
238     oid.disableCollection();
239   }
240 
executeEnableCollection(ByteBuffer bb, DataOutputStream os)241   private void executeEnableCollection(ByteBuffer bb, DataOutputStream os)
242     throws JdwpException, IOException
243   {
244     ObjectId oid = idMan.readObjectId(bb);
245     oid.enableCollection();
246   }
247 
executeIsCollected(ByteBuffer bb, DataOutputStream os)248   private void executeIsCollected(ByteBuffer bb, DataOutputStream os)
249     throws JdwpException, IOException
250   {
251     ObjectId oid = idMan.readObjectId(bb);
252     boolean collected = (oid.getReference().get () == null);
253     os.writeBoolean(collected);
254   }
255 }
256