libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / classpath / jdwp / processor / VirtualMachineCommandSet.java
blobb6e0cfeb8b3b15c53fb064a6d5e252536fd9c0d5
1 /* VirtualMachineCommandSet.java -- class to implement the VirtualMachine
2 Command Set
3 Copyright (C) 2005, 2006, 2007 Free Software Foundation
5 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
40 package gnu.classpath.jdwp.processor;
42 import gnu.classpath.jdwp.JdwpConstants;
43 import gnu.classpath.jdwp.VMFrame;
44 import gnu.classpath.jdwp.VMVirtualMachine;
45 import gnu.classpath.jdwp.exception.JdwpException;
46 import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
47 import gnu.classpath.jdwp.exception.NotImplementedException;
48 import gnu.classpath.jdwp.id.ObjectId;
49 import gnu.classpath.jdwp.id.ReferenceTypeId;
50 import gnu.classpath.jdwp.util.JdwpString;
51 import gnu.classpath.jdwp.util.Signature;
53 import java.io.DataOutputStream;
54 import java.io.IOException;
55 import java.nio.ByteBuffer;
56 import java.util.ArrayList;
57 import java.util.Collection;
58 import java.util.Iterator;
59 import java.util.Properties;
61 /**
62 * A class representing the VirtualMachine Command Set.
64 * @author Aaron Luchko <aluchko@redhat.com>
66 public class VirtualMachineCommandSet
67 extends CommandSet
69 public boolean runCommand(ByteBuffer bb, DataOutputStream os, byte command)
70 throws JdwpException
72 boolean shutdown = false;
73 try
75 switch (command)
77 case JdwpConstants.CommandSet.VirtualMachine.VERSION:
78 executeVersion(bb, os);
79 break;
80 case JdwpConstants.CommandSet.VirtualMachine.CLASSES_BY_SIGNATURE:
81 executeClassesBySignature(bb, os);
82 break;
83 case JdwpConstants.CommandSet.VirtualMachine.ALL_CLASSES:
84 executeAllClasses(bb, os);
85 break;
86 case JdwpConstants.CommandSet.VirtualMachine.ALL_THREADS:
87 executeAllThreads(bb, os);
88 break;
89 case JdwpConstants.CommandSet.VirtualMachine.TOP_LEVEL_THREAD_GROUPS:
90 executeTopLevelThreadGroups(bb, os);
91 break;
92 case JdwpConstants.CommandSet.VirtualMachine.IDSIZES:
93 executeIDsizes(bb, os);
94 break;
95 case JdwpConstants.CommandSet.VirtualMachine.DISPOSE:
96 shutdown = true;
97 executeDispose(bb, os);
98 break;
99 case JdwpConstants.CommandSet.VirtualMachine.SUSPEND:
100 executeSuspend(bb, os);
101 break;
102 case JdwpConstants.CommandSet.VirtualMachine.RESUME:
103 executeResume(bb, os);
104 break;
105 case JdwpConstants.CommandSet.VirtualMachine.EXIT:
106 shutdown = true;
107 executeExit(bb, os);
108 break;
109 case JdwpConstants.CommandSet.VirtualMachine.CREATE_STRING:
110 executeCreateString(bb, os);
111 break;
112 case JdwpConstants.CommandSet.VirtualMachine.CAPABILITIES:
113 executeCapabilities(bb, os);
114 break;
115 case JdwpConstants.CommandSet.VirtualMachine.CLASS_PATHS:
116 executeClassPaths(bb, os);
117 break;
118 case JdwpConstants.CommandSet.VirtualMachine.DISPOSE_OBJECTS:
119 executeDisposeObjects(bb, os);
120 break;
121 case JdwpConstants.CommandSet.VirtualMachine.HOLD_EVENTS:
122 executeHoldEvents(bb, os);
123 break;
124 case JdwpConstants.CommandSet.VirtualMachine.RELEASE_EVENTS:
125 executeReleaseEvents(bb, os);
126 break;
127 case JdwpConstants.CommandSet.VirtualMachine.CAPABILITIES_NEW:
128 executeCapabilitiesNew(bb, os);
129 break;
130 case JdwpConstants.CommandSet.VirtualMachine.REDEFINE_CLASSES:
131 executeRedefineClasses(bb, os);
132 break;
133 case JdwpConstants.CommandSet.VirtualMachine.SET_DEFAULT_STRATUM:
134 executeSetDefaultStratum(bb, os);
135 break;
136 case JdwpConstants.CommandSet.VirtualMachine.ALL_CLASSES_WITH_GENERIC:
137 executeAllClassesWithGeneric(bb, os);
138 break;
139 default:
140 throw new NotImplementedException("Command " + command +
141 " not found in VirtualMachine Command Set.");
144 catch (IOException ex)
146 // The DataOutputStream we're using isn't talking to a socket at all
147 // So if we throw an IOException we're in serious trouble
148 throw new JdwpInternalErrorException(ex);
151 return shutdown;
154 private void executeVersion(ByteBuffer bb, DataOutputStream os)
155 throws JdwpException, IOException
158 Properties props = System.getProperties();
160 int jdwpMajor = JdwpConstants.Version.MAJOR;
161 int jdwpMinor = JdwpConstants.Version.MINOR;
162 // The description field is pretty loosely defined
163 String description = "JDWP version " + jdwpMajor + "." + jdwpMinor
164 + ", JVM version " + props.getProperty("java.vm.name")
165 + " " + props.getProperty("java.vm.version") + " "
166 + props.getProperty("java.version");
167 String vmVersion = props.getProperty("java.version");
168 String vmName = props.getProperty("java.vm.name");
169 JdwpString.writeString(os, description);
170 os.writeInt(jdwpMajor);
171 os.writeInt(jdwpMinor);
172 JdwpString.writeString(os, vmName);
173 JdwpString.writeString(os, vmVersion);
176 private void executeClassesBySignature(ByteBuffer bb, DataOutputStream os)
177 throws JdwpException, IOException
179 String sig = JdwpString.readString(bb);
180 ArrayList allMatchingClasses = new ArrayList();
182 // This will be an Iterator over all loaded Classes
183 Collection classes = VMVirtualMachine.getAllLoadedClasses();
184 Iterator iter = classes.iterator ();
186 while (iter.hasNext())
188 Class clazz = (Class) iter.next();
189 String clazzSig = Signature.computeClassSignature(clazz);
190 if (clazzSig.equals(sig))
191 allMatchingClasses.add(clazz);
194 os.writeInt(allMatchingClasses.size());
195 for (int i = 0; i < allMatchingClasses.size(); i++)
197 Class clazz = (Class) allMatchingClasses.get(i);
198 ReferenceTypeId id = idMan.getReferenceTypeId(clazz);
199 id.writeTagged(os);
200 int status = VMVirtualMachine.getClassStatus(clazz);
201 os.writeInt(status);
205 private void executeAllClasses(ByteBuffer bb, DataOutputStream os)
206 throws JdwpException, IOException
208 Collection classes = VMVirtualMachine.getAllLoadedClasses();
209 os.writeInt(classes.size ());
211 Iterator iter = classes.iterator ();
212 while (iter.hasNext())
214 Class clazz = (Class) iter.next();
215 ReferenceTypeId id = idMan.getReferenceTypeId(clazz);
216 id.writeTagged(os);
217 String sig = Signature.computeClassSignature(clazz);
218 JdwpString.writeString(os, sig);
219 int status = VMVirtualMachine.getClassStatus(clazz);
220 os.writeInt(status);
224 private void executeAllThreads(ByteBuffer bb, DataOutputStream os)
225 throws JdwpException, IOException
227 ThreadGroup jdwpGroup = Thread.currentThread().getThreadGroup();
228 ThreadGroup root = getRootThreadGroup(jdwpGroup);
230 int numThreads = root.activeCount();
231 Thread allThreads[] = new Thread[numThreads];
232 root.enumerate(allThreads);
234 // We need to loop through for the true count since some threads may have
235 // been destroyed since we got
236 // activeCount so those spots in the array will be null. As well we must
237 // ignore any threads that belong to jdwp
238 numThreads = 0;
239 for (int i = 0; i < allThreads.length; i++)
241 Thread thread = allThreads[i];
242 if (thread == null)
243 break; // No threads after this point
244 if (!thread.getThreadGroup().equals(jdwpGroup))
245 numThreads++;
248 os.writeInt(numThreads);
250 for (int i = 0; i < allThreads.length; i++)
252 Thread thread = allThreads[i];
253 if (thread == null)
254 break; // No threads after this point
255 if (!thread.getThreadGroup().equals(jdwpGroup))
256 idMan.getObjectId(thread).write(os);
260 private void executeTopLevelThreadGroups(ByteBuffer bb, DataOutputStream os)
261 throws JdwpException, IOException
263 ThreadGroup jdwpGroup = Thread.currentThread().getThreadGroup ();
264 ThreadGroup root = getRootThreadGroup(jdwpGroup);
266 os.writeInt(1); // Just one top level group allowed?
267 idMan.getObjectId(root).write(os);
270 private void executeDispose(ByteBuffer bb, DataOutputStream os)
271 throws JdwpException
273 // resumeAllThreads isn't sufficient as a thread may have been
274 // suspended multiple times, we likely need a way to keep track of how many
275 // times a thread has been suspended or else a stronger resume method for
276 // this purpose
277 // VMVirtualMachine.resumeAllThreads ();
279 // Simply shutting down the jdwp layer will take care of the rest of the
280 // shutdown other than disabling debugging in the VM
281 // VMVirtualMachine.disableDebugging();
283 // Don't implement this until we're sure how to remove all the debugging
284 // effects from the VM.
285 throw new NotImplementedException(
286 "Command VirtualMachine.Dispose not implemented");
290 private void executeIDsizes(ByteBuffer bb, DataOutputStream os)
291 throws JdwpException, IOException
293 os.writeInt(ObjectId.SIZE); // fieldId FIXME
294 os.writeInt(ObjectId.SIZE); // methodId FIXME
295 os.writeInt(ObjectId.SIZE); // objectId
296 os.writeInt(ReferenceTypeId.SIZE); // referenceTypeId
297 os.writeInt(VMFrame.SIZE); // frameId
300 private void executeSuspend(ByteBuffer bb, DataOutputStream os)
301 throws JdwpException
303 VMVirtualMachine.suspendAllThreads ();
306 private void executeResume(ByteBuffer bb, DataOutputStream os)
307 throws JdwpException
309 VMVirtualMachine.resumeAllThreads ();
312 private void executeExit(ByteBuffer bb, DataOutputStream os)
313 throws JdwpException, IOException
315 int exitCode = bb.getInt();
316 System.exit (exitCode);
319 private void executeCreateString(ByteBuffer bb, DataOutputStream os)
320 throws JdwpException, IOException
322 String string = JdwpString.readString(bb);
323 ObjectId stringId = idMan.getObjectId(string);
325 // Since this string isn't referenced anywhere we'll disable garbage
326 // collection on it so it's still around when the debugger gets back to it.
327 stringId.disableCollection();
328 stringId.write(os);
331 private void executeCapabilities(ByteBuffer bb, DataOutputStream os)
332 throws JdwpException, IOException
334 os.writeBoolean(VMVirtualMachine.canWatchFieldModification);
335 os.writeBoolean(VMVirtualMachine.canWatchFieldAccess);
336 os.writeBoolean(VMVirtualMachine.canGetBytecodes);
337 os.writeBoolean(VMVirtualMachine.canGetSyntheticAttribute);
338 os.writeBoolean(VMVirtualMachine.canGetOwnedMonitorInfo);
339 os.writeBoolean(VMVirtualMachine.canGetCurrentContendedMonitor);
340 os.writeBoolean(VMVirtualMachine.canGetMonitorInfo);
343 private void executeClassPaths(ByteBuffer bb, DataOutputStream os)
344 throws JdwpException, IOException
346 String baseDir = System.getProperty("user.dir");
347 JdwpString.writeString(os, baseDir);
349 // Find and write the classpath
350 String classPath = System.getProperty("java.class.path");
351 String[] paths = classPath.split(":");
353 os.writeInt(paths.length);
354 for (int i = 0; i < paths.length; i++)
355 JdwpString.writeString(os, paths[i]);
357 // Now the bootpath
358 String bootPath = System.getProperty("sun.boot.class.path");
359 paths = bootPath.split(":");
360 os.writeInt(paths.length);
361 for (int i = 0; i < paths.length; i++)
362 JdwpString.writeString(os, paths[i]);
365 private void executeDisposeObjects(ByteBuffer bb, DataOutputStream os)
366 throws JdwpException
368 // Instead of going through the list of objects they give us it's probably
369 // better just to find the garbage collected objects ourselves
370 //idMan.update();
373 private void executeHoldEvents(ByteBuffer bb, DataOutputStream os)
374 throws JdwpException
376 // Going to have to implement a send queue somewhere and do this without
377 // triggering events
378 // Until then just don't implement
379 throw new NotImplementedException(
380 "Command VirtualMachine.HoldEvents not implemented");
383 // Opposite of executeHoldEvents
384 private void executeReleaseEvents(ByteBuffer bb, DataOutputStream os)
385 throws JdwpException
387 throw new NotImplementedException(
388 "Command VirtualMachine.ReleaseEvents not implemented");
391 private void executeCapabilitiesNew(ByteBuffer bb, DataOutputStream os)
392 throws JdwpException, IOException
394 final int CAPABILITIES_NEW_SIZE = 32;
396 executeCapabilities(bb, os);
397 os.writeBoolean(VMVirtualMachine.canRedefineClasses);
398 os.writeBoolean(VMVirtualMachine.canAddMethod);
399 os.writeBoolean(VMVirtualMachine.canUnrestrictedlyRedefineClasses);
400 os.writeBoolean(VMVirtualMachine.canPopFrames);
401 os.writeBoolean(VMVirtualMachine.canUseInstanceFilters);
402 os.writeBoolean(VMVirtualMachine.canGetSourceDebugExtension);
403 os.writeBoolean(VMVirtualMachine.canRequestVMDeathEvent);
404 os.writeBoolean(VMVirtualMachine.canSetDefaultStratum);
405 for (int i = 15; i < CAPABILITIES_NEW_SIZE; i++)
407 // Future capabilities (currently unused)
408 os.writeBoolean(false);
412 private void executeRedefineClasses(ByteBuffer bb, DataOutputStream os)
413 throws JdwpException
415 if (!VMVirtualMachine.canRedefineClasses)
417 String msg = "redefinition of classes is not supported";
418 throw new NotImplementedException(msg);
421 int classes = bb.getInt();
422 Class[] types = new Class[classes];
423 byte[][] bytecodes = new byte[classes][];
424 for (int i = 0; i < classes; ++i)
426 ReferenceTypeId id = idMan.readReferenceTypeId(bb);
427 int classfile = bb.getInt();
428 byte[] bytecode = new byte[classfile];
429 bb.get(bytecode);
430 types[i] = id.getType();
431 bytecodes[i] = bytecode;
434 VMVirtualMachine.redefineClasses (types, bytecodes);
437 private void executeSetDefaultStratum(ByteBuffer bb, DataOutputStream os)
438 throws JdwpException
440 if (!VMVirtualMachine.canSetDefaultStratum)
442 String msg = "setting the default stratum is not supported";
443 throw new NotImplementedException(msg);
446 String stratum = JdwpString.readString(bb);
447 VMVirtualMachine.setDefaultStratum(stratum);
450 private void executeAllClassesWithGeneric(ByteBuffer bb, DataOutputStream os)
451 throws JdwpException
453 // We don't handle generics
454 throw new NotImplementedException(
455 "Command VirtualMachine.AllClassesWithGeneric not implemented");
459 * Find the root ThreadGroup of this ThreadGroup
461 private ThreadGroup getRootThreadGroup(ThreadGroup group)
463 ThreadGroup parent = group.getParent();
465 while (parent != null)
467 group = parent;
468 parent = group.getParent();
470 return group; // This group was the root