/******************************************************************************* * 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.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; import org.eclipse.debug.core.*; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.LaunchConfigurationDelegate; 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.*; import org.eclipse.php.internal.debug.core.pathmapper.PathMapperRegistry; import org.eclipse.php.internal.debug.core.preferences.PHPProjectPreferences; import org.eclipse.php.internal.debug.core.xdebug.IDELayerFactory; import org.eclipse.php.internal.debug.core.xdebug.XDebugPreferenceMgr; import org.eclipse.php.internal.debug.core.xdebug.communication.XDebugCommunicationDaemon; import org.eclipse.php.internal.debug.core.xdebug.dbgp.DBGpBreakpointFacade; import org.eclipse.php.internal.debug.core.xdebug.dbgp.DBGpProxyHandler; import org.eclipse.php.internal.debug.core.xdebug.dbgp.DBGpProxyHandlersManager; import org.eclipse.php.internal.debug.core.xdebug.dbgp.XDebugDebuggerSettingsUtil; import org.eclipse.php.internal.debug.core.xdebug.dbgp.model.DBGpMultiSessionTarget; import org.eclipse.php.internal.debug.core.xdebug.dbgp.model.DBGpTarget; import org.eclipse.php.internal.debug.core.xdebug.dbgp.model.IDBGpDebugTarget; import org.eclipse.php.internal.debug.core.xdebug.dbgp.session.DBGpSessionHandler; import org.eclipse.php.internal.debug.core.xdebug.dbgp.session.IDBGpSessionListener; 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; @SuppressWarnings("restriction") public class XDebugWebLaunchConfigurationDelegate extends LaunchConfigurationDelegate { private static final String LAUNCH_LISTENERS_EXTENSION_ID = "org.eclipse.php.debug.core.phpLaunchDelegateListener"; //$NON-NLS-1$ /* * list of registered ILaunchDelegateListeners */ private List<ILaunchDelegateListener> preLaunchListeners = new ArrayList<ILaunchDelegateListener>(); public XDebugWebLaunchConfigurationDelegate() { registerLaunchListeners(); } /* * (non-Javadoc) * * @see * org.eclipse.debug.core.model.LaunchConfigurationDelegate#getLaunch(org. * eclipse.debug.core.ILaunchConfiguration, java.lang.String) */ @Override public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException { return new XDebugLaunch(configuration, mode, null); } /* * (non-Javadoc) * * @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) */ public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { // Notify all listeners of a pre-launch event. int resultCode = notifyPreLaunch(configuration, mode, launch, monitor); if (resultCode != 0) { // cancel launch monitor.setCanceled(true); monitor.done(); return; // canceled } if (mode.equals(ILaunchManager.DEBUG_MODE)) { if (XDebugLaunchListener.getInstance().isWebLaunchActive()) { displayErrorMessage(PHPDebugCoreMessages.XDebug_WebLaunchConfigurationDelegate_0); DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); return; } PHPLaunchUtilities.showDebugView(); } // Resolve the server 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$ displayErrorMessage(PHPDebugCoreMessages.XDebug_WebLaunchConfigurationDelegate_1); DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); return; } // Get the project from the file name String fileName = configuration.getAttribute(Server.FILE_NAME, (String) null); IPath filePath = new Path(fileName); IProject proj = null; try { proj = ResourcesPlugin.getWorkspace().getRoot().getProject(filePath.segment(0)); } catch (Throwable t) { if (proj == null) { Logger.logException("Could not execute the debug (Project is null).", t); //$NON-NLS-1$ DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); return; } } // Save the project name for source lookup ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy(); String project = proj.getFullPath().toString(); wc.setAttribute(IPHPDebugConstants.PHP_Project, project); wc.setAttribute(IDebugParametersKeys.TRANSFER_ENCODING, PHPProjectPreferences.getTransferEncoding(proj)); wc.setAttribute(IDebugParametersKeys.OUTPUT_ENCODING, PHPProjectPreferences.getOutputEncoding(proj)); wc.doSave(); /* * Determine stop at first line (first calculate the default and then * try to extract the configuration attribute). */ boolean stopAtFirstLine = PHPProjectPreferences.getStopAtFirstLine(proj); stopAtFirstLine = wc.getAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT, stopAtFirstLine); /* * Generate a session id for this launch and start the listener then * create the start and stop debug URLs */ String[] startStopURLs; String baseURL = new String(configuration.getAttribute(Server.BASE_URL, "").getBytes()); //$NON-NLS-1$ IDBGpDebugTarget target = null; SSHTunnel tunnel = null; if (mode.equals(ILaunchManager.DEBUG_MODE)) { String sessionId = DBGpSessionHandler.getInstance().generateSessionId(); String ideKey = null; DBGpProxyHandler proxyHandler = DBGpProxyHandlersManager.INSTANCE.getHandler(server.getUniqueId()); if (proxyHandler != null && proxyHandler.useProxy()) { ideKey = proxyHandler.getCurrentIdeKey(); if (proxyHandler.registerWithProxy() == false) { displayErrorMessage( PHPDebugCoreMessages.XDebug_WebLaunchConfigurationDelegate_2 + proxyHandler.getErrorMsg()); DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); return; } } else { ideKey = DBGpSessionHandler.getInstance().getIDEKey(); } startStopURLs = generateStartStopDebugURLs(baseURL, sessionId, ideKey); String launchScript = configuration.getAttribute(Server.FILE_NAME, (String) null); // Check if a tunneled connection is needed and create request for a // tunnel if needed. tunnel = PHPLaunchUtilities.getSSHTunnel(configuration); // determine if we should use the multisession manager or the single // session manager if (XDebugPreferenceMgr.useMultiSession() == true) { target = new DBGpMultiSessionTarget(launch, launchScript, startStopURLs[1], ideKey, stopAtFirstLine); target.setPathMapper(PathMapperRegistry.getByServer(server)); launch.addDebugTarget(target); // has to be added now, not } else { target = new DBGpTarget(launch, launchScript, startStopURLs[1], ideKey, null, stopAtFirstLine); target.setPathMapper(PathMapperRegistry.getByServer(server)); IProcess process = new PHPProcess(launch, PHPDebugCoreMessages.XDebugWebLaunchConfigurationDelegate_PHP_process); process.setAttribute(IProcess.ATTR_PROCESS_TYPE, IPHPDebugConstants.PHPProcessType); ((DBGpTarget) target).setProcess(process); ((PHPProcess) process).setDebugTarget(target); launch.addProcess(process); } DBGpSessionHandler.getInstance().addSessionListener((IDBGpSessionListener) target); int requestPort = getDebugPort(server); if (!PHPLaunchUtilities.isDebugDaemonActive(requestPort, XDebugCommunicationDaemon.XDEBUG_DEBUGGER_ID)) { PHPLaunchUtilities.showLaunchErrorMessage(NLS.bind( PHPDebugCoreMessages.WebLaunchConfigurationDelegate_PortInUse, requestPort, server.getName())); monitor.setCanceled(true); monitor.done(); return; } } else { startStopURLs = new String[] { baseURL, null }; } final String startURL = startStopURLs[0]; // Will be used in the future? @SuppressWarnings("unused") final SSHTunnel sshTunnel = tunnel; // load the URL into the appropriate web browser monitor.beginTask("", 10); //$NON-NLS-1$ monitor.subTask(PHPDebugCoreMessages.XDebug_WebLaunchConfigurationDelegate_3); try { PHPDebugUtil.openLaunchURL(startURL); } catch (Exception e) { if (mode.equals(ILaunchManager.DEBUG_MODE)) { DBGpSessionHandler.getInstance().removeSessionListener((IDBGpSessionListener) target); } DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); monitor.done(); return; } monitor.worked(5); if (mode.equals(ILaunchManager.DEBUG_MODE)) { launch.addDebugTarget(target); monitor.subTask(PHPDebugCoreMessages.XDebug_WebLaunchConfigurationDelegate_4); if (target != null) { target.waitForInitialSession((DBGpBreakpointFacade) IDELayerFactory.getIDELayer(), XDebugPreferenceMgr.createSessionPreferences(), monitor); } } else { /* * launched is not in debug mode, so remove the launch from the * debug view as we are not debugging anything. */ DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); } monitor.worked(5); monitor.done(); } /** * generate the URLS that start the debug environment and stop the debug * environment. * * @param baseURL * the base URL * @param sessionId * the DBGp session Id * @param ideKey * the DBGp IDE Key * @return start and stop queries */ protected String[] generateStartStopDebugURLs(String baseURL, String sessionId, String ideKey) { String[] startStopURLs = new String[2]; if (baseURL.indexOf("?") > -1) { //$NON-NLS-1$ baseURL += "&"; //$NON-NLS-1$ } else { baseURL += "?"; //$NON-NLS-1$ } startStopURLs[0] = baseURL + "XDEBUG_SESSION_START=" + ideKey + "&KEY=" + sessionId; //$NON-NLS-1$ //$NON-NLS-2$ startStopURLs[1] = baseURL + "XDEBUG_SESSION_STOP_NO_EXEC=" + ideKey + "&KEY=" + sessionId; //$NON-NLS-1$ //$NON-NLS-2$ return startStopURLs; } protected int getDebugPort(Server server) { // Set custom port if any from debugger's owner settings int customRequestPort = XDebugDebuggerSettingsUtil.getDebugPort(server.getUniqueId()); if (customRequestPort != -1) return customRequestPort; return PHPDebugPlugin.getDebugPort(XDebugCommunicationDaemon.XDEBUG_DEBUGGER_ID); } /** * Displays a dialog 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.XDebugMessage_debugError, message); } }); } protected int notifyPreLaunch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) { for (ILaunchDelegateListener listener : preLaunchListeners) { int returnCode = listener.preLaunch(configuration, mode, launch, monitor); if (returnCode != 0) { return returnCode; } } return 0; } /** * Registers all pre-launch listeners. */ private void registerLaunchListeners() { IConfigurationElement[] config = Platform.getExtensionRegistry() .getConfigurationElementsFor(LAUNCH_LISTENERS_EXTENSION_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; Assert.isNotNull(listener); preLaunchListeners.add(listener); } public void handleException(Throwable exception) { Logger.logException(exception); } }; SafeRunner.run(runnable); } } } catch (CoreException ex) { Logger.logException(ex); } } }