Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 2c796c2dd99d5460e65ddc44b2c06a939f826520 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
                                                                                
                                                       











                                                                                 
                                 





                                            
                                                            







                                                      
                                         







                                                                            





                                                                   
                                                                                             
 


                                                                       
                                                                                              



                                                                                  
        

                                                                    



                                                                                    
        



                                                                                            




                                                                                









                                                                                   
                                                                                                                            

                                                                                     

                                                                                                    



                                                                                        
                                                           




                                                                                    
                         
                        




                                                                                       
                                                                









                                                                                                     
                                 
                         



                                     







                                                                                              




                                                                                                       
                                                              








                                                                                                                                                                                                           
        
                                                                                                                     




                                                                                                                  
                                                                           





















                                                                                                                  











































                                                                                                                                     




                                                                                                         











                                                                                                                                  
                                                                                                                                                                                                























                                                                                                                                           
                                                                        
















                                                                                                                                       
                                                       



























                                                                                                                                                            
                                             










                                                                                                                   
















                                                              
                             


















                                                                                          





                                                                                   















                                                                             



                                                                   


                       
 
/*******************************************************************************
 * Copyright (c) 2000, 2005 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 java.util.StringTokenizer;

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.IncrementalProjectBuilder;
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.core.runtime.Platform;
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$

	/**
	 * Constant used to find a builder using the 3.0-interim format
	 */
	public static final String BUILDER_FOLDER_NAME= ".externalToolBuilders"; //$NON-NLS-1$
	/**
	 * Constant used to represent the current project in the 3.0-final format.
	 */
	public static final String PROJECT_TAG= "<project>"; //$NON-NLS-1$
	
	public static final String VERSION_1_0= "1.0"; //$NON-NLS-1$
	public static final String VERSION_2_1= "2.1"; //$NON-NLS-1$
	// The format shipped up to and including Eclipse 3.0 RC1
	public static final String VERSION_3_0_interim= "3.0.interim"; //$NON-NLS-1$
	// The format shipped in Eclipse 3.0 final
	public static final String VERSION_3_0_final= "3.0"; //$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$
    
    private static final String BUILD_TYPE_SEPARATOR = ","; //$NON-NLS-1$
    private static final int[] DEFAULT_BUILD_TYPES= new int[] {
                                    IncrementalProjectBuilder.INCREMENTAL_BUILD,
                                    IncrementalProjectBuilder.FULL_BUILD};

	/**
	 * 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[] version) {
		String configHandle = (String) commandArgs.get(LAUNCH_CONFIG_HANDLE);
		if (configHandle == null) {
			// Probably an old-style (Eclipse 1.0 or 2.0) external tool. Try to migrate.
			version[0]= VERSION_1_0;
			return ExternalToolMigration.configFromArgumentMap(commandArgs);
		}
		ILaunchManager manager= DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfiguration configuration= null;
		if (configHandle.startsWith(PROJECT_TAG)) {
			version[0]= VERSION_3_0_final;
			IPath path= new Path(configHandle);
			IFile file= project.getFile(path.removeFirstSegments(1));
			if (file.exists()) {
				configuration= manager.getLaunchConfiguration(file);
			}
		} else {
		    // Try treating the handle as a file name.
			// This is the format used in 3.0 RC1.
			IPath path= new Path(BUILDER_FOLDER_NAME).append(configHandle);
			IFile file= project.getFile(path);
			if (file.exists()) {
				version[0]= VERSION_3_0_interim;
				configuration= manager.getLaunchConfiguration(file);
			} else {
				try {
					// Treat the configHandle as a memento. This is the format
					// used in Eclipse 2.1.
					configuration = manager.getLaunchConfiguration(configHandle);
				} catch (CoreException e) {
				}
				if (configuration != null) {
					version[0]= VERSION_2_1;
				}
			}
		}
		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);
			configureTriggers(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;
	}
	
	public static void configureTriggers(ILaunchConfiguration config, ICommand newCommand) throws CoreException {
		newCommand.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false);
		newCommand.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false);
		newCommand.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false);
		newCommand.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false);
		String buildKinds= config.getAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, (String)null);
		int[] triggers= BuilderUtils.buildTypesToArray(buildKinds);
		for (int i = 0; i < triggers.length; i++) {
			switch (triggers[i]) {
				case IncrementalProjectBuilder.FULL_BUILD:
					newCommand.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
					break;
				case IncrementalProjectBuilder.INCREMENTAL_BUILD:
					newCommand.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
					break;
				case IncrementalProjectBuilder.AUTO_BUILD:
					newCommand.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
					break;
				case IncrementalProjectBuilder.CLEAN_BUILD:
					newCommand.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
					break;
			}
		}
		if (!config.getAttribute(IExternalToolConstants.ATTR_TRIGGERS_CONFIGURED, false)) {
			ILaunchConfigurationWorkingCopy copy= config.getWorkingCopy();
			copy.setAttribute(IExternalToolConstants.ATTR_TRIGGERS_CONFIGURED, true);
			copy.doSave();
		}
	}

	/**
	 * 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 with a project-relative path
			StringBuffer buffer= new StringBuffer(PROJECT_TAG);
			// Append the project-relative path (workspace path minus first segment)
			buffer.append('/').append(config.getFile().getFullPath().removeFirstSegments(1));
			args.put(LAUNCH_CONFIG_HANDLE, buffer.toString());
		}
		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= Platform.getExtensionRegistry().getExtensionPoint(IExternalToolConstants.PLUGIN_ID, 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= 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= 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();
	}

    /**
     * Converts the build types string into an array of
     * build kinds.
     *
     * @param buildTypes the string of built types to convert
     * @return the array of build kinds.
     */
    public static int[] buildTypesToArray(String buildTypes) {
    	if (buildTypes == null || buildTypes.length() == 0) {
    		return DEFAULT_BUILD_TYPES;
    	}
    	
    	int count = 0;
    	boolean incremental = false;
    	boolean full = false;
    	boolean auto = false;
        boolean clean= false;
    
    	StringTokenizer tokenizer = new StringTokenizer(buildTypes, BUILD_TYPE_SEPARATOR);
    	while (tokenizer.hasMoreTokens()) {
    		String token = tokenizer.nextToken();
    		if (IExternalToolConstants.BUILD_TYPE_INCREMENTAL.equals(token)) {
    			if (!incremental) {
    				incremental = true;
    				count++;
    			}
    		} else if (IExternalToolConstants.BUILD_TYPE_FULL.equals(token)) {
    			if (!full) {
    				full = true;
    				count++;
    			}
    		} else if (IExternalToolConstants.BUILD_TYPE_AUTO.equals(token)) {
    			if (!auto) {
    				auto = true;
    				count++;
    			}
    		} else if (IExternalToolConstants.BUILD_TYPE_CLEAN.equals(token)) {
                if (!clean) {
                    clean = true;
                    count++;
                }
            }
    	}
    
    	int[] results = new int[count];
    	count = 0;
    	if (incremental) {
    		results[count] = IncrementalProjectBuilder.INCREMENTAL_BUILD;
    		count++;
    	}
    	if (full) {
    		results[count] = IncrementalProjectBuilder.FULL_BUILD;
    		count++;
    	}
    	if (auto) {
    		results[count] = IncrementalProjectBuilder.AUTO_BUILD;
    		count++;
    	}
        if (clean) {
            results[count] = IncrementalProjectBuilder.CLEAN_BUILD;
            count++;
        }
    
    	return results;
    }
}

Back to the top