package org.eclipse.dltk.javascript.jsjdtdebugger; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.Preferences.IPropertyChangeListener; import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IThread; import org.eclipse.dltk.dbgp.commands.IDbgpPropertyCommands; import org.eclipse.dltk.dbgp.exceptions.DbgpException; import org.eclipse.dltk.debug.core.DLTKDebugPlugin; import org.eclipse.dltk.debug.core.model.IScriptThread; import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin; import org.eclipse.dltk.javascript.internal.debug.JavaScriptDebugConstants; import org.eclipse.dltk.javascript.jsjdtdebugger.preferences.IJavaScriptAndJdtDebuggerPreferenceConstants; import org.eclipse.dltk.launching.DebuggingEngineRunner; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class JavaScriptAndJdtDebuggerPlugin extends AbstractUIPlugin implements IDebugEventSetListener, IPropertyChangeListener { private static final String SUSPEND_ON_ENTRY = "suspendOnEntry"; //$NON-NLS-1$ private static final String SUSPEND_ON_EXIT = "suspendOnExit"; //$NON-NLS-1$ private static final String SUSPEND_ON_EXCEPTION = "suspendOnException"; //$NON-NLS-1$ // The plug-in ID public static final String PLUGIN_ID = "org.eclipse.dltk.javascript.jsjdtdebugger"; //$NON-NLS-1$ // The shared instance private static JavaScriptAndJdtDebuggerPlugin plugin; /** * The constructor */ public JavaScriptAndJdtDebuggerPlugin() { } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { super.start(context); plugin = this; Preferences prefs = getPluginPreferences(); resetSuspendProperties(prefs); prefs.addPropertyChangeListener(this); DebugPlugin.getDefault().addDebugEventListener(this); } private void resetSuspendProperties(Preferences prefs) { // TODO this shouldnt be done or needed to be done!! // These preferences should be remembered but whatever i try its // impossible (ToggleStates, AbstractHandlerWithState, Action that is // pulldown) prefs .setValue( IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_ENTRY, false); prefs .setValue( IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_EXIT, false); prefs .setValue( IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_EXCEPTION, false); } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { DebugPlugin.getDefault().removeDebugEventListener(this); getPluginPreferences().removePropertyChangeListener(this); plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static JavaScriptAndJdtDebuggerPlugin getDefault() { return plugin; } public void handleDebugEvents(DebugEvent[] events) { for (int i = 0; i < events.length; i++) { DebugEvent event = events[i]; if (event.getKind() == DebugEvent.CREATE && checkThread(event.getSource())) { IScriptThread thread = (IScriptThread) event.getSource(); setupBreakOnMethodEntry(thread); setupBreakOnMethodExit(thread); setupBreakOnException(thread); } } } /** * Checks that the specified object is {@link IScriptThread} and its model * identifier is {@link JavaScriptDebugConstants#DEBUG_MODEL_ID} * * @param source * @return */ private boolean checkThread(Object source) { if (source instanceof IScriptThread) { final IScriptThread thread = (IScriptThread) source; return JavaScriptDebugConstants.DEBUG_MODEL_ID.equals(thread .getModelIdentifier()); } return false; } private void setupBreakOnMethodEntry(IScriptThread thread) { IDbgpPropertyCommands propCmds = thread.getDbgpSession() .getCoreCommands(); try { Preferences prefs = getPluginPreferences(); String suspendOnEntry = prefs .getString(IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_ENTRY); propCmds.setProperty(SUSPEND_ON_ENTRY, -1, suspendOnEntry); } catch (DbgpException e) { DLTKDebugPlugin.log(e); } } private void setupBreakOnMethodExit(IScriptThread thread) { IDbgpPropertyCommands propCmds = thread.getDbgpSession() .getCoreCommands(); try { Preferences prefs = getPluginPreferences(); String suspendOnExit = prefs .getString(IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_EXIT); propCmds.setProperty(SUSPEND_ON_EXIT, -1, suspendOnExit); } catch (DbgpException e) { DLTKDebugPlugin.log(e); } } private void setupBreakOnException(IScriptThread thread) { IDbgpPropertyCommands propCmds = thread.getDbgpSession() .getCoreCommands(); try { Preferences prefs = getPluginPreferences(); String suspendOnException = prefs .getString(IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_EXCEPTION); propCmds.setProperty(SUSPEND_ON_EXCEPTION, -1, suspendOnException); } catch (DbgpException e) { DLTKDebugPlugin.log(e); } } private boolean isThisDebuggerLaunch(ILaunch launch) { String engineId = launch .getAttribute(DebuggingEngineRunner.LAUNCH_ATTR_DEBUGGING_ENGINE_ID); if (JavaScriptAndJDTDebuggerRunner.ENGINE_ID.equals(engineId)) { return true; } return false; } public void propertyChange(PropertyChangeEvent event) { if (IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_ENTRY .equals(event.getProperty())) { runForEachDebuggerThread(new IDebuggerThreadVisitor() { public void visit(IScriptThread thread) { setupBreakOnMethodEntry(thread); } }); } else if (IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_METHOD_EXIT .equals(event.getProperty())) { runForEachDebuggerThread(new IDebuggerThreadVisitor() { public void visit(IScriptThread thread) { setupBreakOnMethodExit(thread); } }); } else if (IJavaScriptAndJdtDebuggerPreferenceConstants.PREF_BREAK_ON_EXCEPTION .equals(event.getProperty())) { runForEachDebuggerThread(new IDebuggerThreadVisitor() { public void visit(IScriptThread thread) { setupBreakOnException(thread); } }); } } private interface IDebuggerThreadVisitor { void visit(IScriptThread thread); } private void runForEachDebuggerThread(IDebuggerThreadVisitor visitor) { ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager() .getLaunches(); for (int i = 0; i < launches.length; i++) { ILaunch launch = launches[i]; if (false && !isThisDebuggerLaunch(launch)) continue; IDebugTarget target = launch.getDebugTarget(); if (target == null) continue; if (!JavaScriptDebugConstants.DEBUG_MODEL_ID.equals(target .getModelIdentifier())) continue; IThread[] threads = null; try { threads = target.getThreads(); } catch (DebugException e) { DLTKDebugUIPlugin.log(e); } if (threads == null || threads.length == 0) continue; for (int t = 0; t < threads.length; t++) { if (checkThread(threads[t])) { IScriptThread scriptThread = (IScriptThread) threads[t]; visitor.visit(scriptThread); } } } } }