Package org.eclipse.php.internal.debug.core.launching

Source Code of org.eclipse.php.internal.debug.core.launching.PHPWebPageLaunchDelegate

/*******************************************************************************
* Copyright (c) 2009 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
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.debug.core.launching;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.*;
import org.eclipse.debug.core.model.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.php.debug.core.debugger.launching.ILaunchDelegateListener;
import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys;
import org.eclipse.php.internal.debug.core.IPHPDebugConstants;
import org.eclipse.php.internal.debug.core.Logger;
import org.eclipse.php.internal.debug.core.PHPDebugCoreMessages;
import org.eclipse.php.internal.debug.core.PHPDebugPlugin;
import org.eclipse.php.internal.debug.core.preferences.PHPProjectPreferences;
import org.eclipse.php.internal.debug.core.zend.communication.DebuggerCommunicationDaemon;
import org.eclipse.php.internal.debug.core.zend.debugger.IDebuggerInitializer;
import org.eclipse.php.internal.debug.core.zend.debugger.PHPSessionLaunchMapper;
import org.eclipse.php.internal.debug.core.zend.debugger.PHPWebServerDebuggerInitializer;
import org.eclipse.php.internal.debug.daemon.DaemonPlugin;
import org.eclipse.php.internal.server.core.Server;
import org.eclipse.php.internal.server.core.manager.ServersManager;
import org.eclipse.php.internal.server.core.tunneling.SSHTunnel;
import org.eclipse.swt.widgets.Display;

/**
* A launch configuration delegate class for launching a PHP web page script.
*
* @author shalom
*
*/
public class PHPWebPageLaunchDelegate extends LaunchConfigurationDelegate {

  private static final String ILAUNCH_LISTENER_EXTENTION_ID = "org.eclipse.php.debug.core.phpLaunchDelegateListener"; //$NON-NLS-1$
  protected Job runDispatch;
  protected ILaunch launch;
  protected IDebuggerInitializer debuggerInitializer;

  public PHPWebPageLaunchDelegate() {
    debuggerInitializer = createDebuggerInitilizer();
    registerLaunchListeners();
  }

  /*
   * list of registered ILaunchDelegateListeners
   */
  List<ILaunchDelegateListener> launchListeners = new ArrayList<ILaunchDelegateListener>();

  /**
   * register new a LaunchDelegateListener
   *
   * @param listener
   *            - ILaunchDelegateListener listener instance
   */
  private void addLaunchDelegateListener(ILaunchDelegateListener listener) {
    Assert.isNotNull(listener);
    launchListeners.add(listener);
  }

  /*
   * notify all registered ILaunchDelegateListener listeners launch is about
   * to be invoked
   *
   * @see
   * org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.
   * eclipse.debug.core.ILaunchConfiguration, java.lang.String,
   * org.eclipse.debug.core.ILaunch,
   * org.eclipse.core.runtime.IProgressMonitor)
   */
  protected int notifyPreLaunch(ILaunchConfiguration configuration,
      String mode, ILaunch launch, IProgressMonitor monitor) {
    for (ILaunchDelegateListener listener : launchListeners) {
      int returnCode = listener.preLaunch(configuration, mode, launch,
          monitor);
      if (returnCode != 0) {
        return returnCode;
      }
    }
    return 0;
  }

  /**
   * registers all ILAUNCH_LISTENER_EXTENTION_ID listeners
   */
  private void registerLaunchListeners() {
    IConfigurationElement[] config = Platform.getExtensionRegistry()
        .getConfigurationElementsFor(ILAUNCH_LISTENER_EXTENTION_ID);
    try {
      for (IConfigurationElement e : config) {

        final Object o = e.createExecutableExtension("class"); //$NON-NLS-1$
        if (o instanceof ILaunchDelegateListener) {
          ISafeRunnable runnable = new ISafeRunnable() {

            public void run() throws Exception {
              ILaunchDelegateListener listener = (ILaunchDelegateListener) o;
              addLaunchDelegateListener(listener);
            }

            public void handleException(Throwable exception) {
              System.out.println("One of the" //$NON-NLS-1$
                  + ILAUNCH_LISTENER_EXTENTION_ID
                  + "extensions fail"); //$NON-NLS-1$
            }
          };
          SafeRunner.run(runnable);
        }
      }
    } catch (CoreException ex) {
      System.out.println(ex.getMessage());
    }
  }

