blob: 20b57249b614c9e55474843fb2b3f5ba4d683065 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.externaltools.internal.model;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.externaltools.internal.registry.ExternalToolMigration;
/**
* Utility methods for working with external tool project builders.
*/
public class BuilderUtils {
public static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$
public static final String BUILDER_FOLDER_NAME= ".externalToolBuilders"; //$NON-NLS-1$
// Extension point constants.
private static final String TAG_CONFIGURATION_MAP= "configurationMap"; //$NON-NLS-1$
private static final String TAG_SOURCE_TYPE= "sourceType"; //$NON-NLS-1$
private static final String TAG_BUILDER_TYPE= "builderType"; //$NON-NLS-1$
/**
* Returns a launch configuration from the given ICommand arguments. If the
* given arguments are from an old-style external tool, an unsaved working
* copy will be created from the arguments and returned.
*
* @param commandArgs the builder ICommand arguments
* @return a launch configuration, a launch configuration working copy, or
* <code>null</code> if not possible.
*/
public static ILaunchConfiguration configFromBuildCommandArgs(IProject project, Map commandArgs) {
String configHandle = (String) commandArgs.get(LAUNCH_CONFIG_HANDLE);
if (configHandle == null) {
// Probably an old-style external tool. Try to migrate.
return ExternalToolMigration.configFromArgumentMap(commandArgs);
}
ILaunchManager manager= DebugPlugin.getDefault().getLaunchManager();
ILaunchConfiguration configuration= null;
try {
// First, treat the configHandle as a memento. This is the format
// used before 3.0
configuration = manager.getLaunchConfiguration(configHandle);
} catch (CoreException e) {
}
if (configuration == null) {
// If the memento failed, try treating the handle as a file name.
// This is the format used in 3.0.
IPath path= new Path(BUILDER_FOLDER_NAME).append(configHandle);
IFile file= project.getFile(path);
if (file.exists()) {
configuration= manager.getLaunchConfiguration(file);
}
}
return configuration;
}
/**
* Returns an <code>ICommand</code> from the given launch configuration.
*
* @param project the project the ICommand is relevant to
* @param config, the launch configuration to create the command from
* @return the new command. <code>null</code> can be returned if problems occur during
* the translation.
*/
public static ICommand commandFromLaunchConfig(IProject project, ILaunchConfiguration config) {
ICommand newCommand = null;
try {
newCommand = project.getDescription().newCommand();
newCommand = toBuildCommand(project, config, newCommand);
} catch (CoreException exception) {
Shell shell= ExternalToolsPlugin.getActiveWorkbenchShell();
if (shell != null) {
MessageDialog.openError(shell, ExternalToolsModelMessages.getString("BuilderUtils.5"), ExternalToolsModelMessages.getString("BuilderUtils.6")); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
return newCommand;
}
/**
* Returns whether the given configuration is an "unmigrated" builder.
* Unmigrated builders are external tools that are stored in an old format
* but have not been migrated by the user. Old format builders are always
* translated into launch config working copies in memory, but they're not
* considered "migrated" until the config has been saved and the project spec
* updated.
* @param config the config to examine
* @return whether the given config represents an unmigrated builder
*/
public static boolean isUnmigratedConfig(ILaunchConfiguration config) {
return config.isWorkingCopy() && ((ILaunchConfigurationWorkingCopy) config).getOriginal() == null;
}
/**
* Converts the given config to a build command which is stored in the
* given command.
*
* @return the configured build command
*/
public static ICommand toBuildCommand(IProject project, ILaunchConfiguration config, ICommand command) throws CoreException {
Map args= null;
if (isUnmigratedConfig(config)) {
// This config represents an old external tool builder that hasn't
// been edited. Try to find the old ICommand and reuse the arguments.
// The goal here is to not change the storage format of old, unedited builders.
ICommand[] commands= project.getDescription().getBuildSpec();
for (int i = 0; i < commands.length; i++) {
ICommand projectCommand = commands[i];
String name= ExternalToolMigration.getNameFromCommandArgs(projectCommand.getArguments());
if (name != null && name.equals(config.getName())) {
args= projectCommand.getArguments();
break;
}
}
} else {
if (config instanceof ILaunchConfigurationWorkingCopy) {
ILaunchConfigurationWorkingCopy workingCopy= (ILaunchConfigurationWorkingCopy) config;
if (workingCopy.getOriginal() != null) {
config= workingCopy.getOriginal();
}
}
args= new HashMap();
// Launch configuration builders are stored by their name only.
// The config's location is recreated dynamically based on the
// containing project.
args.put(LAUNCH_CONFIG_HANDLE, config.getFile().getName());
}
command.setBuilderName(ExternalToolBuilder.ID);
command.setArguments(args);
return command;
}
/**
* Returns the type of launch configuration that should be created when
* duplicating the given configuration as a project builder. Queries to see
* if an extension has been specified to explicitly declare the mapping.
*/
public static ILaunchConfigurationType getConfigurationDuplicationType(ILaunchConfiguration config) throws CoreException {
IExtensionPoint ep= ExternalToolsPlugin.getDefault().getDescriptor().getExtensionPoint(IExternalToolConstants.EXTENSION_POINT_CONFIGURATION_DUPLICATION_MAPS);
IConfigurationElement[] elements = ep.getConfigurationElements();
String sourceType= config.getType().getIdentifier();
String builderType= null;
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (element.getName().equals(TAG_CONFIGURATION_MAP) && sourceType.equals(element.getAttribute(TAG_SOURCE_TYPE))) {
builderType= element.getAttribute(TAG_BUILDER_TYPE);
break;
}
}
if (builderType != null) {
ILaunchConfigurationType type= DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(builderType);
if (type != null) {
return type;
}
}
return config.getType();
}
/**
* Returns the folder where project builders should be stored or
* <code>null</code> if the folder could not be created
*/
public static IFolder getBuilderFolder(IProject project, boolean create) {
IFolder folder = project.getFolder(BUILDER_FOLDER_NAME);
if (!folder.exists() && create) {
try {
folder.create(true, true, new NullProgressMonitor());
} catch (CoreException e) {
return null;
}
}
return folder;
}
/**
* Returns a duplicate of the given configuration. The new configuration
* will be of the same type as the given configuration or of the duplication
* type registered for the given configuration via the extension point
* IExternalToolConstants.EXTENSION_POINT_CONFIGURATION_DUPLICATION_MAPS.
*/
public static ILaunchConfiguration duplicateConfiguration(IProject project, ILaunchConfiguration config) throws CoreException {
Map attributes= null;
attributes= config.getAttributes();
String newName= new StringBuffer(config.getName()).append(ExternalToolsModelMessages.getString("BuilderUtils.7")).toString(); //$NON-NLS-1$
newName= DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom(newName);
ILaunchConfigurationType newType= getConfigurationDuplicationType(config);
ILaunchConfigurationWorkingCopy newWorkingCopy= newType.newInstance(getBuilderFolder(project, true), newName);
newWorkingCopy.setAttributes(attributes);
return newWorkingCopy.doSave();
}
/**
* Migrates the launch configuration working copy, which is based on an old-
* style external tool builder, to a new, saved launch configuration. The
* returned launch configuration will contain the same attributes as the
* given working copy with the exception of the configuration name, which
* may be changed during the migration. The name of the configuration will
* only be changed if the current name is not a valid name for a saved
* config.
*
* @param workingCopy the launch configuration containing attributes from an
* old-style project builder.
* @return ILaunchConfiguration a new, saved launch configuration whose
* attributes match those of the given working copy as well as possible
* @throws CoreException if an exception occurs while attempting to save the
* new launch configuration
*/
public static ILaunchConfiguration migrateBuilderConfiguration(IProject project, ILaunchConfigurationWorkingCopy workingCopy) throws CoreException {
workingCopy.setContainer(getBuilderFolder(project, true));
// Before saving, make sure the name is valid
String name= workingCopy.getName();
name.replace('/', '.');
if (name.charAt(0) == ('.')) {
name = name.substring(1);
}
IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
if (!status.isOK()) {
name = "ExternalTool"; //$NON-NLS-1$
}
name = DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom(name);
workingCopy.rename(name);
return workingCopy.doSave();
}
}