/******************************************************************************* * Copyright (c) 2009, 2014 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.ui.launching; import java.io.File; import java.util.Arrays; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.preferences.DefaultScope; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.debug.core.*; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.ILaunchShortcut2; import org.eclipse.dltk.core.IMethod; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.IType; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.php.core.PHPVersion; import org.eclipse.php.core.project.ProjectOptions; import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys; import org.eclipse.php.internal.core.documentModel.provisional.contenttype.ContentTypeIdForPHP; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.PHPDebugPlugin; import org.eclipse.php.internal.debug.core.PHPRuntime; import org.eclipse.php.internal.debug.core.debugger.IDebuggerConfiguration; import org.eclipse.php.internal.debug.core.preferences.*; import org.eclipse.php.internal.debug.ui.Logger; import org.eclipse.php.internal.debug.ui.PHPDebugUIMessages; import org.eclipse.php.internal.debug.ui.PHPDebugUIPlugin; import org.eclipse.php.internal.ui.editor.input.NonExistingPHPFileEditorInput; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.IURIEditorInput; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.editors.text.TextFileDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; public class PHPExeLaunchShortcut implements ILaunchShortcut2 { /** * PHPExeLaunchShortcut constructor. */ public PHPExeLaunchShortcut() { super(); } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers * .ISelection, java.lang.String) */ public void launch(ISelection selection, String mode) { if (selection instanceof IStructuredSelection) { searchAndLaunch(((IStructuredSelection) selection).toArray(), mode, getPHPExeLaunchConfigType()); } } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, * java.lang.String) */ public void launch(IEditorPart editor, String mode) { IEditorInput input = editor.getEditorInput(); IFile file = (IFile) input.getAdapter(IFile.class); if (file == null) { IPath path = null; try { if (input instanceof IStorageEditorInput) { IStorageEditorInput editorInput = (IStorageEditorInput) input; IStorage storage = editorInput.getStorage(); path = storage.getFullPath(); } else if (input instanceof IURIEditorInput) { path = URIUtil.toPath(((IURIEditorInput) input).getURI()); } else if (input instanceof NonExistingPHPFileEditorInput) { // handle untitled document debugging // first save the file to the disk and after that set the // document as dirty if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; final TextFileDocumentProvider documentProvider = (TextFileDocumentProvider) textEditor .getDocumentProvider(); final IDocument document = documentProvider.getDocument(input); documentProvider.saveDocument(null, input, document, true); // set document dirty document.replace(0, 0, ""); //$NON-NLS-1$ } path = ((NonExistingPHPFileEditorInput) input).getPath(input);// Untitled // dummy // path } if (path != null) { File systemFile = new File(path.toOSString()); if (systemFile.exists()) { searchAndLaunch(new Object[] { systemFile }, mode, getPHPExeLaunchConfigType()); } } } catch (Exception e) { Logger.logException(e); } } else { searchAndLaunch(new Object[] { file }, mode, getPHPExeLaunchConfigType()); } } protected ILaunchConfigurationType getPHPExeLaunchConfigType() { ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager(); return lm.getLaunchConfigurationType(IPHPDebugConstants.PHPEXELaunchType); } public static void searchAndLaunch(Object[] search, String mode, ILaunchConfigurationType configType) { if (search == null) { return; } int entries = search.length; for (int i = 0; i < entries; i++) { try { String phpPathString = null; String phpFileLocation = null; IProject project = null; Object obj = search[i]; IResource res = null; if (obj instanceof IModelElement) { IModelElement elem = (IModelElement) obj; if (elem instanceof ISourceModule) { res = ((ISourceModule) elem).getCorrespondingResource(); } else if (elem instanceof IType) { res = ((IType) elem).getUnderlyingResource(); } else if (elem instanceof IMethod) { res = ((IMethod) elem).getUnderlyingResource(); } if (res instanceof IFile) { obj = (IFile) res; } } if (obj instanceof IFile) { IFile file = (IFile) obj; res = file; project = file.getProject(); IContentType contentType = Platform.getContentTypeManager() .getContentType(ContentTypeIdForPHP.ContentTypeID_PHP); if (contentType.isAssociatedWith(file.getName())) { if (new File(file.getFullPath().toOSString()).exists()) { phpPathString = file.getFullPath().toOSString(); } else { phpPathString = file.getFullPath().toString(); } IPath location = file.getLocation(); // check for non null values - EFS issues if (location != null) { phpFileLocation = location.toOSString(); } else { phpFileLocation = file.getFullPath().toString(); } } } else if (obj instanceof File) { File systemFile = (File) obj; phpPathString = systemFile.getAbsolutePath(); phpFileLocation = phpPathString; } if (phpPathString == null) { // Could not find target to launch throw new CoreException(new Status(IStatus.ERROR, PHPDebugUIPlugin.ID, IStatus.OK, PHPDebugUIMessages.launch_failure_no_target, null)); } PHPexeItem bestMatchExe = getBestMatchPHPExe(project); String phpExeName = (bestMatchExe != null) ? bestMatchExe.getExecutable().getAbsolutePath().toString() : null; if (phpExeName == null) { MessageDialog.openError(PHPDebugUIPlugin.getActiveWorkbenchShell(), PHPDebugUIMessages.launch_noexe_msg_title, PHPDebugUIMessages.launch_noexe_msg_text); PreferencesUtil.createPreferenceDialogOn(PHPDebugUIPlugin.getActiveWorkbenchShell(), "org.eclipse.php.debug.ui.preferencesphps.PHPsPreferencePage", //$NON-NLS-1$ null, null).open(); return; } // Launch the app ILaunchConfiguration config = findLaunchConfiguration(project, phpPathString, phpFileLocation, bestMatchExe, mode, configType, res); if (config != null) { DebugUITools.launch(config, mode); } else { // Could not find launch configuration throw new CoreException(new Status(IStatus.ERROR, PHPDebugUIPlugin.ID, IStatus.OK, PHPDebugUIMessages.launch_failure_no_config, null)); } } catch (CoreException ce) { final IStatus stat = ce.getStatus(); Display.getDefault().asyncExec(new Runnable() { public void run() { ErrorDialog.openError(PHPDebugUIPlugin.getActiveWorkbenchShell(), PHPDebugUIMessages.launch_failure_msg_title, PHPDebugUIMessages.launch_failure_exec_msg_text, stat); } }); } } } private static PHPexeItem getBestMatchPHPExe(IProject project) { PHPexeItem defaultItem = PHPDebugPlugin.getPHPexeItem(project); if (defaultItem == null) { defaultItem = PHPDebugPlugin.getWorkspaceDefaultExe(); } PHPVersion phpVersion = ProjectOptions.getPHPVersion(project); PHPexeItem[] matchingItems = PHPexes.getInstance().getCompatibleItems(PHPexes.getInstance().getAllItems(), phpVersion); if (Arrays.asList(matchingItems).contains(defaultItem)) { return defaultItem; } else if (matchingItems.length > 0) { return matchingItems[0]; } return defaultItem; } // Creates a preferences scope for the given project. // This scope will be used to search for preferences values. private static IScopeContext[] createPreferenceScopes(IProject project) { if (project != null) { return new IScopeContext[] { new ProjectScope(project), InstanceScope.INSTANCE, DefaultScope.INSTANCE }; } return new IScopeContext[] { InstanceScope.INSTANCE, DefaultScope.INSTANCE }; } /** * Locate a configuration to relaunch for the given type. If one cannot be * found, create one. * * @param res * * @return a re-useable config or <code>null</code> if none */ protected static ILaunchConfiguration findLaunchConfiguration(IProject phpProject, String phpPathString, String phpFileFullLocation, PHPexeItem bestMatchExe, String mode, ILaunchConfigurationType configType, IResource res) { ILaunchConfiguration config = null; try { ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager() .getLaunchConfigurations(configType); if (configs != null) { int numConfigs = configs.length; for (int i = 0; i < numConfigs; i++) { String fileName = configs[i].getAttribute(IPHPDebugConstants.ATTR_FILE, (String) null); String exeName = configs[i].getAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, (String) null); String iniPath = configs[i].getAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, (String) null); PHPexeItem item = PHPexes.getInstance().getItemForFile(exeName, iniPath); if (phpPathString .equals(fileName)/* && defaultEXE.equals(item) */) { config = configs[i]; break; } } } if (config == null) { config = createConfiguration(phpProject, phpPathString, phpFileFullLocation, bestMatchExe, configType, res); } } catch (CoreException ce) { ce.printStackTrace(); } return config; } /** * Create & return a new configuration * * @param res */ protected static ILaunchConfiguration createConfiguration(IProject phpProject, String phpPathString, String phpFileFullLocation, PHPexeItem bestMatchExe, ILaunchConfigurationType configType, IResource res) throws CoreException { ILaunchConfiguration config = null; ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, getNewConfigurationName(phpPathString)); // Set the delegate class according to selected executable. wc.setAttribute(PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID, bestMatchExe.getDebuggerID()); IDebuggerConfiguration debuggerConfiguration = PHPDebuggersRegistry .getDebuggerConfiguration(bestMatchExe.getDebuggerID()); wc.setAttribute(PHPDebugCorePreferenceNames.CONFIGURATION_DELEGATE_CLASS, debuggerConfiguration.getScriptLaunchDelegateClass()); wc.setAttribute(IPHPDebugConstants.ATTR_FILE, phpPathString); wc.setAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, phpFileFullLocation); wc.setAttribute(IPHPDebugConstants.ATTR_EXECUTABLE_LOCATION, bestMatchExe.getExecutable().getAbsolutePath().toString()); if (!bestMatchExe.isDefault()) { wc.setAttribute(PHPRuntime.PHP_CONTAINER, PHPRuntime.newPHPContainerPath(bestMatchExe).toPortableString()); } String iniPath = bestMatchExe.getINILocation() != null ? bestMatchExe.getINILocation().toString() : null; wc.setAttribute(IPHPDebugConstants.ATTR_INI_LOCATION, iniPath); wc.setAttribute(IPHPDebugConstants.RUN_WITH_DEBUG_INFO, PHPDebugPlugin.getDebugInfoOption()); wc.setAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT, PHPProjectPreferences.getStopAtFirstLine(phpProject)); if (res != null) { wc.setMappedResources(new IResource[] { res }); } config = wc.doSave(); return config; } /** * Returns a name for a newly created launch configuration according to the * given file name. In case the name generation fails, return the * "New_configuration" string. * * @param fileName * The original file name that this shortcut shoul execute. * @return The new configuration name, or "New_configuration" in case it * fails for some reason. */ protected static String getNewConfigurationName(String fileName) { String configurationName = PHPDebugUIMessages.PHPExeLaunchShortcut_0; try { IPath path = Path.fromOSString(fileName); NonExistingPHPFileEditorInput editorInput = NonExistingPHPFileEditorInput.findEditorInput(path); if (editorInput != null) { path = new Path(editorInput.getName()); } String fileExtention = path.getFileExtension(); String lastSegment = path.lastSegment(); if (lastSegment != null) { if (fileExtention != null) { lastSegment = lastSegment.replaceFirst("." + fileExtention, //$NON-NLS-1$ ""); //$NON-NLS-1$ } configurationName = lastSegment; } } catch (Exception e) { Logger.log(Logger.WARNING_DEBUG, "Could not generate configuration name for " + fileName //$NON-NLS-1$ + ".\nThe default name will be used.", e); //$NON-NLS-1$ } return DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom(configurationName); } public ILaunchConfiguration[] getLaunchConfigurations(ISelection selection) { return null; } public ILaunchConfiguration[] getLaunchConfigurations(IEditorPart editorpart) { return null; } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse * .ui.IEditorPart) */ public IResource getLaunchableResource(IEditorPart editorpart) { return getLaunchableResource(editorpart.getEditorInput()); } /* * (non-Javadoc) * * @see * org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse * .jface.viewers.ISelection) */ public IResource getLaunchableResource(ISelection selection) { if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() == 1) { Object element = ss.getFirstElement(); if (element instanceof IAdaptable) { return getLaunchableResource((IAdaptable) element); } } } return null; } /** * Returns the resource containing the Java element associated with the * given adaptable, or <code>null</code>. * * @param adaptable * adaptable object * @return containing resource or <code>null</code> */ private IResource getLaunchableResource(IAdaptable adaptable) { IModelElement je = (IModelElement) adaptable.getAdapter(IModelElement.class); if (je != null) { return je.getResource(); } return null; } }