/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Bjorn Freeman-Benson - initial API and implementation
*******************************************************************************/
package rhogenwizard.debugger.model;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IExpressionListener;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.dltk.internal.debug.core.model.ScriptLineBreakpoint;
import rhogenwizard.ConsoleHelper;
import rhogenwizard.PlatformType;
import rhogenwizard.RhodesConfigurationRO;
import rhogenwizard.RunType;
import rhogenwizard.ShowOnlyHidePerspectiveJob;
import rhogenwizard.constants.DebugConstants;
import rhogenwizard.debugger.RhogenWatchExpression;
import rhogenwizard.debugger.RhogenWatchExpressionResult;
import rhogenwizard.debugger.backend.DebugServer;
import rhogenwizard.debugger.backend.DebugServerException;
import rhogenwizard.debugger.backend.DebugState;
import rhogenwizard.debugger.backend.DebugVariableType;
import rhogenwizard.debugger.backend.IDebugCallback;
import rhogenwizard.debugger.model.selector.ResourceNameSelector;
import rhogenwizard.project.ProjectFactory;
import rhogenwizard.project.RhoconnectProject;
import rhogenwizard.project.extension.BadProjectTagException;
import rhogenwizard.sdk.task.StopRhodesAppTask;
import rhogenwizard.sdk.task.StopSyncAppTask;
/**
* PDA Debug Target
*/
public class DebugTarget extends DebugElement implements IDebugTarget, IDebugCallback, IExpressionListener
{
private static String fwTag = "framework";
private IProject m_debugProject = null;
// associated system process (VM)
private IProcess m_processHandle = null;
// containing launch object
private ILaunch m_launchHandle = null;
// program name
private String m_programName = null;
// suspend state
private boolean m_isSuspended = true;
// threads
private DebugThread m_threadHandle = null;
private IThread[] m_allThreads = null;
private static DebugServer m_debugServer = null;
private RunType m_runType;
private PlatformType m_platformType;
public DebugTarget(ILaunch launch, IProcess process, IProject debugProject, RunType runType, PlatformType platformType)
{
super(null);
m_platformType = platformType;
m_runType = runType;
m_debugProject = debugProject;
m_launchHandle = launch;
m_debugTarget = this;
m_processHandle = process;
m_threadHandle = new DebugThread(this);
m_allThreads = new IThread[] { m_threadHandle };
DebugServer.setDebugOutputStream(System.out);
if (m_debugServer != null)
{
m_debugServer.shutdown();
}
DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this);
m_debugServer = new DebugServer(this);
m_debugServer.start();
m_debugServer.debugSkipBreakpoints(false);
}
@Override
protected void finalize() throws Throwable
{
exited();
super.finalize();
}
public void setProcess(IProcess p)
{
m_processHandle = p;
}
public IProcess getProcess()
{
return m_processHandle;
}
public IThread[] getThreads() throws DebugException
{
return m_allThreads;
}
public boolean hasThreads() throws DebugException
{
return true;
}
public String getName() throws DebugException
{
if (m_programName == null)
{
m_programName = new RhodesConfigurationRO(getLaunch().getLaunchConfiguration()).project();
}
return m_programName;
}
public boolean supportsBreakpoint(IBreakpoint breakpoint)
{
if (breakpoint.getModelIdentifier().equals(DebugConstants.debugModelId))
{
return true;
}
return false;
}
public IDebugTarget getDebugTarget()
{
return this;
}
public ILaunch getLaunch()
{
return m_launchHandle;
}
public boolean canTerminate()
{
if (m_processHandle == null)
return true;
return m_processHandle.canTerminate();
}
public boolean isTerminated()
{
if (m_processHandle == null)
return true;
return m_processHandle.isTerminated();
}
public void terminate() throws DebugException
{
try
{
m_debugServer.debugTerminate();
if (ProjectFactory.getInstance().typeFromProject(m_debugProject).equals(RhoconnectProject.class))
{
new StopSyncAppTask().run();
}
else if (m_runType == RunType.eDevice || m_runType == RunType.eSimulator)
{
String workDir = m_debugProject.getLocation().makeAbsolute().toString();
new StopRhodesAppTask(workDir, m_platformType, m_runType).run();
}
if (m_processHandle != null)
{
m_processHandle.terminate();
m_processHandle = null;
}
}
catch (DebugServerException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public boolean canResume()
{
return !isTerminated() && isSuspended();
}
public boolean canSuspend()
{
return !isTerminated() && !isSuspended();
}
private void waitDebugProcessing()
{
try
{
while (m_debugServer.debugIsProcessing())
{
}
Thread.currentThread();
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public boolean isSuspended()
{
return m_isSuspended;
}
public void resume() throws DebugException
{
waitDebugProcessing();
cleanState();
waitDebugProcessing();
resumed(DebugEvent.CLIENT_REQUEST);
waitDebugProcessing();
m_debugServer.debugResume();
}
/**
* Notification the target has resumed for the given reason
*
* @param detail
* reason for the resume
*/
private void resumed(int detail)
{
waitDebugProcessing();
m_isSuspended = false;
m_threadHandle.fireResumeEvent(detail);
}
/**
* Notification the target has suspended for the given reason
*
* @param detail
* reason for the suspend
*/
private void suspended(int detail)
{
waitDebugProcessing();
m_isSuspended = true;
m_threadHandle.fireSuspendEvent(detail);
}
public void suspend() throws DebugException
{
}
//TODO - hot fix
private boolean isFunctionDefinition(ScriptLineBreakpoint lineBp)
{
IFile file = (IFile) lineBp.getResource();
try
{
BufferedReader contentBuffer = new BufferedReader(new InputStreamReader(file.getContents()));
String buf = "";
for (int i=0; i < lineBp.getLineNumber(); i++)
{
buf = contentBuffer.readLine();
}
return buf.matches("^\\s*def\\s.*$");
}
catch (CoreException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return false;
}
public void breakpointAdded(IBreakpoint breakpoint)
{
boolean globalBpEnable = DebugPlugin.getDefault().getBreakpointManager().isEnabled();
if (supportsBreakpoint(breakpoint))
{
try
{
if (breakpoint.isEnabled() && globalBpEnable)
{
ScriptLineBreakpoint lineBr = (ScriptLineBreakpoint) breakpoint;
if (!isFunctionDefinition(lineBr))
{
int lineNum = lineBr.getLineNumber();
String srcFile = ResourceNameSelector.getInstance().convertBpName(ProjectFactory.getInstance().typeFromProject(m_debugProject), lineBr);
m_debugServer.debugBreakpoint(srcFile, lineNum);
}
else
{
breakpoint.setEnabled(false);
}
}
}
catch (CoreException e)
{
}
catch (BadProjectTagException e)
{
e.printStackTrace();
}
}
}
public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta)
{
if (supportsBreakpoint(breakpoint))
{
try
{
ScriptLineBreakpoint lineBr = (ScriptLineBreakpoint) breakpoint;
int lineNum = lineBr.getLineNumber();
String srcFile = ResourceNameSelector.getInstance().convertBpName(ProjectFactory.getInstance().typeFromProject(m_debugProject), lineBr);
m_debugServer.debugRemoveBreakpoint(srcFile, lineNum);
}
catch (CoreException e)
{
}
catch (BadProjectTagException e)
{
e.printStackTrace();
}
}
}
public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta)
{
boolean globalBpEnable = DebugPlugin.getDefault().getBreakpointManager().isEnabled();
if (supportsBreakpoint(breakpoint))
{
if (!globalBpEnable)
{
breakpointRemoved(breakpoint, null);
return;
}
try
{
if (breakpoint.isEnabled())
{
breakpointAdded(breakpoint);
}
else
{
breakpointRemoved(breakpoint, null);
}
}
catch (CoreException e)
{
}
}
}
public boolean canDisconnect()
{
return false;
}
public void disconnect() throws DebugException
{
}
public void stepOver()
{
waitDebugProcessing();
m_threadHandle.setStepping(true);
waitDebugProcessing();
resumed(DebugEvent.STEP_OVER);
waitDebugProcessing();
m_debugServer.debugStepOver();
}
public void stepReturn()
{
waitDebugProcessing();
m_threadHandle.setStepping(true);
waitDebugProcessing();
resumed(DebugEvent.STEP_RETURN);
waitDebugProcessing();
m_debugServer.debugStepReturn();
}
public void stepInto()
{
waitDebugProcessing();
m_threadHandle.setStepping(true);
waitDebugProcessing();
resumed(DebugEvent.STEP_INTO);
waitDebugProcessing();
m_debugServer.debugStepInto();
}
public boolean isDisconnected()
{
return false;
}
public boolean supportsStorageRetrieval()
{
return false;
}
public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException
{
return null;
}
/**
* Install breakpoints that are already registered with the breakpoint
* manager.
*/
private void installDeferredBreakpoints()
{
IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugConstants.debugModelId);
for (int i = 0; i < breakpoints.length; i++)
{
breakpointAdded(breakpoints[i]);
}
}
private void installDeferredWatchs()
{
IExpression[] watchs = DebugPlugin.getDefault().getExpressionManager().getExpressions();
for (IExpression exp : watchs)
{
waitDebugProcessing();
m_debugServer.debugEvaluate(exp.getExpressionText());
}
}
/**
* Returns the current stack frames in the target.
*
* @return the current stack frames in the target
* @throws DebugException
* if unable to perform the request
*/
protected IStackFrame[] getStackFrames() throws DebugException
{
waitDebugProcessing();
StackData stackData = new StackData(m_debugServer.debugGetFile(), m_debugServer.debugGetLine());
IStackFrame[] theFrames = new IStackFrame[1];
for (int i = 0; i < 3; ++i)
{
try
{
stackData.m_currVariables = m_debugServer.debugWatchList();
theFrames[0] = new DebugStackFrame(m_threadHandle, stackData, 0);
break;
}
catch (DebugServerException e)
{
try
{
Thread.sleep(200);
}
catch (InterruptedException e1)
{
}
}
}
return theFrames;
}
@Override
public void connected()
{
try
{
cleanState();
fireCreationEvent();
installDeferredBreakpoints();
resume();
}
catch (DebugException e)
{
}
}
boolean isFoundFramework()
{
IFolder fwFodler = m_debugProject.getFolder(fwTag);
try
{
IResource[] childRes = fwFodler.members();
return fwFodler.exists() && childRes.length != 0;
}
catch (CoreException e)
{
e.printStackTrace();
}
return false;
}
private void showDebugPerspective()
{
ShowOnlyHidePerspectiveJob job = new ShowOnlyHidePerspectiveJob("Show debug perspective", DebugConstants.debugPerspectiveId);
job.schedule();
}
@Override
public void stopped(DebugState state, String file, int line, String className, String method)
{
waitDebugProcessing();
showDebugPerspective();
if (file.contains(fwTag))
{
if (!isFoundFramework())
{
try
{
resume();
}
catch (DebugException e)
{
e.printStackTrace();
}
return;
}
}
cleanState();
installDeferredWatchs();
waitDebugProcessing();
if (state == DebugState.BREAKPOINT)
{
IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugConstants.debugModelId);
for (int i = 0; i < breakpoints.length; i++)
{
waitDebugProcessing();
IBreakpoint breakpoint = breakpoints[i];
if (breakpoint instanceof ScriptLineBreakpoint)
{
try
{
ScriptLineBreakpoint lineBreakpoint = (ScriptLineBreakpoint) breakpoint;
String resPath = ResourceNameSelector.getInstance().convertBpName(ProjectFactory.getInstance().typeFromProject(m_debugProject), lineBreakpoint);
if (lineBreakpoint.getLineNumber() == line && resPath.equals(file))
{
m_threadHandle.setBreakpoints(new IBreakpoint[] { breakpoint });
break;
}
}
catch (CoreException e)
{
}
catch (BadProjectTagException e1)
{
}
}
}
suspended(DebugEvent.BREAKPOINT);
}
else if (DebugState.paused(state))
{
m_threadHandle.setStepping(true);
suspended(DebugEvent.STEP_END);
}
}
@Override
public void unknown(String cmd)
{
}
@Override
public void exited()
{
m_isSuspended = false;
DebugPlugin.getDefault().getBreakpointManager().removeBreakpointListener(this);
DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this);
fireTerminateEvent();
if (m_processHandle != null)
{
try
{
terminate();
}
catch (DebugException e)
{
e.printStackTrace();
}
}
try
{
m_debugServer.shutdown();
}
catch (DebugServerException e)
{
}
}
@Override
public void resumed()
{
waitDebugProcessing();
cleanState();
m_isSuspended = false;
waitDebugProcessing();
resumed(DebugEvent.CLIENT_REQUEST);
}
void cleanState()
{
m_threadHandle.setBreakpoints(null);
m_threadHandle.setStepping(false);
}
@Override
synchronized public void evaluation(boolean valid, String code, String value)
{
ConsoleHelper.getAppConsole().show();
ConsoleHelper.getAppConsole().getStream().println("start");
IExpressionManager expManager = DebugPlugin.getDefault().getExpressionManager();
IExpression[] modelExps = expManager.getExpressions();
for (IExpression currExp : modelExps)
{
if (currExp.getExpressionText().equals(code))
{
if (currExp instanceof RhogenWatchExpression)
{
IValue watchVal = new DebugValue(this, value);
RhogenWatchExpression watchExp = (RhogenWatchExpression) currExp;
watchExp.setResult(new RhogenWatchExpressionResult(code, watchVal));
}
}
}
}
@Override
public void watchBOL(DebugVariableType type)
{
// TODO Auto-generated method stub
}
@Override
public void watchEOL(DebugVariableType type)
{
// TODO Auto-generated method stub
}
@Override
public void expressionAdded(IExpression expression)
{
IExpressionManager m = DebugPlugin.getDefault().getExpressionManager();
waitDebugProcessing();
String expText = expression.getExpressionText();
if (!(expression instanceof RhogenWatchExpression))
{
m.removeExpression(expression);
m.addExpression(new RhogenWatchExpression(expText));
m_debugServer.debugEvaluate(expText);
}
}
@Override
public void expressionRemoved(IExpression expression)
{
// TODO Auto-generated method stub
}
@Override
public void expressionChanged(IExpression expression)
{
// waitDebugProcessing();
// String expText = expression.getExpressionText();
// expression = new RhogenWatchExpression(expText);
// m_debugServer.debugEvaluate(expText);
}
@Override
public void watch(DebugVariableType type, String variable, String value)
{
// TODO Auto-generated method stub
}
}