Package xvrengine.debug

Source Code of xvrengine.debug.XVRDebugTarget$EventDispatchJob

package xvrengine.debug;

import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IDebugTarget;
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.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.xvr.xvrengine.perspective.XVRPerspectiveFactory;
import org.xvr.xvrengine.process.IProcessExitListener;
import org.xvr.xvrengine.process.ProcessExitHandler;
import org.xvr.xvrengine.util.XVRUtils;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class XVRDebugTarget extends XVRDebugElement implements IDebugTarget{
 
  private static final int RETRY = 10;
 
  private ILaunch launch;
  private IProcess process;
 
  // sockets to communicate with VM
  private Socket eventSocket;
  private Socket commandSocket;
  private BufferedReader eventReader;
  private PrintStream commandWriter;
  private BufferedReader commandReader;
 
  private VMThread mainThread;
  private IThread[] threads;
  private boolean suspended;
  private String name;
 
  private IStackFrame[] frames;
 
  // event dispatch job
  private EventDispatchJob eventDispatch;
 
  class EventDispatchJob extends Job {
    private int comPort;
    private int evPort;
   
    private boolean canceled;
   
    public EventDispatchJob(int commandPort, int eventPort) {
      super("XVR Event Dispatcher");
      this.comPort = commandPort;
      this.evPort = eventPort;
      this.canceled = false;
      setSystem(true);
    }

    @Override
    protected void canceling() {
      this.canceled = true;
    }
   
    @Override
    protected IStatus run(IProgressMonitor monitor) {
      //connects to the VirtualMachine
      for(int i = 0; i < RETRY; i++){
        if(monitor.isCanceled() || this.canceled)
          return Status.OK_STATUS;
        try {
          if(commandSocket == null) commandSocket = new Socket("localhost", this.comPort);
          commandWriter = new PrintStream(commandSocket.getOutputStream());
          commandReader = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
         
          if(eventSocket == null) eventSocket = new Socket("localhost", this.evPort);
          eventReader = new BufferedReader(new InputStreamReader(eventSocket.getInputStream()));
         
          break;
        }catch (IOException e) {
          if(i == RETRY - 1){
            XVRUtils.setDebugSession(false);
            XVRUtils.displayWarning("Warning!\n" +
                "Debugger connection to the XVR Virtual Machine has timed out. The debugger functionalities will be inactive for this session." +
                "\n\nPlease note that debug for Full Screen is currently not supported.");
            return Status.OK_STATUS;
          }
          else{
            try {
              Thread.sleep(5);
            } catch (InterruptedException e1) {}
          }
        }
      }
     
      DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(XVRDebugTarget.this);
     
      //Starts fetch/decode/execute cycles
      String event = "";
      while (!isTerminated() && event != null) {
        if(monitor.isCanceled() || this.canceled)
          return Status.OK_STATUS;
        try {
          event = eventReader.readLine();
          System.out.println("Event reached: " + event);
          if (event != null) {
            if(event.startsWith("Breakpoint")){
              breakpointHit(event);
            }else if(event.startsWith("Resumed")){
              resumed(event);
            }else if(event.startsWith("Stopped")){
              terminated();
              break;
            }else if(event.startsWith("Started")){
              started();
            }
          }
        } catch (IOException e) {
          terminated();
        }
      }
      return Status.OK_STATUS;
    }
  }
 
  public XVRDebugTarget(ILaunch launch, IProcess process, int commandPort, int eventPort, ProcessExitHandler pExit) throws DebugException{
    super(null);
   
    pExit.addListener(new IProcessExitListener() {
      @Override
      public void processFinished() {
        eventDispatch.cancel();
      }
    });
   
    this.launch = launch;
    this.process = process;
   
    this.mainThread = new VMThread(XVRDebugTarget.this);
    this.threads = new IThread[] {mainThread};
   
    this.eventDispatch = new EventDispatchJob(commandPort, eventPort);
    this.eventDispatch.schedule();
   
  }

  @Override
  public String getName() throws DebugException {
    if (name == null) {
      name = "XVR Virtual Machine";
      try {
        name = "XVR Virtual Machine: " + getLaunch().getLaunchConfiguration().getAttribute(IXVRConstants.ATTR_XVR_MAIN, "bin file");
        if(name.endsWith(".s3d")) name = name.substring(0, name.length() - 4) + ".bin";
      } catch (CoreException e) {
      }
    }
    return name;
  }

  @Override
  public IProcess getProcess() {
    return this.process;
  }

  @Override
  public IThread[] getThreads() throws DebugException {
    return threads;
  }

  @Override
  public boolean hasThreads() throws DebugException {
    return threads.length != 0;
  }

  @Override
  public boolean supportsBreakpoint(IBreakpoint breakpoint) {
    if(this.isTerminated()) return false;
    if(!breakpoint.getModelIdentifier().equals(IXVRConstants.ID_XVR_DEBUG_MODEL)) return false;
    return true;
  }

  @Override
  public IDebugTarget getDebugTarget() {
    return this;
  }

  @Override
  public ILaunch getLaunch() {
    return launch;
  }

  @Override
  public String getModelIdentifier() {
    return IXVRConstants.ID_XVR_DEBUG_MODEL;
  }

  @Override
  public boolean canTerminate() {
    return process.canTerminate();
  }

  @Override
  public boolean isTerminated() {
    return process.isTerminated();
  }

  @Override
  public void terminate() throws DebugException {
    sendRequest("exit");
  }

  @Override
  public boolean canResume() {
    return !isTerminated() && isSuspended();
  }

  @Override
  public boolean canSuspend() {
    return false; //return !isTerminated() && !isSuspended();
  }

  @Override
  public boolean isSuspended() {
    return suspended;
  }

  @Override
  public void resume() throws DebugException {
    sendRequest("continue");
  }

  @Override
  public void suspend() throws DebugException {
    // TODO Auto-generated method stub
  }

  @Override
  public void breakpointAdded(IBreakpoint breakpoint) {
    try {
      if(supportsBreakpoint(breakpoint) && breakpoint.isEnabled()) addBreakpoint((XVRBreakpoint)breakpoint);
    } catch (CoreException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
    if (supportsBreakpoint(breakpoint)) {
      try {
        if (breakpoint.isEnabled()) {
          breakpointAdded(breakpoint);
        } else {
          breakpointRemoved(breakpoint, null);
        }
      } catch (CoreException e) {
      }
    }
  }

  @Override
  public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
    try{
      if(supportsBreakpoint(breakpoint) && breakpoint.isEnabled()) removeBreakpoint((XVRBreakpoint) breakpoint);
    }catch(CoreException e){
      e.printStackTrace();
    }
  }

  @Override
  public boolean canDisconnect() {
    return false;
  }

  @Override
  public void disconnect() throws DebugException {
  }

  @Override
  public boolean isDisconnected() {
    return false;
  }

  @Override
  public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
    return null;
  }

  @Override
  public boolean supportsStorageRetrieval() {
    return false;
  }
 
  public void stepInto() throws DebugException{
    sendRequest("step");
  }
 
  public void stepOver() throws DebugException{
    sendRequest("next");
  }
 
  public IStackFrame[] getStackFrames(){
    return frames;
  }
 
  public IStackFrame[] updateStackFrames() throws DebugException {
    synchronized(commandSocket){
      if(commandSocket.isClosed()) return new IStackFrame[0];
     
      commandWriter.println("bt");
      commandWriter.flush();
      try{
        commandReader.readLine(); //read ok
        String framesData = commandReader.readLine();
        JSONObject answer = (JSONObject)JSONValue.parse(framesData);
        if(answer == null) return new IStackFrame[0];
       
        //System.out.println(answer.toJSONString());
       
        JSONArray frames = (JSONArray)answer.get("stackframes");
        IStackFrame[] theFrames = new IStackFrame[frames.size()];
       
        try{
          for(int i = 0; i < frames.size(); i++)
            theFrames[i] = new XVRStackFrame(launch.getLaunchConfiguration(), mainThread, (JSONObject)frames.get(i), i);
        } catch (CoreException e) {
          abort("Unable to retrieve a stack frame", e);
        }
       
        return theFrames;
       
      }catch(IOException e){
        abort("Unable to retrieve stack frames", e);
      }
    }
   
    return new IStackFrame[0];
  }
 
  private void started(){
    XVRUtils.setDebugSession(true);
    fireCreationEvent();
    mainThread.fireCreationEvent();
    installDeferredBreakpoints();
    try {
      resume();
    } catch (DebugException e) {
      e.printStackTrace();
    }
  }
 
  private void installDeferredBreakpoints() {
    IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
    for(int i = 0; i < breakpoints.length; i++)
      if(supportsBreakpoint(breakpoints[i])) addBreakpoint((XVRBreakpoint)breakpoints[i]);
  }

  private void terminated(){
    threads = new IThread[0];
    suspended = false;
    DebugPlugin.getDefault().getBreakpointManager().removeBreakpointListener(this);
    mainThread.fireTerminateEvent();
    fireTerminateEvent();
    //XVRUtils.setDebugSession(false);
    XVRUtils.switchPerspective(XVRPerspectiveFactory.getPerspectiveID());
  }
 
  private void resumed(String event){
    Pattern pattern = Pattern.compile("Resumed by (.*)");
    Matcher matcher = pattern.matcher(event);
    if(matcher.matches()){
      suspended = false;
     
      if(matcher.group(1).startsWith("client")){
        mainThread.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
      }else if(matcher.group(1).startsWith("step into")){
        mainThread.setStepping(true);
        mainThread.fireResumeEvent(DebugEvent.STEP_INTO);
      }else{
        mainThread.setStepping(true);
        mainThread.fireResumeEvent(DebugEvent.STEP_OVER);
      }
    }
  }

  private void addBreakpoint(XVRBreakpoint breakpoint){
    try {
      IResource res = breakpoint.getMarker().getResource();
      int line = breakpoint.getLineNumber();
      String filename = null;
      if(res.isLinked())
        filename = XVRUtils.getResourceName(res);
      else
        filename = breakpoint.getMarker().getResource().getProjectRelativePath().toString();
      if(filename == null){
        XVRUtils.displayWarning("Unable to add breakpoint at:\nFile: " + res.getName() + "\nLine: " + line);
        return;
      }
      filename = filename.replace("\\", "/");
     
      sendRequest("break " + filename + ":" + line);
    } catch (CoreException e) {
      e.printStackTrace();
    }
  }
 
  private void removeBreakpoint(XVRBreakpoint breakpoint){
    try {
      String filename = breakpoint.getMarker().getResource().getProjectRelativePath().toString();
      int line = breakpoint.getLineNumber();
      sendRequest("delete " + filename + ":" + line);
    } catch (CoreException e) {
      e.printStackTrace();
    }
  }
 
  private void sendRequest(String request) throws DebugException {
    synchronized (commandSocket) {
      commandWriter.println(request);
      commandWriter.flush();
      try {
        /*String line = */commandReader.readLine();
        //System.out.println(line);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }   
  }
 
  private void breakpointHit(String event){
    try {
      frames = updateStackFrames();
    } catch (DebugException e) {
      e.printStackTrace();
    }

    suspended = true;
    if(mainThread.isStepping()){
      mainThread.setStepping(false);
      mainThread.fireSuspendEvent(DebugEvent.STEP_END);
    }else mainThread.fireSuspendEvent(DebugEvent.BREAKPOINT);
  }
 
  private void abort(String message, Throwable e) throws DebugException {
    throw new DebugException(new Status(IStatus.ERROR, IXVRConstants.ID_XVR_DEBUG_MODEL, 0, message, e));
  }
 
  public String evaluate(IDebugElement context, String expression) throws DebugException{
    String evaluation = null;
    changeFrame(context);
   
    synchronized(commandSocket){
      if(commandSocket.isClosed()) return null;
     
      commandWriter.println("print " + expression);
      commandWriter.flush();
     
      try {
        commandReader.readLine();
        evaluation = commandReader.readLine();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
   
    restoreFrame();
    return evaluation;
  }
 
  private void changeFrame(IDebugElement context) throws DebugException{
    if(context instanceof XVRStackFrame){
      XVRStackFrame stackframe = (XVRStackFrame)context;
      sendRequest("frame " + stackframe.getFrameID());
    }
  }
 
  private void restoreFrame() throws DebugException{
    sendRequest("frame 0");
  }
}
TOP

Related Classes of xvrengine.debug.XVRDebugTarget$EventDispatchJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.