  /**
   * Override the extended getLaunch to create a PHPLaunch.
   */
  public ILaunch getLaunch(ILaunchConfiguration configuration, String mode)
      throws CoreException {
    return new PHPLaunch(configuration, mode, null);
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org.eclipse.php.internal.server.core.launch.IHTTPServerLaunch#launch(
   * org.eclipse.debug.core.ILaunchConfiguration, java.lang.String,
   * org.eclipse.debug.core.ILaunch,
   * org.eclipse.core.runtime.IProgressMonitor)
   */
  public void launch(ILaunchConfiguration configuration, String mode,
      ILaunch launch, IProgressMonitor monitor) throws CoreException {

    // notify all listeners of a preLaunch event.
    int rc = notifyPreLaunch(configuration, mode, launch, monitor);
    if (rc != 0) { // cancel launch
      monitor.setCanceled(true);
      monitor.done();
      return; // canceled
    }
    // Check that the debug daemon is functional
    // DEBUGGER - Make sure that the active debugger id is indeed Zend's
    // debugger
    if (!DaemonPlugin.getDefault().validateCommunicationDaemons(
        DebuggerCommunicationDaemon.ZEND_DEBUGGER_ID)) {
      monitor.setCanceled(true);
      monitor.done();
      return;
    }
    // Check for previous launches
    if (!PHPLaunchUtilities.notifyPreviousLaunches(launch)) {
      monitor.setCanceled(true);
      monitor.done();
      return;
    }
    if (!PHPLaunchUtilities.checkDebugAllPages(configuration, launch)) {
      monitor.setCanceled(true);
      monitor.done();
      return;
    }
    PHPLaunchUtilities.showDebugView();
    this.launch = launch;
    Server server = ServersManager.getServer(configuration.getAttribute(
        Server.NAME, "")); //$NON-NLS-1$
    if (server == null) {
      Logger.log(Logger.ERROR,
          "Launch configuration could not find server"); //$NON-NLS-1$
      terminated();
      // throw CoreException();
      return;
    }
    String fileName = configuration.getAttribute(Server.FILE_NAME,
        (String) null);
    // Get the project from the file name
    IPath filePath = new Path(fileName);
    IProject proj = null;
    try {
      proj = ResourcesPlugin.getWorkspace().getRoot()
          .getProject(filePath.segment(0));
    } catch (Throwable t) {
    }

    ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy();
    String project = proj.getFullPath().toString();
    wc.setAttribute(IPHPDebugConstants.PHP_Project, project);

    // Set transfer encoding:
    wc.setAttribute(IDebugParametersKeys.TRANSFER_ENCODING,
        PHPProjectPreferences.getTransferEncoding(proj));
    wc.setAttribute(IDebugParametersKeys.OUTPUT_ENCODING,
        PHPProjectPreferences.getOutputEncoding(proj));
    wc.setAttribute(IDebugParametersKeys.PHP_DEBUG_TYPE,
        IDebugParametersKeys.PHP_WEB_PAGE_DEBUG);
    wc.doSave();

    String URL = new String(configuration.getAttribute(Server.BASE_URL, "") //$NON-NLS-1$
        .getBytes());
    boolean isDebugLaunch = mode.equals(ILaunchManager.DEBUG_MODE);
    if (isDebugLaunch) {
      boolean stopAtFirstLine = wc.getAttribute(
          IDebugParametersKeys.FIRST_LINE_BREAKPOINT,
          PHPProjectPreferences.getStopAtFirstLine(proj));
      launch.setAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT,
          Boolean.toString(stopAtFirstLine));
    }
    int requestPort = PHPDebugPlugin
        .getDebugPort(DebuggerCommunicationDaemon.ZEND_DEBUGGER_ID);

