/******************************************************************************* * 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 static org.eclipse.php.phpunit.ui.launch.PHPUnitLaunchAttributes.*; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.dialogs.ErrorDialog; 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.debugger.IDebuggerConfiguration; import org.eclipse.php.internal.debug.core.launching.PHPExecutableLaunchDelegate; import org.eclipse.php.internal.debug.core.launching.PHPLaunchUtilities; import org.eclipse.php.internal.debug.core.preferences.PHPDebugCorePreferenceNames; import org.eclipse.php.internal.debug.core.preferences.PHPDebuggersRegistry; import org.eclipse.php.internal.debug.core.preferences.PHPexeItem; import org.eclipse.php.internal.debug.core.xdebug.communication.XDebugCommunicationDaemon; import org.eclipse.php.internal.debug.core.zend.communication.DebuggerCommunicationDaemon; import org.eclipse.php.phpunit.PHPUnitMessages; import org.eclipse.php.phpunit.PHPUnitPlugin; import org.eclipse.php.phpunit.model.connection.PHPUnitConnection; import org.eclipse.php.phpunit.ui.preference.PHPUnitPreferenceKeys; import org.eclipse.swt.widgets.Display; public class PHPUnitLaunchConfigurationDelegate extends PHPExecutableLaunchDelegate { public static final String PRINTER_NAME = "PHPUnitLogger"; //$NON-NLS-1$ private static final String PRINTER_DIRECTORY = "printer";//$NON-NLS-1$ private static final String TMP_PRINTER_DIRECTORY = "phpunit_printer";//$NON-NLS-1$ private static final String ENV_PORT = "PHPUNIT_PORT"; //$NON-NLS-1$ private static final String TIMESTAMP_DATA_FORMAT = "yyyyMMdd-HHmm"; //$NON-NLS-1$ private static final String XML_FILE_FORMAT = "%s-%s.xml";//$NON-NLS-1$ @Override public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException { return false; } @Override public void launch(ILaunchConfiguration config, final String mode, final ILaunch launch, final IProgressMonitor monitor) throws CoreException { if (!PHPUnitLaunchUtils.launchIsPHPUnit(launch)) { displayErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationDelegate_Bad_Config); } if (config.getAttribute(PHPUnitLaunchAttributes.ATTRIBUTE_CODE_COVERAGE, false)) { launch.setAttribute(PHPUnitLaunchAttributes.ATTRIBUTE_COLLECT_CODE_COVERAGE, "1"); //$NON-NLS-1$ } IPath elementToTest = findElementToTest(config); if (elementToTest == null || elementToTest.isEmpty()) { displayErrorMessage(PHPUnitMessages.PHPUnitLaunchShortcut_Unable_To_Generate); return; } final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); final IResource resource = workspaceRoot.findMember(elementToTest); if (resource == null) { displayErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_No_Container); return; } final IProject project = resource.getProject(); String fileToExecute = findFileToExecute(config, project); if (fileToExecute == null) { return; } final ILaunchConfigurationWorkingCopy wconfig; if (config.isWorkingCopy()) { wconfig = (ILaunchConfigurationWorkingCopy) config; } else { wconfig = config.getWorkingCopy(); } setAdditionalAttributes(wconfig, fileToExecute, project); setEnvironmentVariables(wconfig, project); PHPUnitOptionsList phpUnitOptionsList = createPHPUnitOptionsList(wconfig, project); config = wconfig.doSave(); if (!(resource instanceof IProject)) { phpUnitOptionsList.setElementToTest(resource.getLocation().toOSString()); } File workingDirectory = resource.getLocation().toFile(); if (workingDirectory.isFile()) { workingDirectory = workingDirectory.getParentFile(); } if (PHPUnitLaunchUtils.isPHPUnitRunning()) { Display.getDefault() .syncExec(() -> ErrorDialog.openError(Display.getCurrent().getActiveShell(), PHPUnitMessages.PHPUnitConnection_Launching, PHPUnitMessages.PHPUnitConnection_Unable_to_run, new Status(IStatus.ERROR, PHPUnitPlugin.ID, 0, PHPUnitMessages.PHPUnitConnection_Previous_session_exists, null))); return; } final int port = Integer.parseInt(envVariables.get(ENV_PORT)); if (!PHPUnitConnection.getInstance().listen(port, launch)) { return; } PHPexeItem execItem = PHPLaunchUtilities.getPHPExe(config); if (execItem != null) { // Update launch configuration - in case PHP executable attributes // have changed ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); wc.setAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, execItem.getExecutable().toString()); wc.setAttribute(PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID, execItem.getDebuggerID()); IDebuggerConfiguration debuggerConfiguration = PHPDebuggersRegistry .getDebuggerConfiguration(execItem.getDebuggerID()); wc.setAttribute(PHPDebugCorePreferenceNames.CONFIGURATION_DELEGATE_CLASS, debuggerConfiguration.getScriptLaunchDelegateClass()); if ((mode.equals(ILaunchManager.DEBUG_MODE) || mode.equals(ILaunchManager.PROFILE_MODE)) && debuggerConfiguration.getDebuggerId().equals(PHPDebuggersRegistry.NONE_DEBUGGER_ID)) { wc.setAttribute(IDebugUIConstants.ATTR_PRIVATE, true); } if (execItem.getINILocation() != null) { wc.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, execItem.getINILocation().toString()); } else { wc.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, (String) null); } config = wc.doSave(); } if (execItem != null) { PHPUnitBasicLauncher launcher = new PHPUnitBasicLauncher(config, launch, phpUnitOptionsList); if (XDebugCommunicationDaemon.XDEBUG_DEBUGGER_ID.equals(execItem.getDebuggerID())) { launcher = new PHPUnitXDLauncher(config, launch, phpUnitOptionsList); } else if (DebuggerCommunicationDaemon.ZEND_DEBUGGER_ID.equals(execItem.getDebuggerID())) { launcher = new PHPUnitZDLauncher(config, launch, phpUnitOptionsList); } launch.setAttribute(PHPUnitLaunchAttributes.ATTRIBUTE_PHPUNIT_LAUNCH, Boolean.TRUE.toString()); launcher.launch(mode, project, workingDirectory, envVariables, monitor); } else { displayErrorMessage(PHPDebugCoreMessages.PHPExecutableLaunchDelegate_4); return; } } private IPath findElementToTest(ILaunchConfiguration config) throws CoreException { String containerType = config.getAttribute(ATTRIBUTE_CONTAINER_TYPE, ""); //$NON-NLS-1$ String container = config.getAttribute(ATTRIBUTE_CONTAINER, ""); //$NON-NLS-1$ String file = config.getAttribute(ATTRIBUTE_FILE, ""); //$NON-NLS-1$ String projectName = config.getAttribute(ATTRIBUTE_PROJECT, ""); //$NON-NLS-1$ boolean runContainer = config.getAttribute(ATTRIBUTE_RUN_CONTAINER, // $NON-NLS-1$ true); IPath resourcePath = null; if (containerType.equals(PROJECT_CONTAINER)) { if (runContainer) { resourcePath = new Path(projectName); } else { resourcePath = new Path(projectName).append(file); } } else if (containerType.equals(FOLDER_CONTAINER)) { if (runContainer) { resourcePath = new Path(projectName).append(container); } } else if (containerType.equals(SOURCE_CONTAINER)) { if (runContainer) { resourcePath = new Path(projectName).append(container); } else { resourcePath = new Path(projectName).append(file); } } return resourcePath; } private String findFileToExecute(ILaunchConfiguration config, IProject project) throws CoreException { String runType = config.getAttribute(ATTRIBUTE_EXECUTION_TYPE, PHAR_EXECUTION_TYPE); String result = null; if (COMPOSER_EXECUTION_TYPE.equals(runType)) { result = PHPUnitLaunchUtils.findComposerExecutionFile(project); if (result == null) { displayErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationDelegate_no_composer_dependency); } } else if (PHAR_EXECUTION_TYPE.equals(runType)) { result = PHPUnitPreferenceKeys.getPHPUnitPharPath(); if (result == null || !new File(result).exists()) { result = null; displayErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationDelegate_no_phar); } } return result; } private PHPUnitOptionsList createPHPUnitOptionsList(ILaunchConfigurationWorkingCopy config, IProject project) throws CoreException { PHPUnitOptionsList optionsList = new PHPUnitOptionsList(); optionsList.add(PHPUnitOption.INCLUDE_PATH, getPrinterDirectory()); optionsList.add(PHPUnitOption.PRINTER, PRINTER_NAME); boolean logXml = config.getAttribute(ATTRIBUTE_LOG_XML, false); if (logXml) { String xmlLocation = PHPUnitPreferenceKeys.getReportPath(); if (xmlLocation != null) { String timestamp = new SimpleDateFormat(TIMESTAMP_DATA_FORMAT).format(new Date()); String fileName = String.format(XML_FILE_FORMAT, config.getName(), timestamp); optionsList.add(PHPUnitOption.LOG_JUNIT, new Path(xmlLocation).append(fileName).toOSString()); config.setAttribute(PHPUnitLaunchAttributes.ATTRIBUTE_LOG_XML_LOCATION, new Path(xmlLocation).append(fileName).toOSString()); } } String configurationXml = config.getAttribute(ATTRIBUTE_PHPUNIT_CFG, (String) null); if (configurationXml != null && !configurationXml.isEmpty()) { IResource configurationXmlResource = project.findMember(configurationXml); if (configurationXmlResource != null && configurationXmlResource.exists()) { optionsList.add(PHPUnitOption.CONFIGURATION, configurationXmlResource.getLocation().toOSString()); } } return optionsList; } private String getPrinterDirectory() { IPath resourcePath = PHPUnitLaunchUtils.getResourcesPath().append(PRINTER_DIRECTORY); String tmpDirectoryPath = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$ File tmpDirectory = new File(tmpDirectoryPath); if (tmpDirectory.exists()) { File printerDirectory = new File(tmpDirectory, TMP_PRINTER_DIRECTORY); if (!printerDirectory.exists()) { printerDirectory.mkdirs(); } File tmpPrinterFile = new File(printerDirectory, PRINTER_NAME + ".php"); //$NON-NLS-1$ if (tmpPrinterFile.exists()) { return tmpPrinterFile.getParentFile().getAbsolutePath(); } File printerFile = resourcePath.append(PRINTER_NAME + ".php") //$NON-NLS-1$ .toFile(); try { FileUtils.copyFile(printerFile, tmpPrinterFile); return tmpPrinterFile.getParentFile().getAbsolutePath(); } catch (IOException e) { PHPUnitPlugin.log(e); return resourcePath.toOSString(); } } return resourcePath.toOSString(); } private void setAdditionalAttributes(ILaunchConfigurationWorkingCopy wconfig, String fileToRun, IProject project) throws CoreException { // don't ever stop on the first line wconfig.setAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT, false); wconfig.setAttribute(IPHPDebugConstants.ATTR_FILE, fileToRun); wconfig.setAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, fileToRun); wconfig.setAttribute(IPHPDebugConstants.PHP_Project, project.getName()); } private void setEnvironmentVariables(final ILaunchConfigurationWorkingCopy wconfig, final IProject project) throws CoreException { // Try get any user variable at first. envVariables = wconfig.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new HashMap<String, String>()); if (envVariables == null) { envVariables = new HashMap<String, String>(); } if (envVariables.get(ENV_PORT) == null) { final int port = PHPUnitPreferenceKeys.getPort(); envVariables.put(ENV_PORT, String.valueOf(port)); } wconfig.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, envVariables); } private void displayErrorMessage(final String message) { final Display display = Display.getDefault(); display.asyncExec(() -> MessageDialog.openError(display.getActiveShell(), PHPUnitMessages.PHPUnitLaunchConfigurationDelegate_Launching, message)); } }