blob: 9e993f356b319047e95cfdc07dd1ef5004808b3b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.internal.debug.core.model;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
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.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.dbgp.IDbgpSession;
import org.eclipse.dltk.dbgp.breakpoints.IDbgpBreakpoint;
import org.eclipse.dltk.dbgp.commands.IDbgpExtendedCommands;
import org.eclipse.dltk.dbgp.exceptions.DbgpException;
import org.eclipse.dltk.dbgp.internal.IDbgpTerminationListener;
import org.eclipse.dltk.debug.core.DLTKDebugPlugin;
import org.eclipse.dltk.debug.core.DebugPreferenceConstants;
import org.eclipse.dltk.debug.core.ISmartStepEvaluator;
import org.eclipse.dltk.debug.core.eval.IScriptEvaluationEngine;
import org.eclipse.dltk.debug.core.model.IScriptDebugTarget;
import org.eclipse.dltk.debug.core.model.IScriptThread;
import org.eclipse.dltk.internal.debug.core.eval.ScriptEvaluationEngine;
import org.eclipse.dltk.internal.debug.core.model.operations.DbgpDebugger;
public class ScriptThread extends ScriptDebugElement implements IScriptThread,
IThreadManagement, IDbgpTerminationListener,
ScriptThreadStateManager.IStateChangeHandler {
private ScriptThreadStateManager stateManager;
private final IScriptThreadManager manager;
private final ScriptStack stack;
// Session
private final IDbgpSession session;
// State variables
private final IScriptDebugTarget target;
private IScriptEvaluationEngine evalEngine;
private int currentStackLevel;
private IPropertyChangeListener propertyListener;
// ScriptThreadStateManager.IStateChangeHandler
public void handleSuspend(int detail) {
stack.update();
if( handleSmartStepInto() ) {
return;
}
DebugEventHelper.fireSuspendEvent(this, detail);
}
private boolean handleSmartStepInto() {
if (stateManager.isStepInto()
&& getScriptDebugTarget().isUseStepFilters()
&& stack.getFrames().length > currentStackLevel) {
stateManager.setStepInto(false);
IScriptDebugTarget target = this.getScriptDebugTarget();
String[] filters = target.getFilters();
IDLTKLanguageToolkit toolkit = this.getScriptDebugTarget().getLanguageToolkit();
if (toolkit != null) {
ISmartStepEvaluator evaluator = SmartStepEvaluatorManager
.getEvaluator(toolkit.getNatureId());
if (evaluator != null) {
if (evaluator.skipSuspend(filters, this)) {
try {
this.stepReturn();
return true;
} catch (DebugException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
}
}
}
return false;
}
public void handleResume(int detail) {
DebugEventHelper.fireResumeEvent(this, detail);
DebugEventHelper.fireChangeEvent(this);
}
public void handleTermination(DbgpException e) {
if (e != null) {
DLTKDebugPlugin.log(e);
}
session.requestTermination();
try {
session.waitTerminated();
} catch (InterruptedException ee) {
ee.printStackTrace();
}
manager.terminateThread(this);
}
public ScriptThread(IScriptDebugTarget target, IDbgpSession session,
IScriptThreadManager manager) throws DbgpException, CoreException {
this.target = target;
this.manager = manager;
this.session = session;
this.session.addTerminationListener(this);
this.stateManager = new ScriptThreadStateManager(this);
final DbgpDebugger engine = this.stateManager.getEngine();
if (DLTKCore.DEBUG) {
DbgpDebugger.printEngineInfo(engine);
}
final IDbgpExtendedCommands extended = session.getExtendedCommands();
engine.setMaxChildren(256);
engine.setMaxDepth(2);
engine.setMaxData(8192);
if (engine.isFeatureSupported(IDbgpExtendedCommands.STDIN_COMMAND)) {
engine.redirectStdin();
}
engine.setNotifyOk(true);
engine.redirectStdout();
engine.redirectStderr();
// session.getNotificationManager().addNotificationListener(
// new IDbgpNotificationListener() {
// private final BufferedReader reader = new BufferedReader(
// new InputStreamReader(getStreamProxy().getStdin()));
//
// public void dbgpNotify(IDbgpNotification notification) {
// try {
// extended.sendStdin(reader.readLine() + "\n");
// } catch (IOException e) {
// // TODO: log exception
// e.printStackTrace();
// } catch (DbgpException e) {
// // TODO: log exception
// e.printStackTrace();
// }
// }
// });
this.stack = new ScriptStack(this);
propertyListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(DebugPreferenceConstants.PREF_DBGP_SHOW_SCOPE_GLOBAL)
|| event.getProperty().equals(DebugPreferenceConstants.PREF_DBGP_SHOW_SCOPE_CLASS)) {
stack.updateFrames();
DebugEventHelper.fireChangeEvent(ScriptThread.this
.getDebugTarget());
}
}
};
Preferences prefs = DLTKDebugPlugin.getDefault().getPluginPreferences();
prefs.addPropertyChangeListener(propertyListener);
}
public boolean hasStackFrames() throws DebugException {
return stack.hasFrames();
}
// IThread
public IStackFrame[] getStackFrames() throws DebugException {
if (!isSuspended()) {
return ScriptStack.NO_STACK_FRAMES;
}
return stack.getFrames();
}
public int getPriority() throws DebugException {
return 0;
}
public IStackFrame getTopStackFrame() throws DebugException {
return stack.getTopFrame();
}
public String getName() throws DebugException {
return session.getInfo().getThreadId();
}
public IBreakpoint[] getBreakpoints() {
return DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
getModelIdentifier());
}
// ISuspendResume
// Suspend
public int getModificationsCount() {
return stateManager.getModificationsCount();
}
public boolean isSuspended() {
return stateManager.isSuspended();
}
public boolean canSuspend() {
return stateManager.canSuspend();
}
public void suspend() throws DebugException {
stateManager.suspend();
}
// Resume
public boolean canResume() {
return stateManager.canResume();
}
public void resume() throws DebugException {
stateManager.resume();
}
// IStep
public boolean isStepping() {
return stateManager.isStepping();
}
// Step into
public boolean canStepInto() {
return stateManager.canStepInto();
}
public void stepInto() throws DebugException {
currentStackLevel = this.stack.getFrames().length;
stateManager.stepInto();
}
// Step over
public boolean canStepOver() {
return stateManager.canStepOver();
}
public void stepOver() throws DebugException {
stateManager.stepOver();
}
// Step return
public boolean canStepReturn() {
return stateManager.canStepReturn();
}
public void stepReturn() throws DebugException {
stateManager.stepReturn();
}
// ITerminate
public boolean isTerminated() {
return stateManager.isTerminated();
}
public boolean canTerminate() {
return !isTerminated();
}
public void terminate() throws DebugException {
stateManager.terminate();
}
public IDbgpSession getDbgpSession() {
return session;
}
public IDbgpBreakpoint getDbgpBreakpoint(String id) {
try {
return session.getCoreCommands().getBreakpoint(id);
} catch (DbgpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public IScriptStreamProxy getStreamProxy() {
return target.getStreamProxy();
}
public IDebugTarget getDebugTarget() {
return target.getDebugTarget();
}
public IScriptEvaluationEngine getEvaluationEngine() {
if (evalEngine == null) {
evalEngine = new ScriptEvaluationEngine(this);
}
return evalEngine;
}
// IDbgpTerminationListener
public void objectTerminated(Object object, Exception e) {
Assert.isTrue(object == session);
manager.terminateThread(this);
Preferences prefs = DLTKDebugPlugin.getDefault().getPluginPreferences();
prefs.addPropertyChangeListener(propertyListener);
}
// Object
public String toString() {
return "Thread (" + session.getInfo().getThreadId() + ")";
}
public void notifyModified() {
stateManager.notifyModified();
}
}