All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.core.internal.resources.ProjectDescription Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Martin Oberhuber (Wind River) - [245937] setLinkLocation() detects non-change
 *     Serge Beauchamp (Freescale Semiconductor) - [229633] Project Path Variable Support
 *     Markus Schorn (Wind River) - [306575] Save snapshot location with project
 *     Broadcom Corporation - build configurations and references
 *     Lars Vogel  - Bug 473427
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.net.URI;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.events.BuildCommand;
import org.eclipse.core.internal.utils.FileUtil;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;

public class ProjectDescription extends ModelObject implements IProjectDescription {
	// constants
	private static final IBuildConfiguration[] EMPTY_BUILD_CONFIG_REFERENCE_ARRAY = new IBuildConfiguration[0];
	private static final ICommand[] EMPTY_COMMAND_ARRAY = new ICommand[0];
	private static final IProject[] EMPTY_PROJECT_ARRAY = new IProject[0];
	private static final String[] EMPTY_STRING_ARRAY = new String[0];
	private static final String EMPTY_STR = ""; //$NON-NLS-1$

	protected static boolean isReading = false;

	//flags to indicate when we are in the middle of reading or writing a
	// workspace description
	//these can be static because only one description can be read at once.
	protected static boolean isWriting = false;
	protected ICommand[] buildSpec = EMPTY_COMMAND_ARRAY;
	protected String comment = EMPTY_STR;

	// Build configuration + References state
	/** Id of the currently active build configuration */
	protected String activeConfiguration = IBuildConfiguration.DEFAULT_CONFIG_NAME;
	/**
	 * The 'real' build configuration names set on this project.
	 * This doesn't contain the generated 'default' build configuration with name
	 * {@link IBuildConfiguration#DEFAULT_CONFIG_NAME}
	 * when no build configurations have been defined.
	 */
	protected String[] configNames = EMPTY_STRING_ARRAY;
	// Static + Dynamic project level references
	protected IProject[] staticRefs = EMPTY_PROJECT_ARRAY;
	protected IProject[] dynamicRefs = EMPTY_PROJECT_ARRAY;
	/** Map from config name in this project -> build configurations in other projects */
	protected HashMap dynamicConfigRefs = new HashMap<>(1);

	// Cache of the build configurations
	protected volatile IBuildConfiguration[] cachedBuildConfigs;
	// Cached build configuration references. Not persisted.
	protected Map cachedConfigRefs = Collections.synchronizedMap(new HashMap<>(1));
	/**
	 * Cached project level references. Synchronize on {@link #cachedRefsMutex} before reading or writing. Increment
	 * {@link #cachedRefsDirtyCount} whenever this is dirtied.
	 */
	protected IProject[] cachedRefs;
	/**
	 * Counts the number of times {@link #cachedRefs} has been dirtied. Can be used to determine if dynamic dependencies have
	 * changed during an operation that is intended to be atomic with respect to dynamic dependencies. Synchronize on
	 * {@link #cachedRefsMutex} before accessing.
	 */
	protected int cachedRefsDirtyCount;
	/**
	 * Mutex used to protect {@link #cachedRefs} and {@link #cachedRefsDirtyCount}.
	 */
	protected final Object cachedRefsMutex = new Object();

	/**
	 * Map of (IPath -> LinkDescription) pairs for each linked resource
	 * in this project, where IPath is the project relative path of the resource.
	 */
	protected HashMap linkDescriptions = null;

	/**
	 * Map of {@literal (IPath -> LinkedList)} pairs for each filtered resource
	 * in this project, where IPath is the project relative path of the resource.
	 */
	protected HashMap> filterDescriptions = null;

	/**
	 * Map of (String -> VariableDescription) pairs for each variable in this
	 * project, where String is the name of the variable.
	 */
	protected HashMap variableDescriptions = null;

	// fields
	protected URI location = null;
	protected String[] natures = EMPTY_STRING_ARRAY;
	protected URI snapshotLocation = null;

	public ProjectDescription() {
		super();
	}

