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