aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java')
-rw-r--r--gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java416
1 files changed, 416 insertions, 0 deletions
diff --git a/gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java b/gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
new file mode 100644
index 000000000..1d2329255
--- /dev/null
+++ b/gcc-4.4.3/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
@@ -0,0 +1,416 @@
+/* Jdwp.java -- Virtual machine to JDWP back-end programming interface
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.classpath.jdwp;
+
+import gnu.classpath.jdwp.event.Event;
+import gnu.classpath.jdwp.event.EventManager;
+import gnu.classpath.jdwp.event.EventRequest;
+import gnu.classpath.jdwp.exception.JdwpException;
+import gnu.classpath.jdwp.processor.PacketProcessor;
+import gnu.classpath.jdwp.transport.ITransport;
+import gnu.classpath.jdwp.transport.JdwpConnection;
+import gnu.classpath.jdwp.transport.TransportException;
+import gnu.classpath.jdwp.transport.TransportFactory;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Main interface from the virtual machine to the JDWP back-end.
+ *
+ * The thread created by this class is only used for initialization.
+ * Once it exits, the JDWP backend is fully initialized.
+ *
+ * @author Keith Seitz (keiths@redhat.com)
+ */
+public class Jdwp
+ extends Thread
+{
+ // The single instance of the back-end
+ private static Jdwp _instance = null;
+
+ /**
+ * Are we debugging? Only true if debugging
+ * *and* initialized.
+ */
+ public static boolean isDebugging = false;
+
+ // Packet processor
+ private PacketProcessor _packetProcessor;
+ private Thread _ppThread;
+
+ // JDWP configuration properties
+ private HashMap _properties;
+
+ // The suspend property of the configure string
+ // (-Xrunjdwp:..suspend=<boolean>)
+ private static final String _PROPERTY_SUSPEND = "suspend";
+
+ // Connection to debugger
+ private JdwpConnection _connection;
+
+ // Are we shutting down the current session?
+ private boolean _shutdown;
+
+ // A thread group for the JDWP threads
+ private ThreadGroup _group;
+
+ // Initialization synchronization
+ private Object _initLock = new Object ();
+ private int _initCount = 0;
+
+ /**
+ * constructor
+ */
+ public Jdwp ()
+ {
+ _shutdown = false;
+ _instance = this;
+ }
+
+ /**
+ * Returns the JDWP back-end, creating an instance of it
+ * if one does not already exist.
+ */
+ public static Jdwp getDefault ()
+ {
+ return _instance;
+ }
+
+ /**
+ * Get the thread group used by JDWP threads
+ *
+ * @return the thread group
+ */
+ public ThreadGroup getJdwpThreadGroup()
+ {
+ return _group;
+ }
+
+ /**
+ * Should the virtual machine suspend on startup?
+ */
+ public static boolean suspendOnStartup ()
+ {
+ Jdwp jdwp = getDefault ();
+ if (jdwp != null)
+ {
+ String suspend = (String) jdwp._properties.get (_PROPERTY_SUSPEND);
+ if (suspend != null && suspend.equals ("y"))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Configures the back-end
+ *
+ * @param configArgs a string of configury options
+ */
+ public void configure (String configArgs)
+ {
+ _processConfigury (configArgs);
+ }
+
+ // A helper function to initialize the transport layer
+ private void _doInitialization ()
+ throws TransportException
+ {
+ _group = new ThreadGroup ("JDWP threads");
+ // initialize transport
+ ITransport transport = TransportFactory.newInstance (_properties);
+ _connection = new JdwpConnection (_group, transport);
+ _connection.initialize ();
+ _connection.start ();
+
+ // Create processor
+ _packetProcessor = new PacketProcessor (_connection);
+ _ppThread = new Thread (_group, new Runnable ()
+ {
+ public void run ()
+ {
+ AccessController.doPrivileged (_packetProcessor);
+ }
+ }, "packet processor");
+ _ppThread.start ();
+ }
+
+ /**
+ * Shutdown the JDWP back-end
+ *
+ * NOTE: This does not quite work properly. See notes in
+ * run() on this subject (catch of InterruptedException).
+ */
+ public void shutdown ()
+ {
+ if (!_shutdown)
+ {
+ _packetProcessor.shutdown ();
+ _ppThread.interrupt ();
+ _connection.shutdown ();
+ _shutdown = true;
+ isDebugging = false;
+
+ /* FIXME: probably need to check state of user's
+ program -- if it is suspended, we need to either
+ resume or kill them. */
+
+ interrupt ();
+ }
+ }
+
+ /**
+ * Notify the debugger of an event. This method should not
+ * be called if debugging is not active (but it would not
+ * cause any harm). Places where event notifications occur
+ * should check isDebugging before doing anything.
+ *
+ * The event is filtered through the event manager before being
+ * sent.
+ *
+ * @param event the event to report
+ */
+ public static void notify(Event event)
+ {
+ Jdwp jdwp = getDefault();
+ if (jdwp != null)
+ {
+ EventManager em = EventManager.getDefault();
+ EventRequest[] requests = em.getEventRequests(event);
+ for (int i = 0; i < requests.length; ++i)
+ {
+ try
+ {
+ sendEvent(requests[i], event);
+ jdwp._enforceSuspendPolicy(requests[i].getSuspendPolicy());
+ }
+ catch (Exception e)
+ {
+ /* Really not much we can do. For now, just print out
+ a warning to the user. */
+ System.out.println ("Jdwp.notify: caught exception: " + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notify the debugger of "co-located" events. This method should
+ * not be called if debugging is not active (but it would not
+ * cause any harm). Places where event notifications occur
+ * should check isDebugging before doing anything.
+ *
+ * The events are filtered through the event manager before being
+ * sent.
+ *
+ * @param events the events to report
+ */
+ public static void notify(Event[] events)
+ {
+ Jdwp jdwp = getDefault();
+
+ if (jdwp != null)
+ {
+ byte suspendPolicy = JdwpConstants.SuspendPolicy.NONE;
+ EventManager em = EventManager.getDefault();
+ ArrayList allEvents = new ArrayList ();
+ ArrayList allRequests = new ArrayList ();
+ for (int i = 0; i < events.length; ++i)
+ {
+ EventRequest[] r = em.getEventRequests(events[i]);
+ for (int j = 0; j < r.length; ++j)
+ {
+ /* This is hacky, but it's not clear whether this
+ can really happen, and if it does, what should
+ occur. */
+ allEvents.add (events[i]);
+ allRequests.add (r[j]);
+
+ // Perhaps this is overkill?
+ if (r[j].getSuspendPolicy() > suspendPolicy)
+ suspendPolicy = r[j].getSuspendPolicy();
+ }
+ }
+
+ try
+ {
+ Event[] e = new Event[allEvents.size()];
+ allEvents.toArray(e);
+ EventRequest[] r = new EventRequest[allRequests.size()];
+ allRequests.toArray(r);
+ sendEvents(r, e, suspendPolicy);
+ jdwp._enforceSuspendPolicy(suspendPolicy);
+ }
+ catch (Exception e)
+ {
+ /* Really not much we can do. For now, just print out
+ a warning to the user. */
+ System.out.println ("Jdwp.notify: caught exception: " + e);
+ }
+ }
+ }
+
+ /**
+ * Sends the event to the debugger.
+ *
+ * This method bypasses the event manager's filtering.
+ *
+ * @param request the debugger request for the event
+ * @param event the event to send
+ * @throws IOException if a communications failure occurs
+ */
+ public static void sendEvent (EventRequest request, Event event)
+ throws IOException
+ {
+ sendEvents (new EventRequest[] { request }, new Event[] { event },
+ request.getSuspendPolicy());
+ }
+
+ /**
+ * Sends the events to the debugger.
+ *
+ * This method bypasses the event manager's filtering.
+ *
+ * @param requests list of debugger requests for the events
+ * @param events the events to send
+ * @param suspendPolicy the suspendPolicy enforced by the VM
+ * @throws IOException if a communications failure occurs
+ */
+ public static void sendEvents (EventRequest[] requests, Event[] events,
+ byte suspendPolicy)
+ throws IOException
+ {
+ Jdwp jdwp = getDefault();
+ if (jdwp != null)
+ {
+ synchronized (jdwp._connection)
+ {
+ jdwp._connection.sendEvents (requests, events, suspendPolicy);
+ }
+ }
+ }
+
+ // Helper function to enforce suspend policies on event notification
+ private void _enforceSuspendPolicy (byte suspendPolicy)
+ throws JdwpException
+ {
+ switch (suspendPolicy)
+ {
+ case EventRequest.SUSPEND_NONE:
+ // do nothing
+ break;
+
+ case EventRequest.SUSPEND_THREAD:
+ VMVirtualMachine.suspendThread (Thread.currentThread ());
+ break;
+
+ case EventRequest.SUSPEND_ALL:
+ VMVirtualMachine.suspendAllThreads ();
+ break;
+ }
+ }
+
+ /**
+ * Allows subcomponents to specify that they are
+ * initialized.
+ *
+ * Subcomponents include JdwpConnection and PacketProcessor.
+ */
+ public void subcomponentInitialized ()
+ {
+ synchronized (_initLock)
+ {
+ ++_initCount;
+ _initLock.notify ();
+ }
+ }
+
+ public void run ()
+ {
+ try
+ {
+ _doInitialization ();
+
+ /* We need a little internal synchronization here, so that
+ when this thread dies, the back-end will be fully initialized,
+ ready to start servicing the VM and debugger. */
+ synchronized (_initLock)
+ {
+ while (_initCount != 2)
+ _initLock.wait ();
+ }
+ _initLock = null;
+ }
+ catch (Throwable t)
+ {
+ System.out.println ("Exception in JDWP back-end: " + t);
+ System.exit (1);
+ }
+
+ /* Force creation of the EventManager. If the event manager
+ has not been created when isDebugging is set, it is possible
+ that the VM will call Jdwp.notify (which uses EventManager)
+ while the EventManager is being created (or at least this is
+ a problem with gcj/gij). */
+ EventManager.getDefault();
+
+ // Now we are finally ready and initialized
+ isDebugging = true;
+ }
+
+ // A helper function to process the configure string "-Xrunjdwp:..."
+ private void _processConfigury (String configString)
+ {
+ // Loop through configuration arguments looking for a
+ // transport name
+ _properties = new HashMap ();
+ String[] options = configString.split (",");
+ for (int i = 0; i < options.length; ++i)
+ {
+ String[] property = options[i].split ("=");
+ if (property.length == 2)
+ _properties.put (property[0], property[1]);
+ // ignore malformed options
+ }
+ }
+}