    // Generate a session id for this launch and put it in the map
    int sessionID = DebugSessionIdGenerator.generateSessionID();
    PHPSessionLaunchMapper.put(sessionID, launch);

    // Fill all rest of the attributes:
    launch.setAttribute(IDebugParametersKeys.PORT,
        Integer.toString(requestPort));
    launch.setAttribute(IDebugParametersKeys.WEB_SERVER_DEBUGGER,
        Boolean.toString(true));
    launch.setAttribute(IDebugParametersKeys.ORIGINAL_URL, URL);
    launch.setAttribute(IDebugParametersKeys.SESSION_ID,
        Integer.toString(sessionID));

    // Trigger the session by initiating a debug request to the debug server
    runDispatch = new RunDispatchJobWebServer(launch);
    runDispatch.schedule();
  }

  /*
   * Override the super preLaunchCheck to make sure that the server we are
   * using is still valid. If not, notify the user that a change should be
   * made and open the launch configuration page to do so.
   *
   * @see
   * org.eclipse.debug.core.model.LaunchConfigurationDelegate#preLaunchCheck
   * (org.eclipse.debug.core.ILaunchConfiguration, java.lang.String,
   * org.eclipse.core.runtime.IProgressMonitor)
   */
  public boolean preLaunchCheck(final ILaunchConfiguration configuration,
      final String mode, IProgressMonitor monitor) throws CoreException {
    // Check if the server exists
    final String serverName = configuration.getAttribute(Server.NAME, ""); //$NON-NLS-1$
    Server server = ServersManager.getServer(serverName);
    if (server == null) {
      Display.getDefault().asyncExec(new Runnable() {
        public void run() {
          MessageDialog
              .openWarning(
                  Display.getDefault().getActiveShell(),
                  PHPDebugCoreMessages.PHPLaunchUtilities_phpLaunchTitle,
                  NLS.bind(
                      PHPDebugCoreMessages.PHPWebPageLaunchDelegate_serverNotFound,
                      new String[] { serverName }));
          PHPLaunchUtilities.openLaunchConfigurationDialog(
              configuration, mode);
        }
      });
      return false;
    }

    return super.preLaunchCheck(configuration, mode, monitor);
  }

  /**
   * Initiate a debug session.
   *
   * @param launch
   */
  protected void initiateDebug(ILaunch launch) {
    try {
      // Initiate a debug tunnel in case needed.
      if (!ILaunchManager.RUN_MODE.equals(launch.getLaunchMode())) {
        SSHTunnel tunnel = PHPLaunchUtilities.getSSHTunnel(launch
            .getLaunchConfiguration());
        if (tunnel != null) {
          tunnel.connect();
        }
      }
      debuggerInitializer.debug(launch);
    } catch (DebugException e) {
      IStatus status = e.getStatus();
      String errorMessage = null;
      if (status == null) {
        Logger.traceException(
            "Unexpected Error return from debuggerInitializer ", e); //$NON-NLS-1$
        fireError(PHPDebugCoreMessages.Debugger_Unexpected_Error_1, e);
        errorMessage = PHPDebugCoreMessages.Debugger_Unexpected_Error_1;
      } else {
        fireError(status);
        errorMessage = status.getMessage();
      }
      displayErrorMessage(errorMessage);
    }
  }

  /**
   * Create an {@link IDebuggerInitializer}.
   *
   * @return An {@link IDebuggerInitializer} instance.
   */
  protected IDebuggerInitializer createDebuggerInitilizer() {
    return new PHPWebServerDebuggerInitializer();
  }

  /**
   * Displays a dialod with an error message.
   *
   * @param message
   *            The error to display.
   */
  protected void displayErrorMessage(final String message) {
    Display.getDefault().asyncExec(new Runnable() {
      public void run() {
        MessageDialog.openError(Display.getDefault().getActiveShell(),
            PHPDebugCoreMessages.PHPWebPageLaunchDelegate_0, message);
      }
    });
  }

  /**
   * Throws a IStatus in a Debug Event
   *
   */
  public void fireError(IStatus status) {
    DebugEvent event = new DebugEvent(this, DebugEvent.MODEL_SPECIFIC);
    event.setData(status);
    fireEvent(event);
  }

  /**
   * Throws a IStatus in a Debug Event
   *
   */
  public void fireError(String errorMessage, Exception e) {
    Status status = new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
        IPHPDebugConstants.INTERNAL_ERROR, errorMessage, e);
    DebugEvent event = new DebugEvent(this, DebugEvent.MODEL_SPECIFIC);
    event.setData(status);
    fireEvent(event);
  }

  /**
   * Called when the debug session was terminated.
   */
  public void terminated() {
    DebugEvent event = null;
    if (launch.getDebugTarget() == null) {
      // We have to force the termination of the ILaunch because at this
      // stage there is no
      // PHPDebugTarget, thus we create a dummy debug target to overcome
      // this issue and terminate the launch.
      IDebugTarget dummyDebugTarget = new DummyDebugTarget(launch);
      event = new DebugEvent(dummyDebugTarget, DebugEvent.TERMINATE);
      if (launch != null) {
        launch.addDebugTarget(dummyDebugTarget);
        IDebugEventSetListener launchListener = (IDebugEventSetListener) launch;
        launchListener.handleDebugEvents(new DebugEvent[] { event });
      }
    }
    event = new DebugEvent(this, DebugEvent.TERMINATE);
    fireEvent(event);
  }

  /**
   * Fires a debug event
   *
   * @param event
   *            The event to be fired
   */
  public void fireEvent(DebugEvent event) {
    DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { event });
  }

  /*
   * Run is seperate thread so launch doesn't hang.
   */
  protected class RunDispatchJobWebServer extends Job {
    private ILaunch launch;

    public RunDispatchJobWebServer(ILaunch launch) {
      super("RunDispatchJobWebServer"); //$NON-NLS-1$
      this.launch = launch;
      setSystem(true);
    }

    protected IStatus run(IProgressMonitor monitor) {
      initiateDebug(launch);
      Logger.debugMSG("Terminating debug session: calling PHPDebugTarget.terminate()"); //$NON-NLS-1$
      terminated();
      return Status.OK_STATUS;
    }
  }

  private static IThread[] EMPTY_THREADS = new IThread[0];

  /*
   * A dummy debug target for the termination of the ILaunch.
   */
  private class DummyDebugTarget implements IDebugTarget {

    private ILaunch launch;

    public DummyDebugTarget(ILaunch launch) {
      this.launch = launch;
    }

    public String getName() throws DebugException {
      return "Session Terminated"; //$NON-NLS-1$
    }

    public IProcess getProcess() {
      return null;
    }

    public IThread[] getThreads() throws DebugException {
      return EMPTY_THREADS;
    }

    public boolean hasThreads() throws DebugException {
      return false;
    }

    public boolean supportsBreakpoint(IBreakpoint breakpoint) {
      return false;
    }

    public IDebugTarget getDebugTarget() {
      return this;
    }

    public ILaunch getLaunch() {
      return launch;
    }

    public String getModelIdentifier() {
      return ""; //$NON-NLS-1$
    }

    public Object getAdapter(Class adapter) {
      return null;
    }

    public boolean canTerminate() {
      return false;
    }

    public boolean isTerminated() {
      return true;
    }

    public void terminate() throws DebugException {
    }

    public boolean canResume() {
      return false;
    }

    public boolean canSuspend() {
      return false;
    }

    public boolean isSuspended() {
      return false;
    }

    public void resume() throws DebugException {
    }

    public void suspend() throws DebugException {
    }

    public void breakpointAdded(IBreakpoint breakpoint) {
    }

    public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
    }

    public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
    }

    public boolean canDisconnect() {
      return false;
    }

    public void disconnect() throws DebugException {
    }

    public boolean isDisconnected() {
      return false;
    }

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

    public boolean supportsStorageRetrieval() {
      return false;
    }
  }
}
TOP

Related Classes of org.eclipse.php.internal.debug.core.launching.PHPWebPageLaunchDelegate

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.