/******************************************************************************* * Copyright (c) 2009, 2010 Sven Kiera * 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 *******************************************************************************/ package org.phpsrc.eclipse.pti.core.launching; import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.IStreamListener; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IStreamMonitor; import org.eclipse.debug.ui.CommonTab; import org.eclipse.debug.ui.RefreshTab; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.PHPDebugCoreMessages; import org.eclipse.php.internal.debug.core.launching.PHPLaunch; import org.eclipse.php.internal.debug.core.launching.PHPLaunchUtilities; import org.eclipse.php.internal.debug.core.phpIni.PHPINIUtil; import org.eclipse.swt.widgets.Display; import org.phpsrc.eclipse.pti.core.PHPToolCorePlugin; import org.phpsrc.eclipse.pti.core.listener.IOutputListener; @SuppressWarnings("restriction") public class PHPToolExecutableLauncher { protected ListenerList outputListenerList = new ListenerList(); public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException { return new PHPLaunch(configuration, mode, null); } public IProcess launch(ILaunchConfiguration configuration) throws CoreException { return launch(configuration, new NullProgressMonitor()); } public IProcess launch(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException { return launch(configuration, getLaunch(configuration, ILaunchManager.RUN_MODE), monitor); } public IProcess launch(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) throws CoreException { String phpExeString = configuration.getAttribute( IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, (String) null); String phpIniPath = configuration.getAttribute( IPHPDebugConstants.ATTR_INI_LOCATION, (String) null); String fileName = configuration.getAttribute( IPHPDebugConstants.ATTR_FILE_FULL_PATH, (String) null); if (monitor.isCanceled()) { return null; } if (fileName == null || fileName.equals("")) { displayErrorMessage("Please set a valid PHP file for this launch."); return null; } if (phpExeString == null || phpExeString.equals("")) { displayErrorMessage("Please set a valid PHP executable for this launch."); return null; } SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10); // Locate the php.ini by using the attribute. If the attribute was null, // try to locate an php.ini that exists next to the executable. File phpIni = (phpIniPath != null && new File(phpIniPath).exists()) ? new File( phpIniPath) : PHPINIUtil.findPHPIni(phpExeString); launch.setAttribute(IDebugParametersKeys.PHP_INI_LOCATION, phpIni.getAbsolutePath()); // resolve location IPath phpExe = new Path(phpExeString); String[] envp = DebugPlugin.getDefault().getLaunchManager() .getEnvironment(configuration); File phpExeFile = new File(phpExeString); String phpIniLocation = launch .getAttribute(IDebugParametersKeys.PHP_INI_LOCATION); // Determine PHP configuration file location: String phpConfigDir = phpExeFile.getParent(); if (phpIniLocation != null && !phpIniLocation.equals("")) { phpConfigDir = new File(phpIniLocation).getParent(); } String[] args = PHPLaunchUtilities.getProgramArguments(launch .getLaunchConfiguration()); String[] cmdLine = PHPLaunchUtilities.getCommandLine( launch.getLaunchConfiguration(), OperatingSystem.escapePHPFileArg(phpExeString), phpConfigDir, OperatingSystem.escapeShellFileArg(fileName), args); // remove unwanted -n argument ArrayList<String> newCmdLineList = new ArrayList<String>(cmdLine.length); for (int i = 0; i < cmdLine.length; ++i) { if (!cmdLine[i].equals("-n")) newCmdLineList.add(cmdLine[i].replace( OperatingSystem.PLACEHOLDER_WHITESPACE, ' ')); } cmdLine = newCmdLineList.toArray(new String[0]); notifyOutputListener(cmdLine, ' '); notifyOutputListener("\n"); // Set library search path: if (!OperatingSystem.WINDOWS) { StringBuffer buf = new StringBuffer(); if (OperatingSystem.MAC) { //$NON-NLS-1$ //$NON-NLS-2$ buf.append("DYLD_LIBRARY_PATH"); //$NON-NLS-1$ } else { buf.append("LD_LIBRARY_PATH"); //$NON-NLS-1$ } buf.append('='); buf.append(phpExeFile.getParent()); String[] envpNew = new String[envp == null ? 1 : envp.length + 1]; if (envp != null) { System.arraycopy(envp, 0, envpNew, 0, envp.length); } envpNew[envpNew.length - 1] = buf.toString(); envp = envpNew; } if (monitor.isCanceled()) { return null; } File workingDir = new File(fileName).getParentFile(); Process p = workingDir.exists() ? DebugPlugin.exec(cmdLine, workingDir, envp) : DebugPlugin.exec(cmdLine, null, envp); IProcess process = null; // add process type to process attributes Map<String, String> processAttributes = new HashMap<String, String>(); String programName = phpExe.lastSegment(); String extension = phpExe.getFileExtension(); if (extension != null) { programName = programName.substring(0, programName.length() - (extension.length() + 1)); } programName = programName.toLowerCase(); processAttributes.put(IProcess.ATTR_PROCESS_TYPE, programName); if (p != null) { subMonitor = new SubProgressMonitor(monitor, 80); // 10+80 of 100; subMonitor .beginTask( MessageFormat .format("start launch", new Object[] { configuration.getName() }), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ process = DebugPlugin.newProcess(launch, p, phpExe.toOSString(), processAttributes); if (process == null) { p.destroy(); throw new CoreException(new Status(IStatus.ERROR, PHPToolCorePlugin.PLUGIN_ID, 0, null, null)); } IStreamListener outputListener = new IStreamListener() { public void streamAppended(String text, IStreamMonitor monitor) { notifyOutputListener(text); } }; process.getStreamsProxy().getErrorStreamMonitor() .addListener(outputListener); process.getStreamsProxy().getOutputStreamMonitor() .addListener(outputListener); subMonitor.done(); } process.setAttribute(IProcess.ATTR_CMDLINE, fileName); if (!CommonTab.isLaunchInBackground(configuration)) { // wait for process to exit while (!process.isTerminated()) { try { if (monitor.isCanceled()) { process.terminate(); break; } Thread.sleep(50); } catch (InterruptedException e) { } } // refresh resources subMonitor = new SubProgressMonitor(monitor, 10); // 10+80+10 of // 100; RefreshTab.refreshResources(configuration, subMonitor); } return process; } private void displayErrorMessage(final String message) { final Display display = Display.getDefault(); display.asyncExec(new Runnable() { public void run() { MessageDialog.openError(display.getActiveShell(), PHPDebugCoreMessages.Debugger_LaunchError_title, message); } }); } protected void notifyOutputListener(String output) { for (Object listener : outputListenerList.getListeners()) { ((IOutputListener) listener).handleOutput(output); } } protected void notifyOutputListener(String[] output, char glue) { StringBuffer str = new StringBuffer(); for (String line : output) { if (str.length() > 0) str.append(glue); str.append(line); } notifyOutputListener(str.toString()); } public void addOutputListener(IOutputListener listener) { outputListenerList.add(listener); } public void removeOutputListener(IOutputListener listener) { outputListenerList.remove(listener); } }