/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. 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:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.phpunit.ui.launch;
import java.io.File;
import java.util.*;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.*;
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.model.IProcess;
import org.eclipse.debug.ui.CommonTab;
import org.eclipse.debug.ui.RefreshTab;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.php.core.project.ProjectOptions;
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.PHPDebugPlugin;
import org.eclipse.php.internal.debug.core.launching.PHPLaunchUtilities;
import org.eclipse.php.internal.debug.core.preferences.PHPexeItem;
import org.eclipse.php.internal.debug.core.preferences.PHPexes;
import org.eclipse.php.internal.debug.core.zend.debugger.ProcessCrashDetector;
import org.eclipse.swt.widgets.Display;
@SuppressWarnings("restriction")
public class PHPUnitBasicLauncher {
protected ILaunchConfiguration configuration;
protected ILaunch launch;
protected PHPUnitOptionsList optionsList;
public PHPUnitBasicLauncher(ILaunchConfiguration configuration, ILaunch launch, PHPUnitOptionsList optionsList) {
this.configuration = configuration;
this.launch = launch;
this.optionsList = optionsList;
}
public void launch(String mode, IProject project, File workingDir, Map<String, String> envVariables,
IProgressMonitor monitor) throws CoreException {
// Check for previous launches.
if (!PHPLaunchUtilities.notifyPreviousLaunches(launch)) {
monitor.setCanceled(true);
monitor.done();
return;
}
if (monitor.isCanceled()) {
return;
}
String phpExeString = configuration.getAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, (String) null);
String fileName = configuration.getAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, (String) null);
if (monitor.isCanceled()) {
return;
}
if (phpExeString == null) {
displayErrorMessage(PHPDebugCoreMessages.PHPExecutableLaunchDelegate_4);
return;
}
// 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);
// File tempIni = PHPINIUtil.prepareBeforeLaunch(phpIni, phpExeString,
// project);
// launch.setAttribute(IDebugParametersKeys.PHP_INI_LOCATION,
// tempIni.getAbsolutePath());
if (mode.equals(ILaunchManager.PROFILE_MODE)) {
launchProfileMode(fileName, workingDir, phpExeString, project, envVariables, monitor);
} else if (mode.equals(ILaunchManager.DEBUG_MODE)) {
launchDebugMode(fileName, workingDir, phpExeString, project, envVariables, monitor);
} else if (mode.equals(ILaunchManager.RUN_MODE)) {
launchRunMode(fileName, workingDir, phpExeString, project, envVariables, monitor);
}
}
protected void launchRunMode(String fileName, File workingDir, String phpExeString, IProject project,
Map<String, String> envVariables, IProgressMonitor monitor) throws CoreException {
// 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("")) { //$NON-NLS-1$
phpConfigDir = new File(phpIniLocation).getParent();
}
// Detect PHP SAPI type:
String sapiType = null;
// String phpV = null;
PHPexeItem[] items = PHPexes.getInstance().getAllItems();
for (PHPexeItem item : items) {
if (item.getExecutable().equals(phpExeFile)) {
sapiType = item.getSapiType();
// phpV = item.getVersion();
break;
}
}
String[] args = PHPLaunchUtilities.getProgramArguments(launch.getLaunchConfiguration());
String[] cmdLine = getCommandLine(project, phpExeString, phpConfigDir, fileName,
PHPexeItem.SAPI_CLI.equals(sapiType) ? args : null);
// Set library search path
String libPath = PHPLaunchUtilities.getLibrarySearchPathEnv(phpExeFile.getParentFile());
if (libPath != null) {
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] = libPath;
envp = envpNew;
}
if (monitor.isCanceled()) {
return;
}
List<String> allArgs = new ArrayList<>();
allArgs.addAll(Arrays.asList(cmdLine));
allArgs.addAll(optionsList.getList());
cmdLine = allArgs.toArray(new String[0]);
if (PHPDebugPlugin.DEBUG) {
System.out.println("Executing: " + Arrays.toString(cmdLine)); //$NON-NLS-1$
System.out.println("Process environment: " //$NON-NLS-1$
+ Arrays.toString(envp));
}
Process p = workingDir.exists() ? DebugPlugin.exec(cmdLine, workingDir, envp)
: DebugPlugin.exec(cmdLine, null, envp);
// Attach a crash detector
new Thread(new ProcessCrashDetector(launch, p)).start();
IProcess process = null;
// Add process type to process attributes
Map<String, String> processAttributes = new HashMap<>();
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);
IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10);
if (p != null) {
subMonitor = new SubProgressMonitor(monitor, 80);
process = DebugPlugin.newProcess(launch, p, phpExe.toOSString(), processAttributes);
if (process == null) {
p.destroy();
throw new CoreException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(), 0, null, null));
}
subMonitor.done();
}
process.setAttribute(IProcess.ATTR_CMDLINE, fileName);
if (CommonTab.isLaunchInBackground(configuration)) {
// Refresh resources after process finishes
/*
* if (RefreshTab.getRefreshScope(configuration) != null) {
* BackgroundResourceRefresher refresher = new
* BackgroundResourceRefresher(configuration, process);
* refresher.startBackgroundRefresh(); }
*/
} else {
// 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);
RefreshTab.refreshResources(configuration, subMonitor);
}
}
protected void launchDebugMode(String fileName, File workingDir, String phpExeString, IProject project,
Map<String, String> envVariables, IProgressMonitor monitor) throws CoreException {
launchRunMode(fileName, workingDir, phpExeString, project, envVariables, monitor);
}
protected void launchProfileMode(String fileName, File workingDir, String phpExeString, IProject project,
Map<String, String> envVariables, IProgressMonitor monitor) throws CoreException {
launchRunMode(fileName, workingDir, phpExeString, project, envVariables, monitor);
}
public String[] getCommandLine(IProject project, String phpExe, String phpConfigDir, String scriptPath,
String[] args) throws CoreException {
// Check if we should treat ASP tags as PHP tags
String aspTags = ProjectOptions.isSupportingASPTags(project) ? "on" //$NON-NLS-1$
: "off"; //$NON-NLS-1$
String shortOpenTag = ProjectOptions.useShortTags(project) ? "on" //$NON-NLS-1$
: "off"; //$NON-NLS-1$
List<String> cmdLineList = new LinkedList<>();
cmdLineList.addAll(Arrays.asList(new String[] { phpExe, "-c", //$NON-NLS-1$
phpConfigDir, "-d", "asp_tags=" + aspTags, "-d", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
"short_open_tag=" + shortOpenTag, scriptPath })); //$NON-NLS-1$
if (args != null) {
cmdLineList.addAll(Arrays.asList(args));
}
return cmdLineList.toArray(new String[cmdLineList.size()]);
}
protected void displayErrorMessage(final String message) {
final Display display = Display.getDefault();
display.asyncExec(() -> MessageDialog.openError(display.getActiveShell(),
PHPDebugCoreMessages.Debugger_LaunchError_title, message));
}
}