	@Override
	@SuppressWarnings({"unchecked"})
	public Object clone() {
		ProjectDescription clone = (ProjectDescription) super.clone();
		//don't want the clone to have access to our internal link locations table or builders
		clone.linkDescriptions = null;
		clone.filterDescriptions = null;
		if (variableDescriptions != null)
			clone.variableDescriptions = (HashMap) variableDescriptions.clone();
		clone.buildSpec = getBuildSpec(true);
		clone.dynamicConfigRefs = (HashMap) dynamicConfigRefs.clone();
		clone.cachedConfigRefs = Collections.synchronizedMap(new HashMap<>(1));
		clone.clearCachedDynamicReferences(null);
		return clone;
	}

	/**
	 * Clear cached references for the specified build config name
	 * or all if configName is null.
	 */
	public void clearCachedDynamicReferences(String configName) {
		synchronized (cachedRefsMutex) {
			if (configName == null)
				cachedConfigRefs.clear();
			else
				cachedConfigRefs.remove(configName);
			cachedRefs = null;
			cachedRefsDirtyCount++;
		}
	}

	/**
	 * Returns a copy of the given array of build configs with all duplicates removed
	 */
	private IBuildConfiguration[] copyAndRemoveDuplicates(IBuildConfiguration[] values) {
		Set set = new LinkedHashSet<>(Arrays.asList(values));
		return set.toArray(new IBuildConfiguration[set.size()]);
	}

	/**
	 * Returns a copy of the given array with all duplicates removed
	 */
	private IProject[] copyAndRemoveDuplicates(IProject[] projects) {
		IProject[] result = new IProject[projects.length];
		int count = 0;
		next: for (IProject project : projects) {
			// scan to see if there are any other projects by the same name
			for (int j = 0; j < count; j++)
				if (project.equals(result[j]))
					continue next;
			// not found
			result[count++] = project;
		}
		if (count < projects.length) {
			//shrink array
			IProject[] reduced = new IProject[count];
			System.arraycopy(result, 0, reduced, 0, count);
			return reduced;
		}
		return result;
	}

	/**
	 * Helper to turn an array of projects into an array of {@link IBuildConfiguration} to the
	 * projects' active configuration
	 * Order is preserved - the buildConfigs appear for each project in the order
	 * that the projects were specified.
	 * @param projects projects to get the active configuration from
	 * @return collection of build config references
	 */
	private Collection getBuildConfigReferencesFromProjects(IProject[] projects) {
		List refs = new ArrayList<>(projects.length);
		for (IProject project : projects)
			refs.add(new BuildConfiguration(project, null));
		return refs;
	}

	/**
	 * Helper to fetch projects from an array of build configuration references
	 * @param refs
	 * @return {@literal List}
	 */
	private Collection getProjectsFromBuildConfigRefs(IBuildConfiguration[] refs) {
		LinkedHashSet projects = new LinkedHashSet<>(refs.length);
		for (IBuildConfiguration ref : refs)
			projects.add(ref.getProject());
		return projects;
	}

	public String getActiveBuildConfig() {
		return activeConfiguration;
	}

	/**
	 * Returns the union of the description's static and dynamic project references,
	 * with duplicates omitted. The calculation is optimized by caching the result
	 * Call the configuration based implementation.
	 * @see #getAllBuildConfigReferences(IProject, String, boolean)
	 */
	public IProject[] getAllReferences(IProject project, boolean makeCopy) {
		int dirtyCount;
		IProject[] projRefs;

		synchronized (cachedRefsMutex) {
			projRefs = cachedRefs;
			dirtyCount = cachedRefsDirtyCount;
		}
		// Retry this computation until we're able to proceed to the end without someone dirtying the cache.
		// This loop is here to prevent us from caching a stale result if someone dirties the cache between
		// the time we invoke getAllBuildConfigReferences and the time we can write to cachedRefs.
		while (projRefs == null) {
			IBuildConfiguration[] refs;
			if (hasBuildConfig(activeConfiguration))
				refs = getAllBuildConfigReferences(project, activeConfiguration, false);
			else if (configNames.length > 0)
				refs = getAllBuildConfigReferences(project, configNames[0], false);
			else
				// No build configuration => fall-back to default
				refs = getAllBuildConfigReferences(project, IBuildConfiguration.DEFAULT_CONFIG_NAME, false);
			Collection l = getProjectsFromBuildConfigRefs(refs);

			synchronized (cachedRefsMutex) {
				// If nobody dirtied the cache since the start of this operation then we can cache the
				// new result and end the loop.
				if (cachedRefsDirtyCount == dirtyCount) {
					cachedRefs = l.toArray(new IProject[l.size()]);
				}
				projRefs = cachedRefs;
				dirtyCount = cachedRefsDirtyCount;
			}
		}
		//still need to copy the result to prevent tampering with the cache
		return makeCopy ? (IProject[]) projRefs.clone() : projRefs;
	}

