1 /* ClassTypeCommandSet.java -- class to implement the ClassType
2    Command Set
3    Copyright (C) 2005 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.JdwpConstants;
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.Value;
53 
54 import java.io.DataOutputStream;
55 import java.io.IOException;
56 import java.lang.reflect.Field;
57 import java.lang.reflect.Method;
58 import java.nio.ByteBuffer;
59 
60 /**
61  * A class representing the ClassType Command Set.
62  *
63  * @author Aaron Luchko <aluchko@redhat.com>
64  */
65 public class ClassTypeCommandSet
66   extends CommandSet
67 {
runCommand(ByteBuffer bb, DataOutputStream os, byte command)68   public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
69       throws JdwpException
70   {
71     try
72       {
73         switch (command)
74           {
75           case JdwpConstants.CommandSet.ClassType.SUPERCLASS:
76             executeSuperclass(bb, os);
77             break;
78           case JdwpConstants.CommandSet.ClassType.SET_VALUES:
79             executeSetValues(bb, os);
80             break;
81           case JdwpConstants.CommandSet.ClassType.INVOKE_METHOD:
82             executeInvokeMethod(bb, os);
83             break;
84           case JdwpConstants.CommandSet.ClassType.NEW_INSTANCE:
85             executeNewInstance(bb, os);
86             break;
87           default:
88             throw new NotImplementedException("Command " + command +
89               " not found in ClassType Command Set.");
90           }
91       }
92     catch (IOException ex)
93       {
94         // The DataOutputStream we're using isn't talking to a socket at all
95         // So if we throw an IOException we're in serious trouble
96         throw new JdwpInternalErrorException(ex);
97       }
98 
99     return false;
100   }
101 
executeSuperclass(ByteBuffer bb, DataOutputStream os)102   private void executeSuperclass(ByteBuffer bb, DataOutputStream os)
103       throws JdwpException, IOException
104   {
105     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
106     Class clazz = refId.getType();
107     Class superClazz = clazz.getSuperclass();
108 
109     ReferenceTypeId clazzId = idMan.getReferenceTypeId(superClazz);
110     clazzId.write(os);
111   }
112 
executeSetValues(ByteBuffer bb, DataOutputStream os)113   private void executeSetValues(ByteBuffer bb, DataOutputStream os)
114       throws JdwpException, IOException
115   {
116     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
117 
118     // We don't actually seem to need this...
119     Class clazz = refId.getType();
120 
121     int numValues = bb.getInt();
122 
123     for (int i = 0; i < numValues; i++)
124       {
125         ObjectId fieldId = idMan.readObjectId(bb);
126         Field field = (Field) (fieldId.getObject());
127         Object value = Value.getUntaggedObj(bb, field.getType());
128         try
129           {
130             field.setAccessible(true); // Might be a private field
131             field.set(null, value);
132           }
133         catch (IllegalArgumentException ex)
134           {
135             throw new InvalidFieldException(ex);
136           }
137         catch (IllegalAccessException ex)
138           { // Since we set it as accessible this really shouldn't happen
139             throw new JdwpInternalErrorException(ex);
140           }
141       }
142   }
143 
executeInvokeMethod(ByteBuffer bb, DataOutputStream os)144   private void executeInvokeMethod(ByteBuffer bb, DataOutputStream os)
145       throws JdwpException, IOException
146   {
147     MethodResult mr = invokeMethod(bb);
148 
149     Object value = mr.getReturnedValue();
150     Exception exception = mr.getThrownException();
151     ObjectId eId = idMan.getObjectId(exception);
152 
153     Value.writeTaggedValue(os, value);
154     eId.writeTagged(os);
155   }
156 
executeNewInstance(ByteBuffer bb, DataOutputStream os)157   private void executeNewInstance(ByteBuffer bb, DataOutputStream os)
158       throws JdwpException, IOException
159   {
160     MethodResult mr = invokeMethod(bb);
161 
162     Object obj = mr.getReturnedValue();
163     ObjectId oId = idMan.getObjectId(obj);
164     Exception exception = mr.getThrownException();
165     ObjectId eId = idMan.getObjectId(exception);
166 
167     oId.writeTagged(os);
168     eId.writeTagged(os);
169   }
170 
171   /**
172    * Execute the static method and return the resulting MethodResult.
173    */
invokeMethod(ByteBuffer bb)174   private MethodResult invokeMethod(ByteBuffer bb) throws JdwpException,
175       IOException
176   {
177     ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
178     Class clazz = refId.getType();
179 
180     ObjectId tId = idMan.readObjectId(bb);
181     Thread thread = (Thread) tId.getObject();
182 
183     ObjectId mId = idMan.readObjectId(bb);
184     Method method = (Method) mId.getObject();
185 
186     int args = bb.getInt();
187     Object[] values = new Object[args];
188 
189     for (int i = 0; i < args; i++)
190       {
191         values[i] = Value.getObj(bb);
192       }
193 
194     int invokeOpts = bb.getInt();
195     boolean suspend = ((invokeOpts
196 			& JdwpConstants.InvokeOptions.INVOKE_SINGLE_THREADED)
197 		       != 0);
198     try
199       {
200         if (suspend)
201 	  VMVirtualMachine.suspendAllThreads ();
202 
203         MethodResult mr = VMVirtualMachine.executeMethod(null, thread,
204 							 clazz, method,
205 							 values, false);
206         if (suspend)
207 	  VMVirtualMachine.resumeAllThreads ();
208 
209         return mr;
210       }
211     catch (Exception ex)
212       {
213         if (suspend)
214 	  VMVirtualMachine.resumeAllThreads ();
215 
216         throw new JdwpInternalErrorException(ex);
217       }
218   }
219 }
220