/*
* Created on Jun 9, 2006 Copyright (C) 2001-5, Anthony Harrison anh23@pitt.edu
* (jactr.org) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have
* received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jactr.eclipse.runtime.debug.elements;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.jactr.eclipse.core.comp.CompilationUnitManager;
import org.jactr.eclipse.core.comp.ICompilationUnit;
import org.jactr.eclipse.core.comp.IProjectCompilationUnit;
import org.jactr.eclipse.runtime.RuntimePlugin;
import org.jactr.eclipse.runtime.debug.ACTRDebugTarget;
import org.jactr.eclipse.runtime.debug.marker.ACTRBreakpoint;
import org.jactr.eclipse.runtime.debug.util.Utilities;
import org.jactr.eclipse.runtime.preferences.RuntimePreferences;
public class ACTRThread extends ACTRDebugElement implements IThread
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(ACTRThread.class);
String _modelName;
boolean _isRunning;
boolean _isSuspended;
IBreakpoint[] _breakpoint = new IBreakpoint[0];
int _maxHistory;
int _cullHistoryTo;
ACTRStackFrame _breakpointStackFrame;
List<ACTRStackFrame> _stackFrames;
public ACTRThread(ACTRDebugTarget target, String modelName)
{
setDebugTarget(target);
_modelName = modelName;
_isRunning = true;
_isSuspended = false;
_stackFrames = new ArrayList<ACTRStackFrame>();
_cullHistoryTo = RuntimePlugin.getDefault().getPluginPreferences().getInt(
RuntimePreferences.DEBUG_STACK_PREF);
_maxHistory = _cullHistoryTo * 3 / 2;
}
public String getSourceName()
{
ICompilationUnit compUnit = Utilities.getCompilationUnitForAlias(
getLaunch(), _modelName);
if (compUnit == null || !(compUnit instanceof IProjectCompilationUnit))
return null;
IResource resource = ((IProjectCompilationUnit) compUnit).getResource();
CompilationUnitManager.release(compUnit);
return resource.getProjectRelativePath().toString();
}
public IBreakpoint[] getBreakpoints()
{
return _breakpoint;
}
public String getName() throws DebugException
{
return _modelName;
}
@Override
public String toString()
{
return _modelName;
}
public int getPriority() throws DebugException
{
return 0;
}
public IStackFrame[] getStackFrames() throws DebugException
{
synchronized (_stackFrames)
{
return _stackFrames.toArray(new IStackFrame[0]);
}
}
public IStackFrame getTopStackFrame() throws DebugException
{
synchronized (_stackFrames)
{
if (_stackFrames.size() > 0)
return _stackFrames.get(_stackFrames.size() - 1);
else
return null;
}
}
/**
* add a stack frame, and possible fire suspend event if it is a breakpoint
*
* @param frame
* @param isBreakpoint
*/
public void addStackFrame(ACTRStackFrame frame, boolean isBreakpoint)
{
synchronized (_stackFrames)
{
if (_breakpointStackFrame != null)
_stackFrames.remove(_breakpointStackFrame);
if (_stackFrames.size() >= _maxHistory)
_stackFrames.subList(0, _maxHistory - _cullHistoryTo).clear();
_stackFrames.add(frame);
}
if (isBreakpoint)
{
_breakpointStackFrame = frame;
setSuspended(true, frame.getProductionName());
}
}
public boolean hasStackFrames() throws DebugException
{
synchronized (_stackFrames)
{
return _stackFrames.size() > 0;
}
}
public void setSuspended(boolean suspended, String details)
{
if (isTerminated()) return;
if (suspended == _isSuspended)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug(_modelName + " Redundant suspend command - ignoring");
return;
}
_isSuspended = suspended;
if (LOGGER.isDebugEnabled())
LOGGER.debug(this + " suspended " + _isSuspended + " at " + details);
_breakpoint = new IBreakpoint[0];
int code = DebugEvent.UNSPECIFIED;
if (_isSuspended)
{
if (details.length() != 0)
{
// try to find the exact break point
IBreakpointManager mgr = DebugPlugin.getDefault()
.getBreakpointManager();
IBreakpoint[] breakpoints = mgr.getBreakpoints(getModelIdentifier());
for (IBreakpoint breakpoint : breakpoints)
if (breakpoint.getMarker() != null)
{
IMarker marker = breakpoint.getMarker();
// check its name
String name = marker.getAttribute(ACTRBreakpoint.BREAKPOINT_NAME,
"");
if (name.equals(details))
{
code = DebugEvent.BREAKPOINT;
_breakpoint = new IBreakpoint[] { breakpoint };
break;
}
}
}
fireSuspendEvent(code);
}
else
fireResumeEvent(code);
}
public void setTerminated(boolean terminated)
{
_isRunning = !terminated;
if (LOGGER.isDebugEnabled())
LOGGER.debug(this + " terminated " + _isRunning);
if (!_isRunning) fireTerminateEvent();
}
public boolean canResume()
{
return getACTRDebugTarget().canResume();
}
public boolean canSuspend()
{
// if (isTerminated()) return false;
// return !isSuspended();
return getACTRDebugTarget().canSuspend();
}
public boolean isSuspended()
{
return getACTRDebugTarget().isSuspended();
}
public void resume() throws DebugException
{
getACTRDebugTarget().resume();
}
public void suspend() throws DebugException
{
getACTRDebugTarget().suspend();
}
public boolean canStepInto()
{
return false;
}
public boolean canStepOver()
{
return false;
}
public boolean canStepReturn()
{
// return isSuspended();
return false;
}
public boolean isStepping()
{
return false;
}
public void stepInto() throws DebugException
{
}
public void stepOver() throws DebugException
{
}
public void stepReturn() throws DebugException
{
// resume();
}
public boolean canTerminate()
{
return getACTRDebugTarget().canTerminate();
}
public boolean isTerminated()
{
return getACTRDebugTarget().isTerminated();
}
public void terminate() throws DebugException
{
getACTRDebugTarget().terminate();
}
}