	/**
	 * The main entrance point to fetch the full set of Project references.
	 *
	 * Returns the union of all the description's references. Includes static and dynamic
	 * project level references as well as build configuration references for the configuration
	 * with the given id.
	 * Duplicates are omitted.  The calculation is optimized by caching the result.
	 * Note that these BuildConfiguration references may have null name.  They must
	 * be resolved using {@link BuildConfiguration#getBuildConfig()} before use.
	 * Returns an empty array if the given configName does not exist in the description.
	 */
	public IBuildConfiguration[] getAllBuildConfigReferences(IProject project, String configName, boolean makeCopy) {
		if (!hasBuildConfig(configName))
			return EMPTY_BUILD_CONFIG_REFERENCE_ARRAY;
		IBuildConfiguration[] refs = cachedConfigRefs.get(configName);
		if (refs == null) {
			Set references = new LinkedHashSet<>();
			IBuildConfiguration[] dynamicBuildConfigs = dynamicConfigRefs.containsKey(configName) ? dynamicConfigRefs.get(configName) : EMPTY_BUILD_CONFIG_REFERENCE_ARRAY;
			Collection dynamic;
			try {
				IBuildConfiguration buildConfig = project.getBuildConfig(configName);
				dynamic = getBuildConfigReferencesFromProjects(computeDynamicReferencesForProject(buildConfig, getBuildSpec()));
			} catch (CoreException e) {
				dynamic = Collections.emptyList();
			}
			Collection legacyDynamic = getBuildConfigReferencesFromProjects(dynamicRefs);
			Collection statik = getBuildConfigReferencesFromProjects(staticRefs);

			// Combine all references:
			// New build config references (which only come in dynamic form) trump all others.
			references.addAll(Arrays.asList(dynamicBuildConfigs));
			// We preserve the previous order of static project references before dynamic project references
			references.addAll(statik);
			references.addAll(legacyDynamic);
			references.addAll(dynamic);
			refs = references.toArray(new IBuildConfiguration[references.size()]);
			cachedConfigRefs.put(configName, refs);
		}
		return makeCopy ? (IBuildConfiguration[]) refs.clone() : refs;
	}

	/**
	 * Used by Project to get the buildConfigs on the description.
	 * @return the project configurations
	 */
	public IBuildConfiguration[] getBuildConfigs(IProject project, boolean makeCopy) {
		IBuildConfiguration[] configs = cachedBuildConfigs;
		// Ensure project is up to date in the cache
		if (configs != null && !project.equals(configs[0].getProject()))
			configs = null;
		if (configs == null) {
			if (configNames.length == 0)
				configs = new IBuildConfiguration[] {new BuildConfiguration(project)};
			else {
				configs = new IBuildConfiguration[configNames.length];
				for (int i = 0; i < configs.length; i++)
					configs[i] = new BuildConfiguration(project, configNames[i]);
			}
			cachedBuildConfigs = configs;
		}
		return makeCopy ? (IBuildConfiguration[]) configs.clone() : configs;
	}

	@Override
	public IBuildConfiguration[] getBuildConfigReferences(String configName) {
		return getBuildConfigRefs(configName, true);
	}

	public IBuildConfiguration[] getBuildConfigRefs(String configName, boolean makeCopy) {
		if (!hasBuildConfig(configName) || !dynamicConfigRefs.containsKey(configName))
			return EMPTY_BUILD_CONFIG_REFERENCE_ARRAY;

		return makeCopy ? (IBuildConfiguration[]) dynamicConfigRefs.get(configName).clone() : dynamicConfigRefs.get(configName);
	}

	/**
	 * Returns the build configuration references map
	 * @param makeCopy
	 */
	@SuppressWarnings({"unchecked"})
	public Map getBuildConfigReferences(boolean makeCopy) {
		return makeCopy ? (Map) dynamicConfigRefs.clone() : dynamicConfigRefs;
	}

