/*******************************************************************************
* 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.server.ui.launching;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.debug.core.*;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.ILaunchShortcut2;
import org.eclipse.dltk.core.*;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys;
import org.eclipse.php.internal.core.documentModel.provisional.contenttype.ContentTypeIdForPHP;
import org.eclipse.php.internal.core.util.FileUtils;
import org.eclipse.php.internal.debug.core.IPHPDebugConstants;
import org.eclipse.php.internal.debug.core.PHPDebugPlugin;
import org.eclipse.php.internal.debug.core.debugger.IDebuggerConfiguration;
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.PHPProjectPreferences;
import org.eclipse.php.internal.debug.ui.Logger;
import org.eclipse.php.internal.debug.ui.PHPDebugUIPlugin;
import org.eclipse.php.internal.server.core.Server;
import org.eclipse.php.internal.server.core.manager.ServersManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
/**
* A PHP web page launch shortcut.
*
* @author Shalom Gibly
*/
public class PHPWebPageLaunchShortcut implements ILaunchShortcut2 {
public void launch(ISelection selection, String mode) {
if (selection instanceof IStructuredSelection) {
searchAndLaunch(((IStructuredSelection) selection).toArray(), mode, getPHPServerLaunchConfigType());
}
}
public void launch(IEditorPart editor, String mode) {
IEditorInput input = editor.getEditorInput();
IFile file = (IFile) input.getAdapter(IFile.class);
if (file != null) {
searchAndLaunch(new Object[] { file }, mode, getPHPServerLaunchConfigType());
}
}
private ILaunchConfigurationType getPHPServerLaunchConfigType() {
ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager();
return lm.getLaunchConfigurationType(IPHPDebugConstants.PHPServerLaunchType);
}
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;
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())) {
phpPathString = file.getFullPath().toString();
}
}
Server defaultServer = ServersManager.getDefaultServer(project);
if (defaultServer == null) {
defaultServer = ServersManager.getDefaultServer(project);
if (defaultServer == null) {
// Sould not happen
throw new CoreException(new Status(IStatus.ERROR, PHPDebugUIPlugin.ID, IStatus.OK,
Messages.PHPWebPageLaunchShortcut_0, null));
}
}
boolean breakAtFirstLine = PHPProjectPreferences.getStopAtFirstLine(project);
String selectedURL = null;
boolean showDebugDialog = true;
if (obj instanceof IScriptProject) {
final PHPWebPageLaunchDialog dialog = new PHPWebPageLaunchDialog(mode, (IScriptProject) obj);
final int open = dialog.open();
if (open == PHPWebPageLaunchDialog.OK) {
defaultServer = dialog.getServer();
selectedURL = dialog.getPHPPathString();
phpPathString = dialog.getFilename();
breakAtFirstLine = dialog.isBreakAtFirstLine();
showDebugDialog = false;
} else {
continue;
}
}
if (phpPathString == null) {
// Could not find target to launch
throw new CoreException(new Status(IStatus.ERROR, PHPDebugUIPlugin.ID, IStatus.OK,
Messages.launch_failure_no_target, null));
}
// Launch the app
ILaunchConfiguration config = findLaunchConfiguration(project, phpPathString, selectedURL,
defaultServer, mode, configType, breakAtFirstLine, showDebugDialog, res);
if (config != null) {
DebugUITools.launch(config, mode);
} else {
// Could not find launch configuration or the user
// cancelled.
// 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(),
Messages.launch_failure_msg_title, Messages.launch_failure_server_msg_text, stat);
}
});
}
}
}
/**
* Locate a configuration to relaunch for the given type. If one cannot be
* found, create one.
*
* @param breakAtFirstLine
* @param res
*
* @return a re-useable config or <code>null</code> if none
*/
static ILaunchConfiguration findLaunchConfiguration(IProject project, String fileName, String selectedURL,
Server server, String mode, ILaunchConfigurationType configType, boolean breakAtFirstLine,
boolean showDebugDialog, IResource res) {
ILaunchConfiguration config = null;
try {
ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager()
.getLaunchConfigurations(configType);
if (configs == null) {
return config;
}
int numConfigs = configs.length;
for (int i = 0; i < numConfigs; i++) {
String configuredServerName = configs[i].getAttribute(Server.NAME, (String) null);
String configuredFileName = configs[i].getAttribute(Server.FILE_NAME, (String) null);
if (configuredFileName != null)
if (configuredFileName.equals(fileName) && server.getName().equals(configuredServerName)) {
config = configs[i].getWorkingCopy();
break;
}
}
if (config == null) {
config = createConfiguration(project, fileName, selectedURL, server, configType, mode, breakAtFirstLine,
showDebugDialog, res);
}
} catch (CoreException ce) {
Logger.logException(ce);
}
return config;
}
static String computeContextRoot(String url, String fileName, Server server) {
String serverBaseURL = server.getBaseURL();
if (url.length() > serverBaseURL.length() + 1) {
url = url.substring(serverBaseURL.length() + 1);
} else if (url.length() == serverBaseURL.length() || url.length() == serverBaseURL.length() + 1) {
return ""; //$NON-NLS-1$
}
// Remove the project name from the file name
if (fileName.length() > 0) {
fileName = fileName.substring(1);
int pathIndex = fileName.indexOf('/');
if (pathIndex < 0) {
fileName = ""; //$NON-NLS-1$
} else {
fileName = fileName.substring(pathIndex);
}
}
if (url.length() > fileName.length()) {
url = url.substring(0, url.length() - fileName.length());
} else {
return ""; //$NON-NLS-1$
}
return url;
}
static ILaunchConfiguration createConfiguration(IProject project, String fileName, String selectedURL,
Server server, ILaunchConfigurationType configType, String mode, boolean breakAtFirstLine,
boolean showDebugDialog, IResource res) throws CoreException {
ILaunchConfiguration config = null;
if (!FileUtils.resourceExists(fileName)) {
return null;
}
String URL = null;
if (selectedURL != null) {
URL = selectedURL;
} else {
try {
URL resolvedUrl = constractURL(res.getProject(), server.getBaseURL(), new Path(fileName));
URL = resolvedUrl.toString();
} catch (MalformedURLException e) {
// safe as resolved URL is server.getBaseURL()
}
}
ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, getNewConfigurationName(fileName));
// Set the debugger ID and the configuration delegate for this launch
// configuration
String debuggerID = PHPDebugPlugin.getDebuggerId(server.getName());
wc.setAttribute(PHPDebugCorePreferenceNames.PHP_DEBUGGER_ID, debuggerID);
IDebuggerConfiguration debuggerConfiguration = PHPDebuggersRegistry.getDebuggerConfiguration(debuggerID);
wc.setAttribute(PHPDebugCorePreferenceNames.CONFIGURATION_DELEGATE_CLASS,
debuggerConfiguration.getWebLaunchDelegateClass());
wc.setAttribute(Server.NAME, server.getName());
wc.setAttribute(Server.FILE_NAME, fileName);
wc.setAttribute(Server.BASE_URL, URL);
wc.setAttribute(IPHPDebugConstants.RUN_WITH_DEBUG_INFO, PHPDebugPlugin.getDebugInfoOption());
wc.setAttribute(IPHPDebugConstants.OPEN_IN_BROWSER, PHPDebugPlugin.getOpenInBrowserOption());
wc.setAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT, breakAtFirstLine);
if (res != null) {
wc.setMappedResources(new IResource[] { res });
}
// Display a dialog for selecting the URL.
if (showDebugDialog) {
String title = (ILaunchManager.DEBUG_MODE.equals(mode) ? Messages.PHPWebPageLaunchShortcut_1
: (ILaunchManager.PROFILE_MODE.equals(mode) ? Messages.PHPWebPageLaunchShortcut_2
: Messages.PHPWebPageLaunchShortcut_3));
PHPWebPageURLLaunchDialog launchDialog = new PHPWebPageURLLaunchDialog(wc, server, title);
launchDialog.setBlockOnOpen(true);
if (launchDialog.open() != PHPWebPageURLLaunchDialog.OK) {
return null;
}
}
config = wc.doSave();
return config;
}
private static URL constractURL(IProject project, String serverURL, Path path) throws MalformedURLException {
URL server = new URL(serverURL);
IPath url = new Path("/" + server.getPath()); //$NON-NLS-1$
String basePath = getProjectsBasePath(project);
boolean removeFirstSegment = true;
if (basePath == null) {
basePath = "/"; //$NON-NLS-1$
removeFirstSegment = false;
}
url = url.append(basePath);
if (removeFirstSegment)
url = url.append(path.removeFirstSegments(1));
else
url = url.append(path);
return new URL(server.getProtocol(), server.getHost(), server.getPort(), url.toString());
}
private static String getProjectsBasePath(IProject project) {
if (project == null)
return null;
return PHPProjectPreferences.getDefaultBasePath(project);
}
/**
* 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 = Messages.PHPWebPageLaunchShortcut_4;
try {
IPath path = Path.fromOSString(fileName);
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,
Messages.PHPWebPageLaunchShortcut_9 + fileName + Messages.PHPWebPageLaunchShortcut_10, e);
}
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;
}
}