blob: 2d31c4fdfc4757b03d9a01d2fe93aba423c14403 [file] [log] [blame]
/*
* Copyright (c) 2002 IBM Corp. All rights reserved.
* This file is made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*/
package org.eclipse.pde.internal.ui.launcher;
import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.*;
import org.eclipse.debug.core.model.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.debug.ui.JavaUISourceLocator;
import org.eclipse.jdt.launching.*;
import org.eclipse.jdt.launching.sourcelookup.JavaSourceLocator;
import org.eclipse.jface.dialogs.*;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.ui.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.pde.internal.core.*;
public class WorkbenchLaunchConfigurationDelegate
implements ILaunchConfigurationDelegate, ILauncherSettings {
private static final String KEY_NO_JRE = "WorkbenchLauncherConfigurationDelegate.noJRE";
private static final String KEY_NO_JRE2 = "WorkbenchLauncherConfigurationDelegate.noJRE2";
private static final String KEY_STARTING = "WorkbenchLauncherConfigurationDelegate.starting";
private static final String KEY_NO_BOOT = "WorkbenchLauncherConfigurationDelegate.noBoot";
private static final String KEY_BROKEN_PLUGINS = "WorkbenchLauncherConfigurationDelegate.brokenPlugins";
private static final String KEY_PROBLEMS_DELETING = "WorkbenchLauncherConfigurationDelegate.problemsDeleting";
private static final String KEY_TITLE = "WorkbenchLauncherConfigurationDelegate.title";
private static final String KEY_SLIMLAUNCHER = "WorkbenchLauncherConfigurationDelegate.slimlauncher";
private static final String KEY_DELETE_WORKSPACE = "WorkbenchLauncherConfigurationDelegate.confirmDeleteWorkspace";
/*
* @see ILaunchConfigurationDelegate#launch(ILaunchConfiguration, String)
*/
public void launch(
ILaunchConfiguration configuration,
String mode,
ILaunch launch,
IProgressMonitor monitor)
throws CoreException {
final String vmArgs = configuration.getAttribute(VMARGS, "");
final String progArgs = configuration.getAttribute(PROGARGS, "");
final String appName = configuration.getAttribute(APPLICATION, (String) null);
final String data = configuration.getAttribute(LOCATION + "0", (String) null);
final boolean tracing = configuration.getAttribute(TRACING, false);
final boolean clearWorkspace = configuration.getAttribute(DOCLEAR, false);
final IPluginModelBase[] plugins = getPluginsFromConfiguration(configuration);
String vmInstallName = configuration.getAttribute(VMINSTALL, (String) null);
IVMInstall[] vmInstallations = BasicLauncherTab.getAllVMInstances();
IVMInstall launcher = null;
if (monitor==null)
monitor = new NullProgressMonitor();
if (vmInstallName != null) {
for (int i = 0; i < vmInstallations.length; i++) {
if (vmInstallName.equals(vmInstallations[i].getName())) {
launcher = vmInstallations[i];
break;
}
}
} else if (vmInstallations.length>0)
launcher = vmInstallations[0];
if (launcher == null) {
String message;
if (vmInstallName!=null)
message = PDEPlugin.getFormattedMessage(KEY_NO_JRE, vmInstallName);
else
message = PDEPlugin.getResourceString(KEY_NO_JRE2);
monitor.setCanceled(true);
throw new CoreException(createErrorStatus(message));
}
validatePlugins(plugins, monitor);
IVMRunner runner = launcher.getVMRunner(mode);
ExecutionArguments args = new ExecutionArguments(vmArgs, progArgs);
IPath path = new Path(data);
boolean success =
doLaunch(
launch,
configuration,
mode,
runner,
path,
clearWorkspace,
args,
plugins,
appName,
tracing,
monitor);
}
private IPluginModelBase[] getPluginsFromConfiguration(ILaunchConfiguration config)
throws CoreException {
boolean useDefault = config.getAttribute(USECUSTOM, true);
ArrayList deselectedWSPlugins = new ArrayList();
String wstring = config.getAttribute(WSPROJECT, (String) null);
String exstring = config.getAttribute(EXTPLUGINS, (String) null);
if (wstring != null) {
StringTokenizer tok = new StringTokenizer(wstring, File.pathSeparator);
while (tok.hasMoreTokens()) {
deselectedWSPlugins.add(tok.nextToken());
}
}
AdvancedLauncherTab.ExternalStates exstates =
new AdvancedLauncherTab.ExternalStates();
if (exstring != null) {
exstates.parseStates(exstring);
}
ArrayList wsList = new ArrayList();
IPluginModelBase[] wsmodels = AdvancedLauncherTab.getWorkspacePlugins();
for (int i = 0; i < wsmodels.length; i++) {
IPluginModelBase model = wsmodels[i];
if (useDefault || !deselectedWSPlugins.contains(model.getPluginBase().getId()))
wsList.add(model);
}
IPluginModelBase[] exmodels = AdvancedLauncherTab.getExternalPlugins();
ArrayList exList = new ArrayList();
for (int i = 0; i < exmodels.length; i++) {
IPluginModelBase model = exmodels[i];
if (useDefault) {
if (model.isEnabled())
exList.add(model);
} else {
AdvancedLauncherTab.ExternalState es =
exstates.getState(model.getPluginBase().getId());
if (es != null) {
if(es.state)
exList.add(model);
} else if (model.isEnabled())
exList.add(model);
}
}
ArrayList result = new ArrayList();
mergeWithoutDuplicates(wsList, exList, result);
IPluginModelBase[] plugins =
(IPluginModelBase[]) result.toArray(new IPluginModelBase[result.size()]);
return plugins;
}
private void mergeWithoutDuplicates(ArrayList wsmodels, ArrayList exmodels, ArrayList result) {
boolean duplicates=false;
for (int i=0; i<wsmodels.size(); i++) {
result.add(wsmodels.get(i));
}
for (int i=0; i<exmodels.size(); i++) {
IPluginModelBase exmodel = (IPluginModelBase)exmodels.get(i);
boolean localDuplicate=false;
for (int j=0; j<wsmodels.size(); j++) {
IPluginModelBase wsmodel = (IPluginModelBase)wsmodels.get(j);
if (isDuplicate(wsmodel, exmodel)) {
localDuplicate=true;
break;
}
}
if (localDuplicate) duplicates=true;
else
result.add(exmodel);
}
if (duplicates) {
//FIXME NL
showWarningDialog("The list of plug-ins to run contains duplicates. Plug-ins from the workspace will be used. To fix the problem, uncheck the offending external plug-ins in the Preferences or Launch Configurations");
}
}
private boolean isDuplicate(IPluginModelBase wsmodel, IPluginModelBase exmodel) {
if (!wsmodel.isLoaded() || !exmodel.isLoaded()) return false;
return wsmodel.getPluginBase().getId().equalsIgnoreCase(exmodel.getPluginBase().getId());
}
private void validatePlugins(IPluginModelBase[] plugins, IProgressMonitor monitor) throws CoreException {
ArrayList entries = new ArrayList();
for (int i=0; i<plugins.length; i++) {
IPluginModelBase model = plugins[i];
if (model.isLoaded()==false) {
String message = model.getInstallLocation();
if (model.getUnderlyingResource()!=null)
message = model.getUnderlyingResource().getProject().getName();
Status status = new Status(IStatus.WARNING, PDEPlugin.getPluginId(), IStatus.OK, message, null);
entries.add(status);
}
}
if (entries.size()>0) {
IStatus [] children = (IStatus[])entries.toArray(new IStatus[entries.size()]);
String message = PDEPlugin.getResourceString(KEY_BROKEN_PLUGINS);
final MultiStatus status = new MultiStatus(PDEPlugin.getPluginId(), IStatus.OK, children, message, null);
//monitor.setCanceled(true);
//throw new CoreException(status);
Display display = getDisplay();
display.syncExec(new Runnable() {
public void run() {
String title = PDEPlugin.getResourceString(KEY_TITLE);
ErrorDialog.openError(PDEPlugin.getActiveWorkbenchShell(), title, null, status);
}
});
}
}
private boolean doLaunch(
ILaunch launch,
ILaunchConfiguration config,
String mode,
IVMRunner runner,
IPath targetWorkspace,
boolean clearWorkspace,
ExecutionArguments args,
IPluginModelBase[] plugins,
String appname,
boolean tracing,
IProgressMonitor monitor)
throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(PDEPlugin.getResourceString(KEY_STARTING), 2);
try {
File propertiesFile =
TargetPlatform.createPropertiesFile(plugins, targetWorkspace);
String[] vmArgs = args.getVMArgumentsArray();
String[] progArgs = args.getProgramArgumentsArray();
int exCount = tracing ? 8 : 6;
String[] fullProgArgs = new String[progArgs.length + exCount];
fullProgArgs[0] = appname;
fullProgArgs[1] = propertiesFile.getPath();
fullProgArgs[2] = "-dev";
fullProgArgs[3] = "bin";
fullProgArgs[4] = "-data";
fullProgArgs[5] = targetWorkspace.toOSString();
if (tracing) {
fullProgArgs[6] = "-debug";
fullProgArgs[7] = getTracingFileArgument(config);
}
System.arraycopy(progArgs, 0, fullProgArgs, exCount, progArgs.length);
String[] classpath = constructClasspath(plugins);
if (classpath == null) {
String message = PDEPlugin.getResourceString(KEY_NO_BOOT);
monitor.setCanceled(true);
throw new CoreException(createErrorStatus(message));
}
VMRunnerConfiguration runnerConfig =
new VMRunnerConfiguration("EclipseRuntimeLauncher", classpath);
runnerConfig.setVMArguments(vmArgs);
runnerConfig.setProgramArguments(fullProgArgs);
File workspaceFile = targetWorkspace.toFile();
if (clearWorkspace && workspaceFile.exists()) {
if (confirmDeleteWorkspace(workspaceFile)) {
try {
deleteContent(workspaceFile);
} catch (IOException e) {
String message = PDEPlugin.getResourceString(KEY_PROBLEMS_DELETING);
showWarningDialog(message);
}
}
}
monitor.worked(1);
if (monitor.isCanceled()) {
return false;
}
runner.run(runnerConfig, launch, monitor);
monitor.worked(1);
ISourceLocator sourceLocator = constructSourceLocator(plugins);
launch.setSourceLocator(sourceLocator);
} finally {
monitor.done();
}
return true;
}
private String getTracingFileArgument(ILaunchConfiguration config) {
TracingOptionsManager mng = PDECore.getDefault().getTracingOptionsManager();
Map options;
try {
options =
config.getAttribute(
ILauncherSettings.TRACING_OPTIONS,
mng.getTracingTemplateCopy());
} catch (CoreException e) {
return "";
}
mng.save(options);
String optionsFileName = mng.getTracingFileName();
String tracingArg;
if (SWT.getPlatform().equals("motif"))
tracingArg = "file:" + optionsFileName;
// defect 17661
else if (SWT.getPlatform().equals("gtk"))
tracingArg = "file://localhost" + optionsFileName;
else
tracingArg = "\"file:" + optionsFileName + "\"";
return tracingArg;
}
private void deleteContent(File curr) throws IOException {
if (curr.isDirectory()) {
File[] children = curr.listFiles();
for (int i = 0; i < children.length; i++) {
deleteContent(children[i]);
}
}
curr.delete();
}
private Display getDisplay() {
Display display = Display.getCurrent();
if (display == null) {
display = Display.getDefault();
}
return display;
}
private IStatus createErrorStatus(String message) {
return new Status(
IStatus.ERROR,
PDEPlugin.getPluginId(),
IStatus.OK,
message,
null);
}
private boolean confirmDeleteWorkspace(final File workspaceFile) {
Display display = getDisplay();
final boolean [] result = new boolean[1];
display.syncExec(new Runnable() {
public void run() {
String title = PDEPlugin.getResourceString(KEY_TITLE);
String message = PDEPlugin.getFormattedMessage(KEY_DELETE_WORKSPACE, workspaceFile.getPath());
result[0] = MessageDialog.openQuestion(PDEPlugin.getActiveWorkbenchShell(), title,message);
}
});
return result[0];
}
private void showWarningDialog(final String message) {
Display display = getDisplay();
display.syncExec(new Runnable() {
public void run() {
String title = PDEPlugin.getResourceString(KEY_TITLE);
MessageDialog.openWarning(PDEPlugin.getActiveWorkbenchShell(), title, message);
}
});
}
/**
* Constructs a classpath with the slimlauncher and the boot plugin (org.eclipse.core.boot)
* If the boot project is in the workspace, the classpath used in the workspace is used.
*/
private String[] constructClasspath(IPluginModelBase[] plugins)
throws CoreException {
File slimLauncher =
PDEPlugin.getFileInPlugin(new Path("launcher/slimlauncher.jar"));
if (slimLauncher == null || !slimLauncher.exists()) {
PDEPlugin.logErrorMessage(
PDEPlugin.getResourceString(KEY_SLIMLAUNCHER));
return null;
}
IPluginModelBase model = findModel("org.eclipse.core.boot", plugins);
if (model != null) {
IResource resource = model.getUnderlyingResource();
if (resource != null) {
// in workspace - use the java project
IProject project = resource.getProject();
IJavaProject jproject = JavaCore.create(project);
String[] bootClassPath = JavaRuntime.computeDefaultRuntimeClassPath(jproject);
if (bootClassPath != null) {
String[] resClassPath = new String[bootClassPath.length + 1];
resClassPath[0] = slimLauncher.getPath();
System.arraycopy(bootClassPath, 0, resClassPath, 1, bootClassPath.length);
return resClassPath;
}
} else {
// outside - locate boot.jar
String installLocation = model.getInstallLocation();
if (installLocation.startsWith("file:"))
installLocation = installLocation.substring(5);
File bootJar = new File(installLocation, "boot.jar");
if (bootJar.exists()) {
return new String[] { slimLauncher.getPath(), bootJar.getPath()};
}
// Check PDE case (third instance) - it may be in the bin
File binDir = new File(installLocation, "bin/");
if (binDir.exists()) {
return new String[] { slimLauncher.getPath(), binDir.getPath()};
}
}
}
// failed to construct the class path: boot plugin not existing or boot.jar not found
return null;
}
private IPluginModelBase findModel(String id, IPluginModelBase[] models) {
for (int i = 0; i < models.length; i++) {
IPluginModelBase model = (IPluginModelBase) models[i];
if (model.getPluginBase().getId().equals(id))
return model;
}
return null;
}
/**
* Constructs a source locator containg all projects selected as plugins.
*/
private ISourceLocator constructSourceLocator(IPluginModelBase[] plugins)
throws CoreException {
ArrayList javaProjects = new ArrayList(plugins.length);
IWorkspaceRoot root = PDEPlugin.getWorkspace().getRoot();
for (int i = 0; i < plugins.length; i++) {
try {
File pluginDir =
new File(new URL("file:" + plugins[i].getInstallLocation()).getFile());
IContainer container =
root.getContainerForLocation(new Path(pluginDir.getPath()));
if (container instanceof IProject) {
IProject project = (IProject) container;
if (WorkspaceModelManager.isJavaPluginProject(project))
javaProjects.add(JavaCore.create(project));
}
} catch (MalformedURLException e) {
PDEPlugin.log(e);
}
}
IJavaProject[] projs =
(IJavaProject[]) javaProjects.toArray(new IJavaProject[javaProjects.size()]);
return new JavaUISourceLocator(projs, false);
}
}