	@Override
	public ICommand[] getBuildSpec() {
		return getBuildSpec(true);
	}

	public ICommand[] getBuildSpec(boolean makeCopy) {
		//thread safety: copy reference in case of concurrent write
		ICommand[] oldCommands = this.buildSpec;
		if (oldCommands == null)
			return EMPTY_COMMAND_ARRAY;
		if (!makeCopy)
			return oldCommands;
		ICommand[] result = new ICommand[oldCommands.length];
		for (int i = 0; i < result.length; i++)
			result[i] = (ICommand) ((BuildCommand) oldCommands[i]).clone();
		return result;
	}

	@Override
	public String getComment() {
		return comment;
	}

	@Override
	public IProject[] getDynamicReferences() {
		return getDynamicReferences(true);
	}

	public IProject[] getDynamicReferences(boolean makeCopy) {
		return makeCopy ? (IProject[]) dynamicRefs.clone() : dynamicRefs;
	}

	/**
	 * Returns the link location for the given resource name. Returns null if
	 * no such link exists.
	 */
	public URI getLinkLocationURI(IPath aPath) {
		if (linkDescriptions == null)
			return null;
		LinkDescription desc = linkDescriptions.get(aPath);
		return desc == null ? null : desc.getLocationURI();
	}

	/**
	 * Returns the filter for the given resource name. Returns null if
	 * no such filter exists.
	 */
	synchronized public LinkedList getFilter(IPath aPath) {
		if (filterDescriptions == null)
			return null;
		return filterDescriptions.get(aPath);
	}

	/**
	 * Returns the map of link descriptions (IPath (project relative path) -> LinkDescription).
	 * Since this method is only used internally, it never creates a copy.
	 * Returns null if the project does not have any linked resources.
	 */
	public HashMap getLinks() {
		return linkDescriptions;
	}

	/**
	 * Returns the map of filter descriptions (IPath (project relative path) ->
	 * {@literal LinkedList}). Since this method is only used
	 * internally, it never creates a copy. Returns null if the project does not
	 * have any filtered resources.
	 */
	public HashMap> getFilters() {
		return filterDescriptions;
	}

	/**
	 * Returns the map of variable descriptions (String (variable name) ->
	 * VariableDescription). Since this method is only used internally, it never
	 * creates a copy. Returns null if the project does not have any variables.
	 */
	public HashMap getVariables() {
		return variableDescriptions;
	}

	/**
	 * @see IProjectDescription#getLocation()
	 * @deprecated
	 */
	@Override
	@Deprecated
	public IPath getLocation() {
		if (location == null)
			return null;
		return FileUtil.toPath(location);
	}

	@Override
	public URI getLocationURI() {
		return location;
	}

	@Override
	public String[] getNatureIds() {
		return getNatureIds(true);
	}

	public String[] getNatureIds(boolean makeCopy) {
		if (natures == null)
			return EMPTY_STRING_ARRAY;
		return makeCopy ? (String[]) natures.clone() : natures;
	}

	@Override
	public IProject[] getReferencedProjects() {
		return getReferencedProjects(true);
	}

	public IProject[] getReferencedProjects(boolean makeCopy) {
		if (staticRefs == null)
			return EMPTY_PROJECT_ARRAY;
		return makeCopy ? (IProject[]) staticRefs.clone() : staticRefs;
	}

