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