277 lines · 9.4 KB · Java
RawDownload
/* * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.example.debug.tty; import com.sun.jdi.*;import com.sun.jdi.event.*;import com.sun.jdi.request.EventRequest; public class EventHandler implements Runnable {     EventNotifier notifier;    Thread thread;    volatile boolean connected = true;    boolean completed = false;    String shutdownMessageKey;    boolean stopOnVMStart;     EventHandler(EventNotifier notifier, boolean stopOnVMStart) {        this.notifier = notifier;        this.stopOnVMStart = stopOnVMStart;        this.thread = new Thread(this, "event-handler");        this.thread.start();    }     synchronized void shutdown() {        connected = false;  // force run() loop termination        thread.interrupt();        while (!completed) {            try {wait();} catch (InterruptedException exc) {}        }    }     @Override    public void run() {        EventQueue queue = Env.vm().eventQueue();        while (connected) {            try {                EventSet eventSet = queue.remove();                boolean resumeStoppedApp = false;                EventIterator it = eventSet.eventIterator();                while (it.hasNext()) {                    resumeStoppedApp |= !handleEvent(it.nextEvent());                }                 if (resumeStoppedApp) {                    eventSet.resume();                } else if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL) {                    setCurrentThread(eventSet);                    notifier.vmInterrupted();                }            } catch (InterruptedException exc) {                // Do nothing. Any changes will be seen at top of loop.            } catch (VMDisconnectedException discExc) {                handleDisconnectedException();                break;            }        }        synchronized (this) {            completed = true;            notifyAll();        }    }     private boolean handleEvent(Event event) {        notifier.receivedEvent(event);         if (event instanceof ExceptionEvent) {            return exceptionEvent(event);        } else if (event instanceof BreakpointEvent) {            return breakpointEvent(event);        } else if (event instanceof WatchpointEvent) {            return fieldWatchEvent(event);        } else if (event instanceof StepEvent) {            return stepEvent(event);        } else if (event instanceof MethodEntryEvent) {            return methodEntryEvent(event);        } else if (event instanceof MethodExitEvent) {            return methodExitEvent(event);        } else if (event instanceof ClassPrepareEvent) {            return classPrepareEvent(event);        } else if (event instanceof ClassUnloadEvent) {            return classUnloadEvent(event);        } else if (event instanceof ThreadStartEvent) {            return threadStartEvent(event);        } else if (event instanceof ThreadDeathEvent) {            return threadDeathEvent(event);        } else if (event instanceof VMStartEvent) {            return vmStartEvent(event);        } else {            return handleExitEvent(event);        }    }     private boolean vmDied = false;    private boolean handleExitEvent(Event event) {        if (event instanceof VMDeathEvent) {            vmDied = true;            return vmDeathEvent(event);        } else if (event instanceof VMDisconnectEvent) {            connected = false;            if (!vmDied) {                vmDisconnectEvent(event);            }            Env.shutdown(shutdownMessageKey);            return false;        } else {            throw new InternalError(MessageOutput.format("Unexpected event type",                                                         new Object[] {event.getClass()}));        }    }     synchronized void handleDisconnectedException() {        /*         * A VMDisconnectedException has happened while dealing with         * another event. We need to flush the event queue, dealing only         * with exit events (VMDeath, VMDisconnect) so that we terminate         * correctly.         */        EventQueue queue = Env.vm().eventQueue();        while (connected) {            try {                EventSet eventSet = queue.remove();                EventIterator iter = eventSet.eventIterator();                while (iter.hasNext()) {                    handleExitEvent(iter.next());                }            } catch (InterruptedException exc) {                // ignore            } catch (InternalError exc) {                // ignore            }        }    }     private ThreadReference eventThread(Event event) {        if (event instanceof ClassPrepareEvent) {            return ((ClassPrepareEvent)event).thread();        } else if (event instanceof LocatableEvent) {            return ((LocatableEvent)event).thread();        } else if (event instanceof ThreadStartEvent) {            return ((ThreadStartEvent)event).thread();        } else if (event instanceof ThreadDeathEvent) {            return ((ThreadDeathEvent)event).thread();        } else if (event instanceof VMStartEvent) {            return ((VMStartEvent)event).thread();        } else {            return null;        }    }     private void setCurrentThread(EventSet set) {        ThreadReference thread;        if (set.size() > 0) {            /*             * If any event in the set has a thread associated with it,             * they all will, so just grab the first one.             */            Event event = set.iterator().next(); // Is there a better way?            thread = eventThread(event);        } else {            thread = null;        }        setCurrentThread(thread);    }     private void setCurrentThread(ThreadReference thread) {        ThreadInfo.invalidateAll();        ThreadInfo.setCurrentThread(thread);    }     private boolean vmStartEvent(Event event)  {        VMStartEvent se = (VMStartEvent)event;        notifier.vmStartEvent(se);        return stopOnVMStart;    }     private boolean breakpointEvent(Event event)  {        BreakpointEvent be = (BreakpointEvent)event;        notifier.breakpointEvent(be);        return true;    }     private boolean methodEntryEvent(Event event)  {        MethodEntryEvent me = (MethodEntryEvent)event;        notifier.methodEntryEvent(me);        return true;    }     private boolean methodExitEvent(Event event)  {        MethodExitEvent me = (MethodExitEvent)event;        return notifier.methodExitEvent(me);    }     private boolean fieldWatchEvent(Event event)  {        WatchpointEvent fwe = (WatchpointEvent)event;        notifier.fieldWatchEvent(fwe);        return true;    }     private boolean stepEvent(Event event)  {        StepEvent se = (StepEvent)event;        notifier.stepEvent(se);        return true;    }     private boolean classPrepareEvent(Event event)  {        ClassPrepareEvent cle = (ClassPrepareEvent)event;        notifier.classPrepareEvent(cle);         if (!Env.specList.resolve(cle)) {            MessageOutput.lnprint("Stopping due to deferred breakpoint errors.");            return true;        } else {            return false;        }    }     private boolean classUnloadEvent(Event event)  {        ClassUnloadEvent cue = (ClassUnloadEvent)event;        notifier.classUnloadEvent(cue);        return false;    }     private boolean exceptionEvent(Event event) {        ExceptionEvent ee = (ExceptionEvent)event;        notifier.exceptionEvent(ee);        return true;    }     private boolean threadDeathEvent(Event event) {        ThreadDeathEvent tee = (ThreadDeathEvent)event;        ThreadInfo.removeThread(tee.thread());        return false;    }     private boolean threadStartEvent(Event event) {        ThreadStartEvent tse = (ThreadStartEvent)event;        ThreadInfo.addThread(tse.thread());        notifier.threadStartEvent(tse);        return false;    }     public boolean vmDeathEvent(Event event) {        shutdownMessageKey = "The application exited";        notifier.vmDeathEvent((VMDeathEvent)event);        return false;    }     public boolean vmDisconnectEvent(Event event) {        shutdownMessageKey = "The application has been disconnected";        notifier.vmDisconnectEvent((VMDisconnectEvent)event);        return false;    }}