	/**
	 * Returns the URI to load a resource snapshot from.
	 * May return null if no snapshot is set.
	 * 

* EXPERIMENTAL. This constant has been added as * part of a work in progress. There is no guarantee that this API will * work or that it will remain the same. Please do not use this API without * consulting with the Platform Core team. *

* @return the snapshot location URI, * or null. * @see IProject#loadSnapshot(int, URI, IProgressMonitor) * @see #setSnapshotLocationURI(URI) * @since 3.6 */ public URI getSnapshotLocationURI() { return snapshotLocation; } @Override public boolean hasNature(String natureID) { String[] natureIDs = getNatureIds(false); for (String natureID2 : natureIDs) if (natureID2.equals(natureID)) return true; return false; } /** * Helper method to compare two maps of Configuration Name -> IBuildConfigurationReference[] * @return boolean indicating if there are differences between the two maps */ private static boolean configRefsHaveChanges(Map m1, Map m2) { if (m1.size() != m2.size()) return true; for (Entry e : m1.entrySet()) { if (!m2.containsKey(e.getKey())) return true; if (!Arrays.equals(e.getValue(), m2.get(e.getKey()))) return true; } return false; } /** * Internal method to check if the description has a given build configuration. */ boolean hasBuildConfig(String buildConfigName) { Assert.isNotNull(buildConfigName); if (configNames.length == 0) return IBuildConfiguration.DEFAULT_CONFIG_NAME.equals(buildConfigName); for (String configName : configNames) if (configName.equals(buildConfigName)) return true; return false; } /** * Returns true if any private attributes of the description have changed. * Private attributes are those that are not stored in the project description * file (.project). */ public boolean hasPrivateChanges(ProjectDescription description) { if (location == null) { if (description.location != null) return true; } else if (!location.equals(description.location)) return true; if (!Arrays.equals(dynamicRefs, description.dynamicRefs)) return true; // Build Configuration state if (!activeConfiguration.equals(description.activeConfiguration)) return true; if (!Arrays.equals(configNames, description.configNames)) return true; // Configuration level references if (configRefsHaveChanges(dynamicConfigRefs, description.dynamicConfigRefs)) return true; return false; } /** * Returns true if any public attributes of the description have changed. * Public attributes are those that are stored in the project description * file (.project). */ public boolean hasPublicChanges(ProjectDescription description) { if (!getName().equals(description.getName())) return true; if (!comment.equals(description.getComment())) return true; //don't bother optimizing if the order has changed if (!Arrays.equals(buildSpec, description.getBuildSpec(false))) return true; if (!Arrays.equals(staticRefs, description.getReferencedProjects(false))) return true; if (!Arrays.equals(natures, description.getNatureIds(false))) return true; HashMap> otherFilters = description.getFilters(); if ((filterDescriptions == null) && (otherFilters != null)) return otherFilters != null; if ((filterDescriptions != null) && !filterDescriptions.equals(otherFilters)) return true; HashMap otherVariables = description.getVariables(); if ((variableDescriptions == null) && (otherVariables != null)) return true; if ((variableDescriptions != null) && !variableDescriptions.equals(otherVariables)) return true; final HashMap otherLinks = description.getLinks(); if (linkDescriptions != otherLinks) { if (linkDescriptions == null || !linkDescriptions.equals(otherLinks)) return true; } final URI otherSnapshotLoc = description.getSnapshotLocationURI(); if (snapshotLocation != otherSnapshotLoc) { if (snapshotLocation == null || !snapshotLocation.equals(otherSnapshotLoc)) return true; } return false; } @Override public ICommand newCommand() { return new BuildCommand(); } @Override public void setActiveBuildConfig(String configName) { Assert.isNotNull(configName); if (!configName.equals(activeConfiguration)) clearCachedDynamicReferences(null); activeConfiguration = configName; } @Override public void setBuildSpec(ICommand[] value) { Assert.isLegal(value != null); //perform a deep copy in case clients perform further changes to the command ICommand[] result = new ICommand[value.length]; for (int i = 0; i < result.length; i++) { result[i] = (ICommand) ((BuildCommand) value[i]).clone(); //copy the reference to any builder instance from the old build spec //to preserve builder states if possible. for (ICommand element : buildSpec) { if (result[i].equals(element)) { ((BuildCommand) result[i]).setBuilders(((BuildCommand) element).getBuilders()); break; } } } buildSpec = result; } @Override public void setComment(String value) { comment = value; } @Deprecated @Override public void setDynamicReferences(IProject[] value) { Assert.isLegal(value != null); dynamicRefs = copyAndRemoveDuplicates(value); clearCachedDynamicReferences(null); } public void setBuildConfigReferences(HashMap refs) { dynamicConfigRefs = new HashMap<>(refs); clearCachedDynamicReferences(null); } @Override public void setBuildConfigReferences(String configName, IBuildConfiguration[] references) { Assert.isLegal(configName != null); Assert.isLegal(references != null); if (!hasBuildConfig(configName)) return; dynamicConfigRefs.put(configName, copyAndRemoveDuplicates(references)); clearCachedDynamicReferences(configName); } @Override public void setBuildConfigs(String[] names) { // Remove references for deleted buildConfigs LinkedHashSet buildConfigNames = new LinkedHashSet<>(); if (names == null || names.length == 0) { configNames = EMPTY_STRING_ARRAY; buildConfigNames.add(IBuildConfiguration.DEFAULT_CONFIG_NAME); } else { // Filter out duplicates for (String n : names) { Assert.isLegal(n != null); buildConfigNames.add(n); } if (buildConfigNames.size() == 1 && ((buildConfigNames.iterator().next())).equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) configNames = EMPTY_STRING_ARRAY; else configNames = buildConfigNames.toArray(new String[buildConfigNames.size()]); } // Remove references for deleted buildConfigs boolean modified = dynamicConfigRefs.keySet().retainAll(buildConfigNames); if (modified) clearCachedDynamicReferences(null); // Clear the cached IBuildConfiguration[] cachedBuildConfigs = null; } /** * Sets the map of link descriptions (String name -> LinkDescription). * Since this method is only used internally, it never creates a copy. May * pass null if this project does not have any linked resources */ public void setLinkDescriptions(HashMap linkDescriptions) { this.linkDescriptions = linkDescriptions; } /** * Sets the map of filter descriptions {@literal (String name -> LinkedList)}. * Since this method is only used internally, it never creates a copy. May * pass null if this project does not have any filtered resources */ public void setFilterDescriptions(HashMap> filterDescriptions) { this.filterDescriptions = filterDescriptions; } /** * Sets the map of variable descriptions (String name -> * VariableDescription). Since this method is only used internally, it never * creates a copy. May pass null if this project does not have any variables */ public void setVariableDescriptions(HashMap variableDescriptions) { this.variableDescriptions = variableDescriptions; } /** * Sets the description of a link. Setting to a description of null will * remove the link from the project description. * @return true if the description was actually changed, * false otherwise. * @since 3.5 returns boolean (was void before) */ @SuppressWarnings({"unchecked"}) public boolean setLinkLocation(IPath path, LinkDescription description) { HashMap tempMap = linkDescriptions; if (description != null) { //addition or modification if (tempMap == null) tempMap = new HashMap<>(10); else //copy on write to protect against concurrent read tempMap = (HashMap) tempMap.clone(); Object oldValue = tempMap.put(path, description); if (oldValue != null && description.equals(oldValue)) { //not actually changed anything return false; } linkDescriptions = tempMap; } else { //removal if (tempMap == null) return false; //copy on write to protect against concurrent access HashMap newMap = (HashMap) tempMap.clone(); Object oldValue = newMap.remove(path); if (oldValue == null) { //not actually changed anything return false; } linkDescriptions = newMap.isEmpty() ? null : newMap; } return true; } /** * Add the description of a filter. Setting to a description of null will * remove the filter from the project description. */ synchronized public void addFilter(IPath path, FilterDescription description) { Assert.isNotNull(description); if (filterDescriptions == null) filterDescriptions = new HashMap<>(10); LinkedList descList = filterDescriptions.get(path); if (descList == null) { descList = new LinkedList<>(); filterDescriptions.put(path, descList); } descList.add(description); } /** * Add the description of a filter. Setting to a description of null will * remove the filter from the project description. */ synchronized public void removeFilter(IPath path, FilterDescription description) { if (filterDescriptions != null) { LinkedList descList = filterDescriptions.get(path); if (descList != null) { descList.remove(description); if (descList.isEmpty()) { filterDescriptions.remove(path); if (filterDescriptions.isEmpty()) filterDescriptions = null; } } } } /** * Sets the description of a variable. Setting to a description of null will * remove the variable from the project description. * @return true if the description was actually changed, * false otherwise. * @since 3.5 */ @SuppressWarnings({"unchecked"}) public boolean setVariableDescription(String name, VariableDescription description) { HashMap tempMap = variableDescriptions; if (description != null) { // addition or modification if (tempMap == null) tempMap = new HashMap<>(10); else // copy on write to protect against concurrent read tempMap = (HashMap) tempMap.clone(); Object oldValue = tempMap.put(name, description); if (oldValue != null && description.equals(oldValue)) { //not actually changed anything return false; } variableDescriptions = tempMap; } else { // removal if (tempMap == null) return false; // copy on write to protect against concurrent access HashMap newMap = (HashMap) tempMap.clone(); Object oldValue = newMap.remove(name); if (oldValue == null) { //not actually changed anything return false; } variableDescriptions = newMap.isEmpty() ? null : newMap; } return true; } /** * set the filters for a given resource. Setting to a description of null will * remove the filter from the project description. * @return true if the description was actually changed, * false otherwise. */ synchronized public boolean setFilters(IPath path, LinkedList descriptions) { if (descriptions != null) { // addition if (filterDescriptions == null) filterDescriptions = new HashMap<>(10); Object oldValue = filterDescriptions.put(path, descriptions); if (oldValue != null && descriptions.equals(oldValue)) { //not actually changed anything return false; } } else { // removal if (filterDescriptions == null) return false; Object oldValue = filterDescriptions.remove(path); if (oldValue == null) { //not actually changed anything return false; } if (filterDescriptions.isEmpty()) filterDescriptions = null; } return true; } @Override public void setLocation(IPath path) { this.location = path == null ? null : URIUtil.toURI(path); } @Override public void setLocationURI(URI location) { this.location = location; } @Override public void setName(String value) { super.setName(value); } @Override public void setNatureIds(String[] value) { natures = value.clone(); } @Override public void setReferencedProjects(IProject[] value) { Assert.isLegal(value != null); staticRefs = copyAndRemoveDuplicates(value); clearCachedDynamicReferences(null); } /** * Sets the location URI for a project snapshot that may be * loaded automatically when the project is created in a workspace. *

* EXPERIMENTAL. This method has been added as * part of a work in progress. There is no guarantee that this API will * work or that it will remain the same. Please do not use this API without * consulting with the Platform Core team. *

* @param snapshotLocation the location URI or * null to clear the setting * @see IProject#loadSnapshot(int, URI, IProgressMonitor) * @see #getSnapshotLocationURI() * @since 3.6 */ public void setSnapshotLocationURI(URI snapshotLocation) { this.snapshotLocation = snapshotLocation; } public URI getGroupLocationURI(IPath projectRelativePath) { return LinkDescription.VIRTUAL_LOCATION; } /** * Updates the dynamic build configuration and reference state to that of the passed in * description. * Copies in: *
    *
  • Active configuration name
  • *
  • Dynamic Project References
  • *
  • Build configurations list
  • *
  • Build Configuration References
  • *
* @param description Project description to copy dynamic state from * @return boolean indicating if anything changed requing re-calculation of WS build order */ public boolean updateDynamicState(ProjectDescription description) { boolean changed = false; if (!activeConfiguration.equals(description.activeConfiguration)) { changed = true; activeConfiguration = description.activeConfiguration; } if (!Arrays.equals(dynamicRefs, description.dynamicRefs)) { changed = true; setDynamicReferences(description.dynamicRefs); } if (!Arrays.equals(configNames, description.configNames)) { changed = true; setBuildConfigs(description.configNames); } if (configRefsHaveChanges(dynamicConfigRefs, description.dynamicConfigRefs)) { changed = true; dynamicConfigRefs = new HashMap<>(description.dynamicConfigRefs); } if (changed) clearCachedDynamicReferences(null); return changed; } /** * Computes the dynamic references for the given project + configuration. */ private static IProject[] computeDynamicReferencesForProject(IBuildConfiguration buildConfig, ICommand[] buildSpec) { List result = new ArrayList<>(); for (ICommand command : buildSpec) { IExtension extension = Platform.getExtensionRegistry().getExtension(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_BUILDERS, command.getBuilderName()); if (extension == null) { continue; } IConfigurationElement[] configurationElements = extension.getConfigurationElements(); if (configurationElements.length == 0) { continue; } IConfigurationElement element = configurationElements[0]; Object executableExtension; try { IConfigurationElement[] children = element.getChildren("dynamicReference"); //$NON-NLS-1$ if (children.length != 0) { executableExtension = children[0].createExecutableExtension("class"); //$NON-NLS-1$ if (executableExtension instanceof IDynamicReferenceProvider) { IDynamicReferenceProvider provider = (IDynamicReferenceProvider) executableExtension; result.addAll(provider.getDependentProjects(buildConfig)); } } } catch (CoreException e) { String problemElement = element.toString(); ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, "Unable to load dynamic reference provider: " + problemElement, e)); //$NON-NLS-1$ } } return result.toArray(new IProject[0]); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy