/*******************************************************************************
 *  Copyright (c) 2003, 2012 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 - Initial API and implementation
 *     Anna Dushistova (MontaVista) - [366771]Converter fails to convert a CDT makefile project
 *******************************************************************************/
package org.eclipse.cdt.managedbuilder.core;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.cdt.core.AbstractCExtension;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IConsoleParser;
import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.XmlStorageUtil;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyManager;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentBuildPathsChangeListener;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.cdt.managedbuilder.internal.buildproperties.BuildPropertyManager;
import org.eclipse.cdt.managedbuilder.internal.core.BooleanExpressionApplicabilityCalculator;
import org.eclipse.cdt.managedbuilder.internal.core.BuildDbgUtil;
import org.eclipse.cdt.managedbuilder.internal.core.BuildObject;
import org.eclipse.cdt.managedbuilder.internal.core.BuildSettingsUtil;
import org.eclipse.cdt.managedbuilder.internal.core.Builder;
import org.eclipse.cdt.managedbuilder.internal.core.BuilderFactory;
import org.eclipse.cdt.managedbuilder.internal.core.CommonBuilder;
import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
import org.eclipse.cdt.managedbuilder.internal.core.DefaultManagedConfigElement;
import org.eclipse.cdt.managedbuilder.internal.core.FolderInfo;
import org.eclipse.cdt.managedbuilder.internal.core.IMatchKeyProvider;
import org.eclipse.cdt.managedbuilder.internal.core.InputType;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedCommandLineGenerator;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject;
import org.eclipse.cdt.managedbuilder.internal.core.MatchKey;
import org.eclipse.cdt.managedbuilder.internal.core.MultiConfiguration;
import org.eclipse.cdt.managedbuilder.internal.core.MultiFolderInfo;
import org.eclipse.cdt.managedbuilder.internal.core.MultiResourceInfo;
import org.eclipse.cdt.managedbuilder.internal.core.Option;
import org.eclipse.cdt.managedbuilder.internal.core.OptionCategory;
import org.eclipse.cdt.managedbuilder.internal.core.OutputType;
import org.eclipse.cdt.managedbuilder.internal.core.ProjectType;
import org.eclipse.cdt.managedbuilder.internal.core.ResourceConfiguration;
import org.eclipse.cdt.managedbuilder.internal.core.Target;
import org.eclipse.cdt.managedbuilder.internal.core.TargetPlatform;
import org.eclipse.cdt.managedbuilder.internal.core.Tool;
import org.eclipse.cdt.managedbuilder.internal.core.ToolChain;
import org.eclipse.cdt.managedbuilder.internal.dataprovider.BuildConfigurationData;
import org.eclipse.cdt.managedbuilder.internal.dataprovider.ConfigurationDataProvider;
import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableProvider;
import org.eclipse.cdt.managedbuilder.internal.macros.BuildMacroProvider;
import org.eclipse.cdt.managedbuilder.internal.tcmodification.ToolChainModificationManager;
import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator;
import org.eclipse.cdt.managedbuilder.projectconverter.UpdateManagedProjectManager;
import org.eclipse.cdt.managedbuilder.tcmodification.IToolChainModificationManager;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
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.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
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.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;

/**
 * This is the main entry point for getting at the build information
 * for the managed build system.
 *
 * @noextend This class is not intended to be subclassed by clients.
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class ManagedBuildManager extends AbstractCExtension {
//	private static final QualifiedName buildInfoProperty = new QualifiedName(ManagedBuilderCorePlugin.PLUGIN_ID, "managedBuildInfo");	//$NON-NLS-1$
	private static final String ROOT_NODE_NAME = "ManagedProjectBuildInfo";	//$NON-NLS-1$
	public  static final String SETTINGS_FILE_NAME = ".cdtbuild";	//$NON-NLS-1$
	private static final ITarget[] emptyTargets = new ITarget[0];
	public  static final String INTERFACE_IDENTITY = ManagedBuilderCorePlugin.PLUGIN_ID + ".ManagedBuildManager";	//$NON-NLS-1$
	public  static final String EXTENSION_POINT_ID = ManagedBuilderCorePlugin.PLUGIN_ID + ".buildDefinitions";		//$NON-NLS-1$
	public  static final String EXTENSION_POINT_ID_V2 = ManagedBuilderCorePlugin.PLUGIN_ID + ".ManagedBuildInfo";	//$NON-NLS-1$
	private static final String REVISION_ELEMENT_NAME = "managedBuildRevision";	//$NON-NLS-1$
	private static final String VERSION_ELEMENT_NAME = "fileVersion";	//$NON-NLS-1$
	private static final String MANIFEST_VERSION_ERROR ="ManagedBuildManager.error.manifest.version.error";	//$NON-NLS-1$
	private static final String PROJECT_VERSION_ERROR ="ManagedBuildManager.error.project.version.error";	//$NON-NLS-1$
	private static final String PROJECT_FILE_ERROR = "ManagedBuildManager.error.project.file.missing";	//$NON-NLS-1$
	private static final String MANIFEST_ERROR_HEADER = "ManagedBuildManager.error.manifest.header";	//$NON-NLS-1$
	public  static final String MANIFEST_ERROR_RESOLVING = "ManagedBuildManager.error.manifest.resolving";	//$NON-NLS-1$
	public  static final String MANIFEST_ERROR_DUPLICATE = "ManagedBuildManager.error.manifest.duplicate";	//$NON-NLS-1$
	public  static final String MANIFEST_ERROR_ICON = "ManagedBuildManager.error.manifest.icon";	//$NON-NLS-1$
	private static final String MANIFEST_ERROR_OPTION_CATEGORY = "ManagedBuildManager.error.manifest.option.category";	//$NON-NLS-1$
	private static final String MANIFEST_ERROR_OPTION_FILTER = "ManagedBuildManager.error.manifest.option.filter";	//$NON-NLS-1$
	private static final String MANIFEST_ERROR_OPTION_VALUEHANDLER = "ManagedBuildManager.error.manifest.option.valuehandler";	//$NON-NLS-1$
	private static final String MANIFEST_ERROR_READ_ONLY = "ManagedBuildManager.error.read_only";  //$NON-NLS-1$
	private static final String MANIFEST_ERROR_WRITE_FAILED = "ManagedBuildManager.error.write_failed";  //$NON-NLS-1$

	// Error ID's for OptionValidError()
	public static final int ERROR_CATEGORY = 0;
	public static final int ERROR_FILTER = 1;

	public static final String BUILD_TYPE_PROPERTY_ID = "org.eclipse.cdt.build.core.buildType";	//$NON-NLS-1$
	public static final String BUILD_ARTEFACT_TYPE_PROPERTY_ID = "org.eclipse.cdt.build.core.buildArtefactType";	//$NON-NLS-1$

	public static final String BUILD_TYPE_PROPERTY_DEBUG = "org.eclipse.cdt.build.core.buildType.debug";	//$NON-NLS-1$
	public static final String BUILD_TYPE_PROPERTY_RELEASE = "org.eclipse.cdt.build.core.buildType.release";	//$NON-NLS-1$
	public static final String BUILD_ARTEFACT_TYPE_PROPERTY_EXE = "org.eclipse.cdt.build.core.buildArtefactType.exe";	//$NON-NLS-1$
	public static final String BUILD_ARTEFACT_TYPE_PROPERTY_STATICLIB = "org.eclipse.cdt.build.core.buildArtefactType.staticLib";	//$NON-NLS-1$
	public static final String BUILD_ARTEFACT_TYPE_PROPERTY_SHAREDLIB = "org.eclipse.cdt.build.core.buildArtefactType.sharedLib";	//$NON-NLS-1$

	public static final String CFG_DATA_PROVIDER_ID = ManagedBuilderCorePlugin.PLUGIN_ID + ".configurationDataProvider"; //$NON-NLS-1$

	private static final String NEWLINE = System.getProperty("line.separator");	//$NON-NLS-1$

	public static final String INTERNAL_BUILDER_ID = "org.eclipse.cdt.build.core.internal.builder";	//$NON-NLS-1$

	private static final String os = Platform.getOS();
	private static final String arch = Platform.getOSArch();
	private static final String ALL = "all";  //$NON-NLS-1$

	// This is the version of the manifest and project files
	private static final Version buildInfoVersion = new Version(4, 0, 0);
	private static final Version version = new Version(4, 0, 0);
	private static boolean projectTypesLoaded = false;
	private static boolean projectTypesLoading = false;
	// Project types defined in the manifest files
	public static SortedMap<String, IProjectType> projectTypeMap;
	private static List<IProjectType> projectTypes;
	// Early configuration initialization extension elements
	private static List<IManagedConfigElement> startUpConfigElements;
	// Configurations defined in the manifest files
	private static Map<String, IConfiguration> extensionConfigurationMap;
	// Resource configurations defined in the manifest files
	private static Map<String, IResourceConfiguration> extensionResourceConfigurationMap;
	// Tool-chains defined in the manifest files
	private static SortedMap<String, ToolChain> extensionToolChainMap;
	// Tools defined in the manifest files
	private static SortedMap<String, Tool> extensionToolMap;
	// Target Platforms defined in the manifest files
	private static Map<String, ITargetPlatform> extensionTargetPlatformMap;
	// Builders defined in the manifest files
	private static SortedMap<String, Builder> extensionBuilderMap;
	// Options defined in the manifest files
	private static Map<String, IOption> extensionOptionMap;
	// Option Categories defined in the manifest files
	private static Map<String, IOptionCategory> extensionOptionCategoryMap;
	// Input types defined in the manifest files
	private static Map<String, IInputType> extensionInputTypeMap;
	// Output types defined in the manifest files
	private static Map<String, IOutputType> extensionOutputTypeMap;
	// Targets defined in the manifest files (CDT V2.0 object model)
	private static Map<String, ITarget> extensionTargetMap;


	// "Selected configuraton" elements defined in the manifest files.
	// These are configuration elements that map to objects in the internal
	// representation of the manifest files.  For example, ListOptionValues
	// and enumeratedOptionValues are NOT included.
	// Note that these "configuration elements" are not related to the
	// managed build system "configurations".
	// From the PDE Guide:
	//  A configuration element, with its attributes and children, directly
	//  reflects the content and structure of the extension section within the
	//  declaring plug-in's manifest (plugin.xml) file.
	// This map has a lifecycle corresponding to the build definitions extension loading.
	private static Map<IBuildObject, IManagedConfigElement> configElementMap;

//	private static List sortedToolChains;
//	private static Map builtTypeToToolChainListMap;
	// Listeners interested in build model changes
	private static Map<IResource, List<IScannerInfoChangeListener>> buildModelListeners;
	// Random number for derived object model elements
	private static Random randomNumber;
	// Environment Build Paths Change Listener
	private static IEnvironmentBuildPathsChangeListener fEnvironmentBuildPathsChangeListener;

	private static HashMap<MatchKey<ToolChain>, List<ToolChain>> fSortedToolChains;
	private static HashMap<MatchKey<Tool>, List<Tool>> fSortedTools;
	private static HashMap<MatchKey<Builder>, List<Builder>> fSortedBuilders;

	private static Map<IProject, IManagedBuildInfo> fInfoMap = new HashMap<IProject, IManagedBuildInfo>();

	private static ISorter fToolChainSorter = new ISorter(){
		@Override
		public void sort() {
			resortToolChains();
		}
	};
	private static ISorter fToolSorter = new ISorter(){
		@Override
		public void sort() {
			resortTools();
		}
	};
	private static ISorter fBuilderSorter = new ISorter(){
		@Override
		public void sort() {
			resortBuilders();
		}
	};

	private static interface ISorter {
		void sort();
	}


	static {
		getEnvironmentVariableProvider().subscribe(
				fEnvironmentBuildPathsChangeListener = new IEnvironmentBuildPathsChangeListener(){
					@Override
					public void buildPathsChanged(IConfiguration configuration, int buildPathType){
//						if(buildPathType == IEnvVarBuildPath.BUILDPATH_INCLUDE){
//							initializePathEntries(configuration,null);
//							notifyListeners(configuration,null);
//						}
					}
				});
	}
	/**
	 * @return the next random number as a positive integer.
	 */
	public static int getRandomNumber() {
		if (randomNumber == null) {
			// Set the random number seed
			randomNumber = new Random();
			randomNumber.setSeed(System.currentTimeMillis());
		}
		int i = randomNumber.nextInt();
		if (i < 0) {
			i *= -1;
		}
		return i;
	}

	/**
	 * @return the list of project types that are defined by this project,
	 * projects referenced by this project, and by the extensions.
	 */
	public static IProjectType[] getDefinedProjectTypes() {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Get the project types for this project and all referenced projects
		List<IProjectType> definedTypes = null;
		// To Do

		// Create the array and copy the elements over
		int size = projectTypes != null ? projectTypes.size() : 0;
		size += definedTypes != null ? definedTypes.size() : 0;

		IProjectType[] types = new IProjectType[size];

		if (size > 0) {
			int n = 0;
			for (int i = 0; i < projectTypes.size(); i++)
				types[n++] = projectTypes.get(i);

			if (definedTypes != null)
				for (int i = 0; i < definedTypes.size(); i++)
					types[n++] = definedTypes.get(i);
		}

		return types;
	}

	/**
	 * @param id - id of the project type
	 * @return the project type with the passed in ID
	 */
	public static IProjectType getProjectType(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionProjectTypeMap().get(id);
	}

	public static Version getVersion(){
		return version;
	}

	/**
	 * Safe accessor for the map of IDs to ProjectTypes
	 */
	public static SortedMap<String, IProjectType> getExtensionProjectTypeMap() {
		try {
			loadExtensions();
		} catch (BuildException e) {
		}
		if (projectTypeMap == null) {
			projectTypeMap = new TreeMap<String, IProjectType>();
		}
		return projectTypeMap;
	}

	/**
	 * Safe accessor for the map of IDs to Configurations
	 */
	protected static Map<String, IConfiguration> getExtensionConfigurationMap() {
		if (extensionConfigurationMap == null) {
			extensionConfigurationMap = new HashMap<String, IConfiguration>();
		}
		return extensionConfigurationMap;
	}

	/**
	 * Safe accessor for the map of IDs to Resource Configurations
	 */
	protected static Map<String, IResourceConfiguration> getExtensionResourceConfigurationMap() {
		if (extensionResourceConfigurationMap == null) {
			extensionResourceConfigurationMap = new HashMap<String, IResourceConfiguration>();
		}
		return extensionResourceConfigurationMap;
	}

	/**
	 * Safe internal accessor for the map of IDs to ToolChains
	 */
	private static SortedMap<String, ToolChain> getExtensionToolChainMapInternal() {
		try {
			loadExtensions();
		} catch (BuildException e) {
		}

		if (extensionToolChainMap == null) {
			extensionToolChainMap =  new TreeMap<String, ToolChain>();
		}
		return extensionToolChainMap;
	}

	/**
	 * Safe accessor for the map of IDs to ToolChains
	 */
	public static SortedMap<String, ? extends IToolChain> getExtensionToolChainMap() {
		return getExtensionToolChainMapInternal();
	}

	public static IToolChain[] getExtensionToolChains() {
		return getExtensionToolChainMapInternal().values().toArray(new ToolChain[extensionToolChainMap.size()]);
	}

	/**
	 * Safe internal accessor for the map of IDs to Tools
	 */
	private static SortedMap<String, Tool> getExtensionToolMapInternal() {
		try {
			loadExtensions();
		} catch (BuildException e) {
		}
		if (extensionToolMap == null) {
			extensionToolMap = new TreeMap<String, Tool>();
		}
		return extensionToolMap;
	}

	/**
	 * Safe accessor for the map of IDs to Tools
	 */
	public static SortedMap<String, ? extends ITool> getExtensionToolMap() {
		return getExtensionToolMapInternal();
	}

	public static ITool[] getExtensionTools() {
		return getExtensionToolMapInternal().values().toArray(new Tool[extensionToolMap.size()]);
	}

	/**
	 * Safe accessor for the map of IDs to TargetPlatforms
	 */
	protected static Map<String, ITargetPlatform> getExtensionTargetPlatformMap() {
		if (extensionTargetPlatformMap == null) {
			extensionTargetPlatformMap = new HashMap<String, ITargetPlatform>();
		}
		return extensionTargetPlatformMap;
	}

	/**
	 * Safe internal accessor for the map of IDs to Builders
	 */
	private static SortedMap<String, Builder> getExtensionBuilderMapInternal() {
		try {
			loadExtensions();
		} catch (BuildException e) {
		}
		if (extensionBuilderMap == null) {
			extensionBuilderMap = new TreeMap<String, Builder>();
		}
		return extensionBuilderMap;
	}

	/**
	 * Safe accessor for the map of IDs to Builders
	 */
	public static SortedMap<String, ? extends IBuilder> getExtensionBuilderMap() {
		return getExtensionBuilderMapInternal();
	}

	public static IBuilder[] getExtensionBuilders() {
		return getExtensionBuilderMapInternal().values().toArray(new Builder[extensionBuilderMap.size()]);
	}

	/**
	 * Safe accessor for the map of IDs to Options
	 */
	protected static Map<String, IOption> getExtensionOptionMap() {
		if (extensionOptionMap == null) {
			extensionOptionMap = new HashMap<String, IOption>();
		}
		return extensionOptionMap;
	}

	/**
	 * Safe accessor for the map of IDs to Option Categories
	 */
	protected static Map<String, IOptionCategory> getExtensionOptionCategoryMap() {
		if (extensionOptionCategoryMap == null) {
			extensionOptionCategoryMap = new HashMap<String, IOptionCategory>();
		}
		return extensionOptionCategoryMap;
	}

	/**
	 * Safe accessor for the map of IDs to InputTypes
	 */
	protected static Map<String, IInputType> getExtensionInputTypeMap() {
		if (extensionInputTypeMap == null) {
			extensionInputTypeMap = new HashMap<String, IInputType>();
		}
		return extensionInputTypeMap;
	}

	/**
	 * Safe accessor for the map of IDs to OutputTypes
	 */
	protected static Map<String, IOutputType> getExtensionOutputTypeMap() {
		if (extensionOutputTypeMap == null) {
			extensionOutputTypeMap = new HashMap<String, IOutputType>();
		}
		return extensionOutputTypeMap;
	}

	/**
	 * Safe accessor for the map of IDs to Targets (CDT V2.0 object model)
	 */
	protected static Map<String, ITarget> getExtensionTargetMap() {
		if (extensionTargetMap == null) {
			extensionTargetMap = new HashMap<String, ITarget>();
		}
		return extensionTargetMap;
	}

	/**
	 * @return the targets owned by this resource.  If none are owned,
	 * an empty array is returned.
	 */
	public static ITarget[] getTargets(IResource resource) {
		IManagedBuildInfo buildInfo = getBuildInfo(resource);

		if (buildInfo != null) {
			List<ITarget> targets = buildInfo.getTargets();
			return targets.toArray(new ITarget[targets.size()]);
		}
		return emptyTargets;
	}

	/**
	 * @return the project type from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IProjectType getExtensionProjectType(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionProjectTypeMap().get(id);
	}

	/**
	 * @return the base extension configuration from the manifest (plugin.xml)
	 *  or {@code null} if not found.
	 *
	 * @since 8.0
	 */
	public static IConfiguration getExtensionConfiguration(IConfiguration cfg) {
		for(;cfg != null && !cfg.isExtensionElement(); cfg = cfg.getParent()) {
			// empty loop to find base configuration
		}
		return cfg;
	}

	/**
	 * @return the configuration from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IConfiguration getExtensionConfiguration(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionConfigurationMap().get(id);
	}

	public static IConfiguration[] getExtensionConfigurations() {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionConfigurationMap().values().toArray(new Configuration[getExtensionConfigurationMap().size()]);
	}

	/**
	 * @return the resource configuration from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IResourceConfiguration getExtensionResourceConfiguration(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionResourceConfigurationMap().get(id);
	}

	/**
	 * @return the tool-chain from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IToolChain getExtensionToolChain(String id) {
		return getExtensionToolChainMapInternal().get(id);
	}

	/**
	 * @return the tool from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static ITool getExtensionTool(String id) {
		return getExtensionToolMapInternal().get(id);
	}

	/**
	 * @return the target platform from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static ITargetPlatform getExtensionTargetPlatform(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionTargetPlatformMap().get(id);
	}

	/**
	 * @return the builder from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IBuilder getExtensionBuilder(String id) {
		return getExtensionBuilderMapInternal().get(id);
	}

	public static IBuilder getExtensionBuilder(IBuilder builder) {
		for(;builder != null && !builder.isExtensionElement(); builder = builder.getSuperClass()) {
			// empty loop to find parent builder
		}
		return builder;
	}


	/**
	 * @return the option from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IOption getExtensionOption(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionOptionMap().get(id);
	}

	/**
	 * @return the InputType from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IInputType getExtensionInputType(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionInputTypeMap().get(id);
	}

	/**
	 * @return the OutputType from the manifest with the ID specified in the argument
	 *  or {@code null}.
	 */
	public static IOutputType getExtensionOutputType(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionOutputTypeMap().get(id);
	}

	/**
	 * @return the target from the manifest with the ID specified in the argument
	 *  or {@code null} - CDT V2.0 object model.
	 */
	public static ITarget getExtensionTarget(String id) {
		try {
			// Make sure the extensions are loaded
			loadExtensions();
		} catch (BuildException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return getExtensionTargetMap().get(id);
	}

	/**
	 * @param resource to find the target
	 * @param id - ID of the target
	 *
	 * @return the result of a best-effort search to find a target with the
	 * specified ID, or {@code null} if one is not found.
	 */
	public static ITarget getTarget(IResource resource, String id) {
		ITarget target = null;
		// Check if the target is spec'd in the build info for the resource
		if (resource != null) {
			IManagedBuildInfo buildInfo = getBuildInfo(resource);
			if (buildInfo != null)
				target = buildInfo.getTarget(id);
		}
		// OK, check the extension map
		if (target == null) {
			target = getExtensionTargetMap().get(id);
		}
		return target;
	}

	/**
	 * Sets the default configuration for the project. Note that this will also
	 * update the default target if needed.
	 */
	public static void setDefaultConfiguration(IProject project, IConfiguration newDefault) {
		if (project == null || newDefault == null) {
			return;
		}
		// Set the default in build information for the project
		IManagedBuildInfo info = getBuildInfo(project);
		if (info != null) {
			info.setDefaultConfiguration(newDefault);
		}
	}

	/**
	 * Sets the currently selected configuration.  This is used while the project
	 * property pages are displayed
	 */
	public static void setSelectedConfiguration(IProject project, IConfiguration config) {
		if (project == null) {
			return;
		}
		// Set the default in build information for the project
		IManagedBuildInfo info = getBuildInfo(project);
		if (info != null) {
			info.setSelectedConfiguration(config);
		}
	}

	public static IManagedBuilderMakefileGenerator getBuildfileGenerator(IConfiguration config) {
		IToolChain toolChain = config.getToolChain();
		if(toolChain != null){
			IBuilder builder = toolChain.getBuilder();
			if(builder != null)
				return builder.getBuildFileGenerator();
		}
		// If no generator is defined, return the default GNU generator
		return new GnuMakefileGenerator();
	}

	/**
	 * load tool provider defined or default (if not found) command line generator special for selected tool
	 * @param toolId - id selected tool ID
	 */
	public static IManagedCommandLineGenerator getCommandLineGenerator(IConfiguration config, String toolId) {
		ITool tool = config.getTool(toolId);
		if (tool != null) {
			return tool.getCommandLineGenerator();
		}
		return ManagedCommandLineGenerator.getCommandLineGenerator();
	}

    /**
     * Targets may have a scanner config discovery profile defined that knows
     * how to discover built-in compiler defines and includes search paths.
     * Find the profile for the target specified.
     *
     * @return scanner configuration discovery profile id
     */
    public static String getScannerInfoProfileId(IConfiguration config) {
        IToolChain toolChain = config.getToolChain();
        return toolChain.getScannerConfigDiscoveryProfileId();
    }

	/**
	 * Gets the currently selected target.  This is used while the project
	 * property pages are displayed.
	 *
	 * @return target configuration.
	 */
	public static IConfiguration getSelectedConfiguration(IProject project) {
		if (project == null) {
			return null;
		}
		// Set the default in build information for the project
		IManagedBuildInfo info = getBuildInfo(project);
		if (info != null) {
			return info.getSelectedConfiguration();
		}
		return null;
	}

	/* (non-Javadoc)
	 *
	 * @param config
	 * @param option
	 */
	/*
	private static void notifyListeners(IConfiguration config, IOption option) {
		// Continue if change is something that effect the scanner
		try {
			//an option can be null in the case of calling this method from the environment
			//build path change listener
			if (config.isTemporary() ||
					(option != null && option.getValueType() != IOption.INCLUDE_PATH
							&& option.getValueType() != IOption.PREPROCESSOR_SYMBOLS
							&& option.getValueType() != IOption.INCLUDE_FILES
							&& option.getValueType() != IOption.LIBRARY_PATHS
							&& option.getValueType() != IOption.LIBRARY_FILES
							&& option.getValueType() != IOption.MACRO_FILES
							&& option.getValueType() != IOption.UNDEF_INCLUDE_PATH
							&& option.getValueType() != IOption.UNDEF_PREPROCESSOR_SYMBOLS
							&& option.getValueType() != IOption.UNDEF_INCLUDE_FILES
							&& option.getValueType() != IOption.UNDEF_LIBRARY_PATHS
							&& option.getValueType() != IOption.UNDEF_LIBRARY_FILES
							&& option.getValueType() != IOption.UNDEF_MACRO_FILES
							)) {
				return;
			}
		} catch (BuildException e) {return;}

		// Figure out if there is a listener for this change
		IResource resource = config.getOwner();
		List listeners = (List) getBuildModelListeners().get(resource);
		if (listeners == null) {
			return;
		}
		ListIterator iter = listeners.listIterator();
		while (iter.hasNext()) {
			((IScannerInfoChangeListener)iter.next()).changeNotification(resource, (IScannerInfo)getBuildInfo(resource));
		}
	}
*/
	public static void initializePathEntries(IConfiguration config, IOption option){
		try{
			if(config.isTemporary() ||
					(option != null
					&& option.getValueType() != IOption.INCLUDE_PATH
					&& option.getValueType() != IOption.PREPROCESSOR_SYMBOLS
					&& option.getValueType() != IOption.INCLUDE_FILES
					&& option.getValueType() != IOption.LIBRARY_PATHS
					&& option.getValueType() != IOption.LIBRARY_FILES
					&& option.getValueType() != IOption.MACRO_FILES
					&& option.getValueType() != IOption.UNDEF_INCLUDE_PATH
					&& option.getValueType() != IOption.UNDEF_PREPROCESSOR_SYMBOLS
					&& option.getValueType() != IOption.UNDEF_INCLUDE_FILES
					&& option.getValueType() != IOption.UNDEF_LIBRARY_PATHS
					&& option.getValueType() != IOption.UNDEF_LIBRARY_FILES
					&& option.getValueType() != IOption.UNDEF_MACRO_FILES
					))
				return;
		} catch (BuildException e){
			return;
		}

		try {
			updateCoreSettings(config);
		} catch (CoreException e) {
		}

	}

	public static void initializePathEntries(IResourceConfiguration resConfig, IOption option){
		IConfiguration cfg = resConfig.getParent();
		if(cfg != null)
			initializePathEntries(cfg,option);
	}

	private static void notifyListeners(IResourceInfo resConfig, IOption option) {
		// Continue if change is something that effect the scanreser
		try {
			if (resConfig.getParent().isTemporary() ||
					(option != null && option.getValueType() != IOption.INCLUDE_PATH
				&& option.getValueType() != IOption.PREPROCESSOR_SYMBOLS
				&& option.getValueType() != IOption.INCLUDE_FILES
				&& option.getValueType() != IOption.LIBRARY_PATHS
				&& option.getValueType() != IOption.LIBRARY_FILES
				&& option.getValueType() != IOption.MACRO_FILES
				&& option.getValueType() != IOption.UNDEF_INCLUDE_PATH
				&& option.getValueType() != IOption.UNDEF_PREPROCESSOR_SYMBOLS
				&& option.getValueType() != IOption.UNDEF_INCLUDE_FILES
				&& option.getValueType() != IOption.UNDEF_LIBRARY_PATHS
				&& option.getValueType() != IOption.UNDEF_LIBRARY_FILES
				&& option.getValueType() != IOption.UNDEF_MACRO_FILES
					)) {
				return;
			}
		} catch (BuildException e) {return;}

		// Figure out if there is a listener for this change
		IResource resource = resConfig.getParent().getOwner();
		List<IScannerInfoChangeListener> listeners = getBuildModelListeners().get(resource);
		if (listeners == null) {
			return;
		}
		ListIterator<IScannerInfoChangeListener> iter = listeners.listIterator();
		while (iter.hasNext()) {
			iter.next().changeNotification(resource, (IScannerInfo)getBuildInfo(resource));
		}
	}

	/**
	 * Adds the version of the managed build system to the project
	 * specified in the argument.
	 *
	 * @param newProject the project to version
	 */
	public static void setNewProjectVersion(IProject newProject) {
		// Get the build info for the argument
		ManagedBuildInfo info = findBuildInfo(newProject, true);
		if(info != null)
			info.setVersion(buildInfoVersion.toString());
	}

	/**
	 * Set the boolean value for an option for a given config.
	 *
	 * @param config The configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The boolean that the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IConfiguration config, IHoldsOptions holder, IOption option, boolean value) {
		IOption retOpt;
		try {
			// Request a value change and set dirty if real change results
			retOpt = config.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					config,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
//			initializePathEntries(config,retOpt);
//			notifyListeners(config, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}

	/**
	 * Set the boolean value for an option for a given config.
	 *
	 * @param resConfig The resource configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The boolean that the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IResourceInfo resConfig, IHoldsOptions holder, IOption option, boolean value) {
		IOption retOpt;
		try {
			// Request a value change and set dirty if real change results
			retOpt = resConfig.setOption(holder, option, value);
			if (retOpt != null && retOpt.getValueHandler().handleValue(
					resConfig,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
	//		initializePathEntries(resConfig,retOpt);
			notifyListeners(resConfig, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}
	/**
	 * Set the string value for an option for a given config.
	 *
	 * @param config The configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The value that the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IConfiguration config, IHoldsOptions holder, IOption option, String value) {
		IOption retOpt;
		try {
			retOpt = config.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					config,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
//			initializePathEntries(config,retOpt);
//			notifyListeners(config, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}

	/**
	 * Set the string value for an option for a given  resource config.
	 *
	 * @param resConfig The resource configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The value that the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IResourceInfo resConfig, IHoldsOptions holder, IOption option, String value) {
		IOption retOpt;
		try {
			retOpt = resConfig.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					resConfig,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
	//		initializePathEntries(resConfig,retOpt);
			notifyListeners(resConfig, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}
/**
	 * Set the string array value for an option for a given config.
	 *
	 * @param config The configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The values the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IConfiguration config, IHoldsOptions holder, IOption option, String[] value) {
		IOption retOpt;
		try {
			retOpt = config.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					config,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
//			initializePathEntries(config,retOpt);
//			notifyListeners(config, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}

	/**
	 * Set the string array value for an option for a given resource config.
	 *
	 * @param resConfig The resource configuration the option belongs to.
	 * @param holder The holder/parent of the option.
	 * @param option The option to set the value for.
	 * @param value The values the option should contain after the change.
	 *
	 * @return The modified option.  This can be the same option or a newly created option.
	 *
	 * @since 3.0 - The type and name of the <code>ITool tool</code> parameter
	 *        has changed to <code>IHoldsOptions holder</code>. Client code
	 *        assuming <code>ITool</code> as type, will continue to work unchanged.
	 */
	public static IOption setOption(IResourceInfo resConfig, IHoldsOptions holder, IOption option, String[] value) {
		IOption retOpt;
		try {
			retOpt = resConfig.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					resConfig,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
//			initializePathEntries(resConfig,retOpt);
			notifyListeners(resConfig, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}

	public static IOption setOption(IResourceInfo resConfig, IHoldsOptions holder, IOption option, OptionStringValue[] value) {
		IOption retOpt;
		try {
			retOpt = resConfig.setOption(holder, option, value);
			if (retOpt.getValueHandler().handleValue(
					resConfig,
					holder,
					retOpt,
					retOpt.getValueHandlerExtraArgument(),
					IManagedOptionValueHandler.EVENT_APPLY)) {
				// TODO : Event is handled successfully and returned true.
				// May need to do something here say log a message.
			} else {
				// Event handling Failed.
			}
//			initializePathEntries(resConfig,retOpt);
			notifyListeners(resConfig, retOpt);
		} catch (BuildException e) {
			return null;
		}
		return retOpt;
	}

	public static void setToolCommand(IConfiguration config, ITool tool, String command) {
		// The tool may be a reference.
		if (tool instanceof IToolReference) {
			// If so, just set the command in the reference
			((IToolReference)tool).setToolCommand(command);
		} else {
			config.setToolCommand(tool, command);
		}
	}

	public static void setToolCommand(IResourceConfiguration resConfig, ITool tool, String command) {
		// The tool may be a reference.
		if (tool instanceof IToolReference) {
			// If so, just set the command in the reference
			((IToolReference)tool).setToolCommand(command);
		} else {
			resConfig.setToolCommand(tool, command);
		}
	}

	public static boolean saveBuildInfoLegacy(IProject project, boolean force) {
		// Create document
		Exception err = null;
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document doc = builder.newDocument();

			// Get the build information for the project
			ManagedBuildInfo buildInfo = (ManagedBuildInfo) getBuildInfo(project);

			// Save the build info
			if (buildInfo != null &&
					!buildInfo.isReadOnly() &&
					buildInfo.isValid() &&
					(force == true || buildInfo.isDirty())) {
				// For post-2.0 projects, there will be a version
				String projectVersion = buildInfo.getVersion();
				if (projectVersion != null) {
					ProcessingInstruction instruction = doc.createProcessingInstruction(VERSION_ELEMENT_NAME, projectVersion);
					doc.appendChild(instruction);
				}
				Element rootElement = doc.createElement(ROOT_NODE_NAME);
				doc.appendChild(rootElement);
				buildInfo.serializeLegacy(doc, rootElement);

				// Transform the document to something we can save in a file
				ByteArrayOutputStream stream = new ByteArrayOutputStream();
				Transformer transformer = TransformerFactory.newInstance().newTransformer();
				transformer.setOutputProperty(OutputKeys.METHOD, "xml");	//$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.INDENT, "yes");	//$NON-NLS-1$
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(stream);
				transformer.transform(source, result);

				// Save the document
				IFile projectFile = project.getFile(SETTINGS_FILE_NAME);
				String utfString = stream.toString("UTF-8");	//$NON-NLS-1$

				if (projectFile.exists()) {
					if (projectFile.isReadOnly()) {
						// If we are not running headless, and there is a UI Window around, grab it
						// and the associated shell
						IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
						if (window == null) {
							IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
							window = windows[0];
						}
						Shell shell = null;
						if (window != null) {
							shell = window.getShell();
						}
	                    // Inform Eclipse that we are intending to modify this file
						// This will provide the user the opportunity, via UI prompts, to fetch the file from source code control
						// reset a read-only file protection to write etc.
						// If there is no shell, i.e. shell is null, then there will be no user UI interaction
						IStatus status = projectFile.getWorkspace().validateEdit(new IFile[]{projectFile}, shell);
						// If the file is still read-only, then we should not attempt the write, since it will
						// just fail - just throw an exception, to be caught below, and inform the user
						// For other non-successful status, we take our chances, attempt the write, and pass
						// along any exception thrown
						if (!status.isOK()) {
							if (status.getCode() == IResourceStatus.READ_ONLY_LOCAL) {
								stream.close();
								throw new IOException(ManagedMakeMessages.getFormattedString(MANIFEST_ERROR_READ_ONLY, projectFile.getFullPath().toString()));
							}
						}
					}
					projectFile.setContents(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor());	//$NON-NLS-1$
				} else {
					projectFile.create(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor());	//$NON-NLS-1$
				}

				// Close the streams
				stream.close();
			}
		} catch (ParserConfigurationException e) {
			err = e;
		} catch (FactoryConfigurationError e) {
			err = e.getException();
		} catch (TransformerConfigurationException e) {
			err = e;
		} catch (TransformerFactoryConfigurationError e) {
			err = e.getException();
		} catch (TransformerException e) {
			err = e;
		} catch (IOException e) {
			// The save failed
			err = e;
    	} catch (CoreException e) {
	    	// Save to IFile failed
		    err = e;
	    }

		if (err != null) {
			// Put out an error message indicating that the attempted write to the .cdtbuild project file failed
			IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
			if (window == null) {
				IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
				window = windows[0];
			}

			final Shell shell = window.getShell();
			if (shell != null) {
				final String exceptionMsg = err.getMessage();
				shell.getDisplay().syncExec( new Runnable() {
					@Override
					public void run() {
						MessageDialog.openError(shell,
								ManagedMakeMessages.getResourceString("ManagedBuildManager.error.write_failed_title"),	//$NON-NLS-1$
								ManagedMakeMessages.getFormattedString(MANIFEST_ERROR_WRITE_FAILED,
										exceptionMsg));
					}
			    } );
			}
		}
		// If we return an honest status when the operation fails, there are instances when the UI behavior
		// is not very good
		// Specifically, if "OK" is clicked by the user from the property page UI, and the return status
		// from this routine is false, the property page UI will not be closed (note: this is Eclispe code) and
		// the OK button will simply be grayed out
		// At this point, the only way out is to click "Cancel" to get the UI to go away; note however that any
		// property page changes will be sticky, in the UI, which is nonintuitive and confusing
		// Therefore, just always return success, i.e. true, from this routine
		return true;
	}

	public static boolean saveBuildInfo(final IProject project, final boolean force) {
		try {
			return updateBuildInfo(project, force);
		} catch (CoreException e) {
			Throwable cause = e.getStatus().getException();
			if(cause instanceof IllegalArgumentException){
				//can not acquire the root rule
				Job j = new Job("save build info job"){ //$NON-NLS-1$

					@Override
					protected IStatus run(IProgressMonitor monitor) {
						try {
							updateBuildInfo(project, force);
						} catch (CoreException e) {
							return e.getStatus();
						}
						return Status.OK_STATUS;
					}

				};
				j.setRule(ResourcesPlugin.getWorkspace().getRoot());
				j.setSystem(true);
				j.schedule();
				return true;
			}
			ManagedBuilderCorePlugin.log(e);
			return false;
		}
	}

	/**
	 * Saves the build information associated with a project and all resources
	 * in the project to the build info file.
	 */
	private static boolean updateBuildInfo(IProject project, boolean force) throws CoreException {
		IManagedBuildInfo info = getBuildInfo(project, false);
		if(info == null)
			return true;

		ICProjectDescription projDes = CoreModel.getDefault().getProjectDescription(project);
		projDes = BuildSettingsUtil.synchBuildInfo(info, projDes, force);

//		try {
			BuildSettingsUtil.checkApplyDescription(project, projDes);
//		} catch (CoreException e) {
//			return false;
//		}
		return true;
		/*
		// Create document
		Exception err = null;
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document doc = builder.newDocument();

			// Get the build information for the project
			ManagedBuildInfo buildInfo = (ManagedBuildInfo) getBuildInfo(project);

			// Save the build info
			if (buildInfo != null &&
					!buildInfo.isReadOnly() &&
					buildInfo.isValid() &&
					(force == true || buildInfo.isDirty())) {
				// For post-2.0 projects, there will be a version
				String projectVersion = buildInfo.getVersion();
				if (projectVersion != null) {
					ProcessingInstruction instruction = doc.createProcessingInstruction(VERSION_ELEMENT_NAME, projectVersion);
					doc.appendChild(instruction);
				}
				Element rootElement = doc.createElement(ROOT_NODE_NAME);
				doc.appendChild(rootElement);
				buildInfo.serialize(doc, rootElement);

				// Transform the document to something we can save in a file
				ByteArrayOutputStream stream = new ByteArrayOutputStream();
				Transformer transformer = TransformerFactory.newInstance().newTransformer();
				transformer.setOutputProperty(OutputKeys.METHOD, "xml");	//$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.INDENT, "yes");	//$NON-NLS-1$
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(stream);
				transformer.transform(source, result);

				// Save the document
				IFile projectFile = project.getFile(SETTINGS_FILE_NAME);
				String utfString = stream.toString("UTF-8");	//$NON-NLS-1$

				if (projectFile.exists()) {
					if (projectFile.isReadOnly()) {
						// If we are not running headless, and there is a UI Window around, grab it
						// and the associated shell
						IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
						if (window == null) {
							IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
							window = windows[0];
						}
						Shell shell = null;
						if (window != null) {
							shell = window.getShell();
						}
	                    // Inform Eclipse that we are intending to modify this file
						// This will provide the user the opportunity, via UI prompts, to fetch the file from source code control
						// reset a read-only file protection to write etc.
						// If there is no shell, i.e. shell is null, then there will be no user UI interaction
						IStatus status = projectFile.getWorkspace().validateEdit(new IFile[]{projectFile}, shell);
						// If the file is still read-only, then we should not attempt the write, since it will
						// just fail - just throw an exception, to be caught below, and inform the user
						// For other non-successful status, we take our chances, attempt the write, and pass
						// along any exception thrown
						if (!status.isOK()) {
						    if (status.getCode() == IResourceStatus.READ_ONLY_LOCAL) {
						    	stream.close();
		    	                throw new IOException(ManagedMakeMessages.getFormattedString(MANIFEST_ERROR_READ_ONLY, projectFile.getFullPath().toString())); //$NON-NLS-1$
						    }
						}
					}
					projectFile.setContents(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor());	//$NON-NLS-1$
				} else {
					projectFile.create(new ByteArrayInputStream(utfString.getBytes("UTF-8")), IResource.FORCE, new NullProgressMonitor());	//$NON-NLS-1$
				}

				// Close the streams
				stream.close();
			}
		} catch (ParserConfigurationException e) {
			err = e;
		} catch (FactoryConfigurationError e) {
			err = e.getException();
		} catch (TransformerConfigurationException e) {
			err = e;
		} catch (TransformerFactoryConfigurationError e) {
			err = e.getException();
		} catch (TransformerException e) {
			err = e;
		} catch (IOException e) {
			// The save failed
			err = e;
    	} catch (CoreException e) {
	    	// Save to IFile failed
		    err = e;
	    }

		if (err != null) {
			// Put out an error message indicating that the attempted write to the .cdtbuild project file failed
			IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
			if (window == null) {
				IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
				window = windows[0];
			}

			final Shell shell = window.getShell();
			if (shell != null) {
				final String exceptionMsg = err.getMessage();
				shell.getDisplay().syncExec( new Runnable() {
					public void run() {
						MessageDialog.openError(shell,
								ManagedMakeMessages.getResourceString("ManagedBuildManager.error.write_failed_title"),	//$NON-NLS-1$
								ManagedMakeMessages.getFormattedString(MANIFEST_ERROR_WRITE_FAILED,		//$NON-NLS-1$
										exceptionMsg));
					}
			    } );
			}
		}
		// If we return an honest status when the operation fails, there are instances when the UI behavior
		// is not very good
		// Specifically, if "OK" is clicked by the user from the property page UI, and the return status
		// from this routine is false, the property page UI will not be closed (note: this is Eclispe code) and
		// the OK button will simply be grayed out
		// At this point, the only way out is to click "Cancel" to get the UI to go away; note however that any
		// property page changes will be sticky, in the UI, which is nonintuitive and confusing
		// Therefore, just always return success, i.e. true, from this routine
		return true;
		*/
	}

	public static void updateCoreSettings(IProject project) throws CoreException {
		updateBuildInfo(project, true);
	}

	public static void updateCoreSettings(IConfiguration cfg) throws CoreException{
		IProject project = cfg.getOwner().getProject();
		ICProjectDescription projDes = CoreModel.getDefault().getProjectDescription(project);
		if(projDes != null){
			if(BuildSettingsUtil.applyConfiguration(cfg, projDes, true)){
				BuildSettingsUtil.checkApplyDescription(project, projDes);
			}
		}
	}
	public static void updateCoreSettings(IProject project, IConfiguration[] cfgs) throws CoreException{
		updateCoreSettings(project, cfgs, false);
	}

	public static void updateCoreSettings(IProject project, IConfiguration[] cfgs, boolean avoidSerialization) throws CoreException{
		if(cfgs == null){
			IManagedBuildInfo info = getBuildInfo(project);
			if(info != null && info.isValid() && info.getManagedProject() != null)
				cfgs = info.getManagedProject().getConfigurations();
		}

		if(cfgs == null || cfgs.length == 0)
			return;

		ICProjectDescription projDes = CoreModel.getDefault().getProjectDescription(project);
		boolean updated = false;
		if(projDes != null){
			for (IConfiguration cfg : cfgs) {
				if(BuildSettingsUtil.applyConfiguration(cfg, projDes, true)){
					updated = true;
				}
			}
			if(updated){
				BuildSettingsUtil.checkApplyDescription(project, projDes, avoidSerialization);
			}
		}
	}

	public static void removeBuildInfo(IResource resource) {
		/*
		IManagedBuildInfo info = findBuildInfo(resource, false);
		if(info != null){
			IConfiguration[] configs = info.getManagedProject().getConfigurations();
			//  Send an event to each configuration and if they exist, its resource configurations
			for (int i=0; i < configs.length; i++) {
				ManagedBuildManager.performValueHandlerEvent(configs[i], IManagedOptionValueHandler.EVENT_CLOSE);
			}

			info.setValid(false);

			try {
				resource.setSessionProperty(buildInfoProperty, null);
			} catch (CoreException e) {
			}
		}
		*/
	}

	/**
	 * Resets the build information for the project and configuration specified in the arguments.
	 * The build information will contain the settings defined in the plugin manifest.
	 */
	public static void resetConfiguration(IProject project, IConfiguration configuration) {
		// reset the configuration
		if (configuration instanceof MultiConfiguration) {
			IConfiguration[] cfs = (IConfiguration[])((MultiConfiguration)configuration).getItems();
			for (IConfiguration c : cfs) {
				((Configuration)c).reset();
				performValueHandlerEvent(c,
						IManagedOptionValueHandler.EVENT_SETDEFAULT, false);
			}
		} else {
			((Configuration)configuration).reset();
			performValueHandlerEvent(configuration,
					IManagedOptionValueHandler.EVENT_SETDEFAULT, false);
		}
	}

	public static void resetResourceConfiguration(IProject project, IResourceConfiguration resConfig) {
		// reset the configuration
		((ResourceConfiguration) resConfig).reset();

		performValueHandlerEvent(resConfig,
				IManagedOptionValueHandler.EVENT_SETDEFAULT);

	}

	public static void resetOptionSettings(IResourceInfo rcInfo){
		if(rcInfo instanceof IFileInfo){
			IConfiguration c = rcInfo.getParent();
			Configuration cfg = null;
			IProject project = null;
			if (c instanceof Configuration)
				cfg = (Configuration)c;
			else if (c instanceof MultiConfiguration) {
				MultiConfiguration mc = (MultiConfiguration)c;
				IConfiguration[] cfs = (IConfiguration[])mc.getItems();
				cfg = (Configuration)cfs[0];
			}
			if(!(cfg==null || cfg.isExtensionElement() || cfg.isPreference()))
				project = cfg.getOwner().getProject();

			if (rcInfo instanceof MultiResourceInfo) {
				for (IResourceInfo ri : (IResourceInfo[])((MultiResourceInfo)rcInfo).getItems())
					resetResourceConfiguration(project, (IFileInfo)ri);
			} else
				resetResourceConfiguration(project, (IFileInfo)rcInfo);
		} else {
			if (rcInfo instanceof MultiFolderInfo) {
				for (IFolderInfo fi : (IFolderInfo[])((MultiFolderInfo)rcInfo).getItems())
					((FolderInfo)fi).resetOptionSettings();
			} else {
				FolderInfo fo = (FolderInfo)rcInfo;
				fo.resetOptionSettings();
			}
		}
	}
	/**
	 * Adds a ProjectType that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionProjectType(ProjectType projectType) {
		if (projectTypes == null) {
			projectTypes = new ArrayList<IProjectType>();
		}

		projectTypes.add(projectType);
		IProjectType previous = getExtensionProjectTypeMap().put(projectType.getId(), projectType);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"ProjectType",	//$NON-NLS-1$
					projectType.getId());
		}
	}

	/**
	 * Adds a Configuration that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionConfiguration(Configuration configuration) {
		IConfiguration previous = getExtensionConfigurationMap().put(configuration.getId(), configuration);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"Configuration",	//$NON-NLS-1$
					configuration.getId());
		}
	}

	/**
	 * Adds a Resource Configuration that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionResourceConfiguration(ResourceConfiguration resourceConfiguration) {
		IResourceConfiguration previous = getExtensionResourceConfigurationMap().put(resourceConfiguration.getId(), resourceConfiguration);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"ResourceConfiguration",	//$NON-NLS-1$
					resourceConfiguration.getId());
		}
	}

	/**
	 * Adds a ToolChain that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionToolChain(ToolChain toolChain) {
		IToolChain previous = getExtensionToolChainMapInternal().put(toolChain.getId(), toolChain);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"ToolChain",	//$NON-NLS-1$
					toolChain.getId());
		}
	}

	/**
	 * Adds a tool that is is specified in the manifest to the
	 * build system. This tool is available to any target that
	 * has a reference to it as part of its description. This
	 * permits a tool that is common to many targets to be defined
	 * only once.
	 */
	public static void addExtensionTool(Tool tool) {
		ITool previous = getExtensionToolMapInternal().put(tool.getId(), tool);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"Tool",	//$NON-NLS-1$
					tool.getId());
		}
	}

	/**
	 * Adds a TargetPlatform that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionTargetPlatform(TargetPlatform targetPlatform) {
		ITargetPlatform previous = getExtensionTargetPlatformMap().put(targetPlatform.getId(), targetPlatform);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"TargetPlatform",	//$NON-NLS-1$
					targetPlatform.getId());
		}
	}

	/**
	 * Adds a Builder that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionBuilder(Builder builder) {
		IBuilder previous = getExtensionBuilderMapInternal().put(builder.getId(), builder);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"Builder",	//$NON-NLS-1$
					builder.getId());
		}
	}

	/**
	 * Adds a Option that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionOption(Option option) {
		IOption previous = getExtensionOptionMap().put(option.getId(), option);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"Option",	//$NON-NLS-1$
					option.getId());
		}
	}

	/**
	 * Adds a OptionCategory that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionOptionCategory(OptionCategory optionCategory) {
		IOptionCategory previous = getExtensionOptionCategoryMap().put(optionCategory.getId(), optionCategory);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"OptionCategory",	//$NON-NLS-1$
					optionCategory.getId());
		}
	}

	/**
	 * Adds an InputType that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionInputType(InputType inputType) {
		IInputType previous = getExtensionInputTypeMap().put(inputType.getId(), inputType);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"InputType",	//$NON-NLS-1$
					inputType.getId());
		}
	}

	/**
	 * Adds an OutputType that is is specified in the manifest to the
	 * build system. It is available to any element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionOutputType(OutputType outputType) {
		IOutputType previous = getExtensionOutputTypeMap().put(outputType.getId(), outputType);
		if (previous != null) {
			// Report error
			ManagedBuildManager.outputDuplicateIdError(
					"OutputType",	//$NON-NLS-1$
					outputType.getId());
		}
	}

	/**
	 * Adds a Target that is is specified in the manifest to the
	 * build system. It is available to any CDT 2.0 object model element that
	 * has a reference to it as part of its description.
	 */
	public static void addExtensionTarget(Target target) {
		getExtensionTargetMap().put(target.getId(), target);
	}

	/**
	 * Creates a new project instance for the resource based on the parent project type.
	 *
	 * @param parent - parent project type
	 * @return new <code>ITarget</code> with settings based on the parent passed in the arguments
	 */
	public static IManagedProject createManagedProject(IResource resource, IProjectType parent)
		throws BuildException
	{
		return new ManagedProject(resource, parent);
	}

	/**
	 * Creates a new target for the resource based on the parentTarget.
	 *
	 * @return new <code>ITarget</code> with settings based on the parent passed in the arguments
	 */
	public static ITarget createTarget(IResource resource, ITarget parentTarget)
		throws BuildException
	{
		IResource owner = parentTarget.getOwner();

		if (owner != null && owner.equals(resource))
			// Already added
			return parentTarget;

		if (resource instanceof IProject) {
			// Must be an extension target
			if (owner != null)
				throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.owner_not_null")); //$NON-NLS-1$
		} else {
			// Owner must be owned by the project containing this resource
			if (owner == null)
				throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.null_owner")); //$NON-NLS-1$
			if (!owner.equals(resource.getProject()))
				throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.owner_not_project")); //$NON-NLS-1$
		}

		// Passed validation so create the target.
		return new Target(resource, parentTarget);
	}

	public static IStatus initBuildInfoContainer(IResource resource) {
		return Status.OK_STATUS;
		/*
		ManagedBuildInfo buildInfo = null;

		// Get the build info associated with this project for this session
		try {
			buildInfo = findBuildInfo(resource.getProject(), true);
			initBuildInfoContainer(buildInfo);
		} catch (CoreException e) {
			return new Status(IStatus.ERROR,
				ManagedBuilderCorePlugin.PLUGIN_ID,
				IStatus.ERROR,
				e.getLocalizedMessage(),
				e);
		}
		return new Status(IStatus.OK,
			ManagedBuilderCorePlugin.PLUGIN_ID,
			IStatus.OK,
			ManagedMakeMessages.getFormattedString("ManagedBuildInfo.message.init.ok", resource.getName()),	//$NON-NLS-1$
			null);
			*/
	}

//	/**
//	 * Private helper method to initialize the path entry container once and
//	 * only once when the build info is first loaded or created.
//	 *
//	 * @param info
//	 * @throws CoreException
//	 */
//	private static void initBuildInfoContainer(ManagedBuildInfo info) throws CoreException {
//		if (info == null) {
//			throw new CoreException(new Status(IStatus.ERROR,
//					ManagedBuilderCorePlugin.PLUGIN_ID,
//					IStatus.ERROR,
//					new String(),
//					null));
//		}
//
//		if (info.isContainerInited()) return;
//		// Now associate the path entry container with the project
//		ICProject cProject = info.getCProject();
//
//		synchronized (cProject) {
//
//			// This does not block the workspace or trigger delta events
//		IPathEntry[] entries = cProject.getRawPathEntries();
//		// Make sure the container for this project is in the path entries
//		List newEntries = new ArrayList(Arrays.asList(entries));
//		if (!newEntries.contains(ManagedBuildInfo.containerEntry)) {
//			// In this case we should trigger an init and deltas
//			newEntries.add(ManagedBuildInfo.containerEntry);
//			cProject.setRawPathEntries((IPathEntry[])newEntries.toArray(new IPathEntry[newEntries.size()]), new NullProgressMonitor());
//		}
//		info.setContainerInited(true);
//
//		}  //  end synchronized
//	}

	private static boolean isVersionCompatible(IExtension extension) {
		// We can ignore the qualifier
		Version version = null;

		// Get the version of the manifest
		IConfigurationElement[] elements = extension.getConfigurationElements();

		// Find the version string in the manifest
		for (IConfigurationElement element : elements) {
			if (element.getName().equals(REVISION_ELEMENT_NAME)) {
				version = new Version(element.getAttribute(VERSION_ELEMENT_NAME));
				break;
			}
		}

		if (version == null) {
			// This is a 1.2 manifest and we are compatible for now
			return true;
		}
		return(buildInfoVersion.compareTo(version)>=0);
	}

	/**
	 * Determine if the .cdtbuild file is present, which will determine if build information
	 * can be loaded externally or not. Return true if present, false otherwise.
	 */
	private static boolean canLoadBuildInfo(final IProject project) {
		IFile file = project.getFile(SETTINGS_FILE_NAME);
	    if (file == null) return false;
		File cdtbuild = file.getLocation().toFile();
		if (cdtbuild == null) return false;
		return cdtbuild.exists();
	}

	/**
	 * Load the build information for the specified resource from its project
	 * file. Pay attention to the version number too.
	 */
	private static ManagedBuildInfo loadOldStyleBuildInfo(final IProject project) throws Exception {
		ManagedBuildInfo buildInfo = null;
		IFile file = project.getFile(SETTINGS_FILE_NAME);
		File cdtbuild = file.getLocation().toFile();
		if (!cdtbuild.exists()) {
			// If we cannot find the .cdtbuild project file, throw an exception and let the user know
			throw new BuildException(ManagedMakeMessages.getFormattedString(PROJECT_FILE_ERROR, project.getName()));
		}

		// So there is a project file, load the information there
		InputStream stream = new FileInputStream(cdtbuild);
		try {
			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = parser.parse(stream);
			String fileVersion = null;

			// Get the first element in the project file
			Node rootElement = document.getFirstChild();

			// Since 2.0 this will be a processing instruction containing version
			if (rootElement.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE) {
				// This is a 1.2 project and it must be updated
			} else {
				// Make sure that the version is compatible with the manager
				fileVersion = rootElement.getNodeValue();
				Version version = new Version(fileVersion);
				//if buildInfoVersion is greater than fileVersion
				if (buildInfoVersion.compareTo(version)>0) {
					// This is >= 2.0 project, but earlier than the current MBS version - it may need to be updated
				} else {
					// This is a
					//  isCompatibleWith will return FALSE, if:
					//   o  The major versions are not equal
					//   o  The major versions are equal, but the remainder of the .cdtbuild version # is
					//      greater than the MBS version #
					boolean compatible=false;
					if (version == null)
						compatible=false;
					if (buildInfoVersion.getMajor() != version.getMajor())
						compatible=false;
					if (buildInfoVersion.getMinor() > version.getMinor())
						compatible=true;
					if (buildInfoVersion.getMinor() < version.getMinor())
						compatible=false;
					if (buildInfoVersion.getMicro() > version.getMicro())
						compatible=true;
					if (buildInfoVersion.getMicro() < version.getMicro())
						compatible=false;
					if (buildInfoVersion.getQualifier().compareTo(version.getQualifier()) >= 0)
						compatible=true;
					if (!compatible) {
						throw new BuildException(ManagedMakeMessages.getFormattedString(PROJECT_VERSION_ERROR, project.getName()));
					}
				}
			}

			// Now get the project root element (there should be only one)
			NodeList nodes = document.getElementsByTagName(ROOT_NODE_NAME);
			if (nodes.getLength() > 0) {
				Node node = nodes.item(0);

				//  Create the internal representation of the project's MBS information
				buildInfo = new ManagedBuildInfo(project, XmlStorageUtil.createCStorageTree((Element)node), true, fileVersion);
				if (fileVersion != null) {
	//				buildInfo.setVersion(fileVersion);
					Version version = new Version(fileVersion);
					Version version21 = new Version("2.1");		//$NON-NLS-1$
					//  CDT 2.1 is the first version using the new MBS model
					if (version.compareTo(version21)>=0) {
						//  Check to see if all elements could be loaded correctly - for example,
						//  if references in the project file could not be resolved to extension
						//  elements
						if (buildInfo.getManagedProject() == null ||
							(!buildInfo.getManagedProject().isValid())) {
							//  The load failed
							throw  new Exception(ManagedMakeMessages.getFormattedString("ManagedBuildManager.error.id.nomatch", project.getName())); //$NON-NLS-1$
						}

						// Each ToolChain/Tool/Builder element maintain two separate
						// converters if available
						// 0ne for previous Mbs versions and one for current Mbs version
						// walk through the project hierarchy and call the converters
						// written for previous mbs versions
						if ( checkForMigrationSupport(buildInfo, false) != true ) {
							// display an error message that the project is not loadable
							if (buildInfo.getManagedProject() == null ||
									(!buildInfo.getManagedProject().isValid())) {
									//  The load failed
									throw  new Exception(ManagedMakeMessages.getFormattedString("ManagedBuildManager.error.id.nomatch", project.getName())); //$NON-NLS-1$
							}
						}
					}
				}

				//  Upgrade the project's CDT version if necessary
				if (!UpdateManagedProjectManager.isCompatibleProject(buildInfo)) {
					UpdateManagedProjectManager.updateProject(project, buildInfo);
				}
				//  Check to see if the upgrade (if required) succeeded
				if (buildInfo.getManagedProject() == null ||
					(!buildInfo.getManagedProject().isValid())) {
					//  The load failed
					throw  new Exception(ManagedMakeMessages.getFormattedString("ManagedBuildManager.error.id.nomatch", project.getName())); //$NON-NLS-1$
				}

				//  Walk through the project hierarchy and call the converters
				//  written for current mbs version
				if ( checkForMigrationSupport(buildInfo, true) != true ) {
					// display an error message.that the project is no loadable
					if (buildInfo.getManagedProject() == null ||
							(!buildInfo.getManagedProject().isValid())) {
							//  The load failed
							throw  new Exception(ManagedMakeMessages.getFormattedString("ManagedBuildManager.error.id.nomatch", project.getName())); //$NON-NLS-1$
						}
				}

				IConfiguration[] configs = buildInfo.getManagedProject().getConfigurations();
				//  Send an event to each configuration and if they exist, its resource configurations
				for (IConfiguration cfg : configs) {
					ManagedBuildManager.performValueHandlerEvent(cfg, IManagedOptionValueHandler.EVENT_OPEN);
				}
				//  Finish up
				//project.setSessionProperty(buildInfoProperty, buildInfo);
				setLoaddedBuildInfo(project, buildInfo);
			}
		} catch (Exception e) {
			throw e;
		}

		buildInfo.setValid(true);
		return buildInfo;
	}

	/**
	 * This method loads all of the managed build system manifest files
	 * that have been installed with CDT.  An internal hierarchy of
	 * objects is created that contains the information from the manifest
	 * files.  The information is then accessed through the ManagedBuildManager.
	 *
	 * Since the class does not have a constructor but all public methods
	 * call this method first, it is effectively a startup method
	 */
	private static void loadExtensions() throws BuildException {
		if (projectTypesLoaded)
			return;

		loadExtensionsSynchronized();
	}

	private synchronized static void loadExtensionsSynchronized() throws BuildException {
		// Do this once
		if (projectTypesLoaded)
				return;

		// This routine gets called recursively.  If so, just return
		if (projectTypesLoading)
			return;
		projectTypesLoading = true;


		// scalability issue:  configElementMap does not need to live past when loading is done, so we will
		// deallocate it upon exit with a try...finally

		try {

		//The list of the IManagedBuildDefinitionsStartup callbacks
		List<IManagedBuildDefinitionsStartup> buildDefStartupList = null;
		// Get the extensions that use the current CDT managed build model
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID);
		if( extensionPoint != null) {
			IExtension[] extensions = extensionPoint.getExtensions();
			if (extensions != null) {

				// First call the constructors of the internal classes that correspond to the
				// build model elements
				for (IExtension extension : extensions) {
					// Can we read this manifest
					if (!isVersionCompatible(extension)) {
						//  The version of the Plug-in is greater than what the manager thinks it understands
						//  Display error message
						IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
						if(window == null){
							IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
							window = windows[0];
						}

						final Shell shell = window.getShell();
						final String errMsg = ManagedMakeMessages.getFormattedString(MANIFEST_VERSION_ERROR, extension.getUniqueIdentifier());
						shell.getDisplay().asyncExec( new Runnable() {
							@Override
							public void run() {
								MessageDialog.openError(shell,
										ManagedMakeMessages.getResourceString("ManagedBuildManager.error.manifest_load_failed_title"),	//$NON-NLS-1$
										errMsg);
							}
						} );
					} else {
						// Get the "configuraton elements" defined in the plugin.xml file.
						// Note that these "configuration elements" are not related to the
						// managed build system "configurations".
						// From the PDE Guide:
						//  A configuration element, with its attributes and children, directly
						//  reflects the content and structure of the extension section within the
						//  declaring plug-in's manifest (plugin.xml) file.
						IConfigurationElement[] elements = extension.getConfigurationElements();
						String revision = null;

						// Get the managedBuildRevsion of the extension.
						for (IConfigurationElement element : elements) {
							if( element.getName().equals(REVISION_ELEMENT_NAME) ) {
								revision = element.getAttribute(VERSION_ELEMENT_NAME);
								break;
							}
						}

						// Get the value of 'ManagedBuildRevision' attribute
						loadConfigElements(DefaultManagedConfigElement.convertArray(elements, extension), revision);
					}
				}

				// Call the start up config extensions. These may rely on the standard elements
				// having already been loaded so we wait to call them from here.
				if (startUpConfigElements != null) {
					buildDefStartupList = new ArrayList<IManagedBuildDefinitionsStartup>(startUpConfigElements.size());

					for (IManagedConfigElement startUpConfigElement : startUpConfigElements) {
						IManagedBuildDefinitionsStartup customConfigLoader;
						try {
							customConfigLoader = createStartUpConfigLoader((DefaultManagedConfigElement)startUpConfigElement);

							//need to save the startup for the future notifications
							buildDefStartupList.add(customConfigLoader);

							// Now we can perform any actions on the build configurations
							// in an extended plugin before the build configurations have been resolved
							customConfigLoader.buildDefsLoaded();
						} catch (CoreException e) {
						}
					}
				}

				// Then call resolve.
				//
				// Here are notes on "references" within the managed build system.
				// References are "pointers" from one model element to another.
				// These are encoded in manifest and managed build system project files (.cdtbuild)
				// using unique string IDs (e.g. "cdt.managedbuild.tool.gnu.c.linker").
				// These string IDs are "resolved" to pointers to interfaces in model
				// elements in the in-memory represent of the managed build system information.
				//
				// Here are the current "rules" for references:
				//  1.  A reference is always resolved to an interface pointer in the
				//      referenced object.
				//  2.  A reference is always TO an extension object - that is, an object
				//      loaded from a manifest file or a dynamic element provider.  It cannot
				//      be to an object loaded from a managed build system project file (.cdtbuild).
				//

				Collection<IProjectType> prjTypes = getExtensionProjectTypeMap().values();
				for (IProjectType projectType : prjTypes) {
					try {
						((ProjectType) projectType).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<IConfiguration> configurations = getExtensionConfigurationMap().values();
				for (IConfiguration configuration : configurations) {
					try {
						((Configuration) configuration).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<IResourceConfiguration> resConfigs = getExtensionResourceConfigurationMap().values();
				for (IResourceConfiguration resConfig : resConfigs) {
					try {
						((ResourceConfiguration) resConfig).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<ToolChain> toolChains = getExtensionToolChainMapInternal().values();
				for (ToolChain toolChain : toolChains) {
					try {
						toolChain.resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<Tool> tools = getExtensionToolMapInternal().values();
				for (Tool tool : tools) {
					try {
						tool.resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<ITargetPlatform> targetPlatforms = getExtensionTargetPlatformMap().values();
				for (ITargetPlatform targetPlatform : targetPlatforms) {
					try {
						((TargetPlatform) targetPlatform).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<Builder> builders = getExtensionBuilderMapInternal().values();
				for (Builder builder : builders) {
					try {
						builder.resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<IOption> options = getExtensionOptionMap().values();
				for (IOption option : options) {
					try {
						((Option) option).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
				Collection<IOptionCategory> optionCategories = getExtensionOptionCategoryMap().values();
				for (IOptionCategory optionCat : optionCategories) {
					try {
						((OptionCategory) optionCat).resolveReferences();
					} catch (Exception ex) {
						// TODO: log
						ex.printStackTrace();
					}
				}
			}
		}

		// Get the extensions that use the CDT 2.0 build model
		extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID_V2);
		if( extensionPoint != null) {
			IExtension[] extensions = extensionPoint.getExtensions();
			String revision = null;

			if (extensions != null) {
				if (extensions.length > 0) {

					// Call the constructors of the internal classes that correspond to the
					// V2.0 build model elements.  Some of these objects are converted to new model objects.
					// Others can use the same classes.
					for (IExtension extension : extensions) {
						// Can we read this manifest
						if (!isVersionCompatible(extension)) {
							//The version of the Plug-in is greater than what the manager thinks it understands
							throw new BuildException(ManagedMakeMessages.getResourceString(MANIFEST_VERSION_ERROR));
						}
						IConfigurationElement[] elements = extension.getConfigurationElements();

						// Get the managedBuildRevsion of the extension.
						for (IConfigurationElement element : elements) {
							if(element.getName().equals(REVISION_ELEMENT_NAME)) {
								revision = element.getAttribute(VERSION_ELEMENT_NAME);
								break;
							}
						}
						// If the "fileVersion" attribute is missing, then default revision is "1.2.0"
						if (revision == null)
							revision = "1.2.0"; 	//$NON-NLS-1$
						loadConfigElementsV2(DefaultManagedConfigElement.convertArray(elements, extension), revision);
					}
					// Resolve references
					Collection<ITarget> targets = getExtensionTargetMap().values();
					for (ITarget target : targets) {
						try {
							((Target) target).resolveReferences();
						} catch (Exception ex) {
							// TODO: log
							ex.printStackTrace();
						}
					}
					// The V2 model can also add top-level Tools - they need to be "resolved"
					Collection<Tool> tools = getExtensionToolMapInternal().values();
					for (Tool tool : tools) {
						try {
							tool.resolveReferences();
						} catch (Exception ex) {
							// TODO: log
							ex.printStackTrace();
						}
					}
					// Convert the targets to the new model
					targets = getExtensionTargetMap().values();
					for (ITarget target : targets) {
						try {
							//  Check to see if it has already been converted - if not, do it
							if (target.getCreatedProjectType() == null) {
								target.convertToProjectType(revision);
							}
						} catch (Exception ex) {
							// TODO: log
							ex.printStackTrace();
						}
					}
					// Resolve references for new ProjectTypes
					Collection<IProjectType> prjTypes = getExtensionProjectTypeMap().values();
					for (IProjectType prjType : prjTypes) {
						try {
							((ProjectType) prjType).resolveReferences();
						} catch (Exception ex) {
							// TODO: log
							ex.printStackTrace();
						}
					}

					// TODO:  Clear the target and configurationV2 maps so that the object can be garbage collected
					//        We can't do this yet, because the UpdateManagedProjectAction class may need these elements later
					//        Can we change UpdateManagedProjectAction to see the converted model elements?
					//targetIter = getExtensionTargetMap().values().iterator();
					//while (targetIter.hasNext()) {
					//	try {
					//		Target target = (Target)targetIter.next();
					//		ManagedBuildManager.removeConfigElement(target);
					//		getExtensionTargetMap().remove(target);
					//	} catch (Exception ex) {
					//		// TODO: log
					//		ex.printStackTrace();
					//	}
					//}
					//getExtensionConfigurationV2Map().clear();
				}
			}
		}

		// configs resolved...
		// Call the start up config extensions again now that configs have been resolved.
		if (buildDefStartupList != null) {
			for (IManagedBuildDefinitionsStartup customConfigLoader : buildDefStartupList) {
				// Now we can perform any actions on the build configurations
				// in an extended plugin now that all build configruations have been resolved
				customConfigLoader.buildDefsResolved();
			}
		}

		performAdjustments();
		projectTypesLoading = false;
		projectTypesLoaded = true;

		ToolChainModificationManager.getInstance().start();

		} // try

		finally {
			configElementMap = null;
		}
	}

	private static void performAdjustments(){
		IProjectType types[] = getDefinedProjectTypes();
		for (IProjectType type : types) {
			IConfiguration cfgs[] = type.getConfigurations();
			for (IConfiguration cfg : cfgs) {
				adjustConfig(cfg);
			}
		}

		for (IProjectType type : types) {
			IConfiguration cfgs[] = type.getConfigurations();
			for (IConfiguration cfg : cfgs) {
				performValueHandlerEvent(cfg, IManagedOptionValueHandler.EVENT_LOAD);
			}
		}

	}

	private static void adjustConfig(IConfiguration cfg){
		IResourceInfo rcInfos[] = cfg.getResourceInfos();
		for (IResourceInfo rcInfo : rcInfos) {
			if(rcInfo instanceof IFolderInfo){
				IFolderInfo info = (IFolderInfo)rcInfo;
				IToolChain tc = info.getToolChain();
				adjustHolder(info, tc);

				ITool tools[] = tc.getTools();
				for (ITool tool : tools) {
					adjustHolder(info, tool);
				}
			} else if (rcInfo instanceof IFileInfo){
				IFileInfo info = (IFileInfo)rcInfo;
				ITool rcTools[] = info.getTools();
				for (ITool rcTool : rcTools) {
					adjustHolder(info, rcTool);
				}

			}
		}

		IResourceConfiguration rcCfgs[] = cfg.getResourceConfigurations();

//		for (IResourceConfiguration rcCfg : rcCfgs) {
//		}

	}

	private static void adjustHolder(IResourceInfo rcInfo, IHoldsOptions holder){
		IOption options[] = holder.getOptions();

		for (IOption opt : options) {
			Option option = (Option)opt;
			BooleanExpressionApplicabilityCalculator calc =
				option.getBooleanExpressionCalculator(true);

			if(calc != null)
				calc.adjustOption(rcInfo,holder,option, true);
		}
	}


	private static void loadConfigElements(IManagedConfigElement[] elements, String revision) {
		for (IManagedConfigElement element : elements) {
			try {
				// Load the top level elements, which in turn load their children
				if (element.getName().equals(IProjectType.PROJECTTYPE_ELEMENT_NAME)) {
					new ProjectType(element, revision);
				} else if (element.getName().equals(IConfiguration.CONFIGURATION_ELEMENT_NAME)) {
					new Configuration((ProjectType)null, element, revision);
				} else if (element.getName().equals(IToolChain.TOOL_CHAIN_ELEMENT_NAME)) {
					new ToolChain((IFolderInfo)null, element, revision);
				} else if (element.getName().equals(ITool.TOOL_ELEMENT_NAME)) {
					new Tool((ProjectType)null, element, revision);
				} else if (element.getName().equals(ITargetPlatform.TARGET_PLATFORM_ELEMENT_NAME)) {
					new TargetPlatform((ToolChain)null, element, revision);
				} else if (element.getName().equals(IBuilder.BUILDER_ELEMENT_NAME)) {
					new Builder((ToolChain)null, element, revision);
				} else if (element.getName().equals(IManagedConfigElementProvider.ELEMENT_NAME)) {
					// don't allow nested config providers.
					if (element instanceof DefaultManagedConfigElement) {
						IManagedConfigElement[] providedConfigs;
						IManagedConfigElementProvider provider = createConfigProvider(
								(DefaultManagedConfigElement)element);
						providedConfigs = provider.getConfigElements();
						loadConfigElements(providedConfigs, revision);	// This must use the current build model
					}
				} else if (element.getName().equals(IManagedBuildDefinitionsStartup.BUILD_DEFINITION_STARTUP)) {
					if (element instanceof DefaultManagedConfigElement) {
					// Cache up early configuration extension elements so was can call them after
					// other configuration elements have loaded.
						if (startUpConfigElements == null)
							startUpConfigElements = new ArrayList<IManagedConfigElement>();
						startUpConfigElements.add(element);
					}
				} else {
					// TODO: Report an error (log?)
				}
			} catch (Exception ex) {
				// TODO: log
				ex.printStackTrace();
			}
		}
	}

	private static void loadConfigElementsV2(IManagedConfigElement[] elements, String revision) {
		for (IManagedConfigElement element : elements) {
			try {
				// Load the top level elements, which in turn load their children
				if (element.getName().equals(ITool.TOOL_ELEMENT_NAME)) {
					new Tool(element, revision);
				} else if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME)) {
					new Target(element,revision);
				} else if (element.getName().equals(IManagedConfigElementProvider.ELEMENT_NAME)) {
					// don't allow nested config providers.
					if (element instanceof DefaultManagedConfigElement) {
						IManagedConfigElement[] providedConfigs;
						IManagedConfigElementProvider provider = createConfigProvider(
								(DefaultManagedConfigElement)element);
						providedConfigs = provider.getConfigElements();
						loadConfigElementsV2(providedConfigs, revision);	// This must use the 2.0 build model
					}
				}
			} catch (Exception ex) {
				// TODO: log
				ex.printStackTrace();
			}
		}
	}

	/*
	 * Creates a new build information object and associates it with the
	 * resource in the argument. Note that the information contains no
	 * build target or configuation information. It is the responsibility
	 * of the caller to populate it. It is also important to note that the
	 * caller is responsible for associating an IPathEntryContainer with the
	 * build information after it has been populated.
	 * <p>
	 * The typical sequence of calls to add a new build information object to
	 * a managed build project is
	 * <p><pre>
	 * ManagedBuildManager.createBuildInfo(project);
	 * &#047;&#047; Do whatever initialization you need here
	 * ManagedBuildManager.createTarget(project);
	 * ManagedBuildManager.initBuildInfoContainer(project);
	 *
	 * @param resource The resource the build information is associated with
	 */
	public static ManagedBuildInfo createBuildInfo(IResource resource) {
		IProject proj = resource.getProject();
		ManagedBuildInfo buildInfo = new ManagedBuildInfo(proj);
		try {
			setLoaddedBuildInfo(proj, buildInfo);
		} catch (CoreException e) {
			ManagedBuilderCorePlugin.log(e);
			buildInfo = null;
		}
		return buildInfo;
	}

	public static void setLoaddedBuildInfo(IProject project, IManagedBuildInfo info) throws CoreException{
		// Associate the build info with the project for the duration of the session
		//project.setSessionProperty(buildInfoProperty, info);
//		IResourceRuleFactory rcRf = ResourcesPlugin.getWorkspace().getRuleFactory();
//		ISchedulingRule rule = rcRf.modifyRule(project);
//		IJobManager mngr = Job.getJobManager();

//		try {
//			mngr.beginRule(rule, null);
			doSetLoaddedInfo(project, info, true);
//		} catch (IllegalArgumentException e) {
//			// TODO: set anyway for now
//			doSetLoaddedInfo(project, info);
//		}finally {
//			mngr.endRule(rule);
//		}
	}

	private synchronized static void doSetLoaddedInfo(IProject project, IManagedBuildInfo info, boolean overwrite){
		if(!overwrite && fInfoMap.get(project) != null)
			return;

		if(info != null){
			fInfoMap.put(project, info);
			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: build info set for project " + project.getName()); //$NON-NLS-1$
		}else{
			fInfoMap.remove(project);
			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: build info CLEARED for project " + project.getName()); //$NON-NLS-1$
		}
	}

	private static IManagedConfigElementProvider createConfigProvider(
		DefaultManagedConfigElement element) throws CoreException {

		return (IManagedConfigElementProvider)element.getConfigurationElement().
			createExecutableExtension(IManagedConfigElementProvider.CLASS_ATTRIBUTE);
	}


	private static IManagedBuildDefinitionsStartup createStartUpConfigLoader(
			DefaultManagedConfigElement element) throws CoreException {

			return (IManagedBuildDefinitionsStartup)element.getConfigurationElement().createExecutableExtension(IManagedBuildDefinitionsStartup.CLASS_ATTRIBUTE);
		}

	public static boolean manages(IResource resource) {
		ICProjectDescription des = CoreModel.getDefault().getProjectDescription(resource.getProject(), false);
		if(des == null){
			return false;
		}

		ICConfigurationDescription cfgDes = des.getActiveConfiguration();
		IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(cfgDes);
		if(cfg != null)
			return true;
		return false;


		//		// The managed build manager manages build information for the
//		// resource IFF it it is a project and has a build file with the proper
//		// root element
//		IProject project = null;
//		if (resource instanceof IProject){
//			project = (IProject)resource;
//		} else if (resource instanceof IFile) {
//			project = ((IFile)resource).getProject();
//		} else {
//			return false;
//		}
//		IFile file = project.getFile(SETTINGS_FILE_NAME);
//		if (file.exists()) {
//			try {
//				InputStream stream = file.getContents();
//				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//				Document document = parser.parse(stream);
//				NodeList nodes = document.getElementsByTagName(ROOT_NODE_NAME);
//				return (nodes.getLength() > 0);
//			} catch (Exception e) {
//				return false;
//			}
//		}
//		return false;
	}

	/**
	 * Private helper method that first checks to see if a build information
	 * object has been associated with the project for the current workspace
	 * session. If one cannot be found, one is created from the project file
	 * associated with the argument. If there is no project file or the load
	 * fails for some reason, the method will return {@code null}.
	 */
	private static ManagedBuildInfo findBuildInfo(IResource rc, boolean forceLoad) {

		if (rc == null){
			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: null resource"); //$NON-NLS-1$
			return null;
		}

		ManagedBuildInfo buildInfo = null;
		IProject proj = rc.getProject();

		if (!proj.exists()) {
			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: info is null, project does not exist"); //$NON-NLS-1$
			return null;
		}

		if(BuildDbgUtil.DEBUG)
			BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: info is null, querying the update mngr"); //$NON-NLS-1$
		buildInfo = UpdateManagedProjectManager.getConvertedManagedBuildInfo(proj);

		if(buildInfo != null)
			return buildInfo;

		// Check if there is any build info associated with this project for this session
		try {
			buildInfo = getLoadedBuildInfo(proj);
		} catch (CoreException e) {
			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: core exception while getting the loaded info: " + e.getLocalizedMessage()); //$NON-NLS-1$
			return null;
		}

		if(buildInfo == null /*&& forceLoad*/){
			int flags = forceLoad ? 0 : ICProjectDescriptionManager.GET_IF_LOADDED;

			if(BuildDbgUtil.DEBUG)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: build info is NOT loaded" + (forceLoad ? " forceload" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			ICProjectDescription projDes = CoreModel.getDefault().getProjectDescriptionManager().getProjectDescription(proj, flags);
			if(projDes != null){
				if(BuildDbgUtil.DEBUG)
					BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: project description is obtained, qwerying the loaded build info"); //$NON-NLS-1$
				try {
					buildInfo = getLoadedBuildInfo(proj);
				} catch (CoreException e) {
					if(BuildDbgUtil.DEBUG)
						BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: core exception while getting the loaded info (2): " + e.getLocalizedMessage()); //$NON-NLS-1$
					return null;
				}

				if(buildInfo == null){
					if(BuildDbgUtil.DEBUG)
						BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: info is null, trying the cfg data provider"); //$NON-NLS-1$

					buildInfo = ConfigurationDataProvider.getLoaddedBuildInfo(projDes);
					if(buildInfo != null){
						if(BuildDbgUtil.DEBUG)
							BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: info found, setting as loaded"); //$NON-NLS-1$

						try {
							setLoaddedBuildInfo(proj, buildInfo);
						} catch (CoreException e) {
							if(BuildDbgUtil.DEBUG)
								BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: core exception while setting loaded description, ignoring; : " + e.getLocalizedMessage()); //$NON-NLS-1$
						}
					}

				}

			} else if(BuildDbgUtil.DEBUG){
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: project description in null"); //$NON-NLS-1$
			}


//			if(buildInfo == null){
//				if(BuildDbgUtil.DEBUG)
//					BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: info is null, querying the update mngr"); //$NON-NLS-1$
//				buildInfo = UpdateManagedProjectManager.getConvertedManagedBuildInfo(proj);
//			}
		}
//		if (buildInfo == null && resource instanceof IProject)
//			buildInfo = findBuildInfoSynchronized((IProject)resource, forceLoad);
/*
		// Nothing in session store, so see if we can load it from cdtbuild
		if (buildInfo == null && resource instanceof IProject) {
			try {
				buildInfo = loadBuildInfo((IProject)resource);
			} catch (Exception e) {
				// TODO:  Issue error reagarding not being able to load the project file (.cdtbuild)
			}

			try {
				// Check if the project needs its container initialized
				initBuildInfoContainer(buildInfo);
			} catch (CoreException e) {
				// We can live without a path entry container if the build information is valid
			}
		}
*/
		if(buildInfo != null)
			buildInfo.updateOwner(proj);

		if(BuildDbgUtil.DEBUG){
			if(buildInfo == null)
				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: build info is null"); //$NON-NLS-1$
//			else
//				BuildDbgUtil.getInstance().traceln(BuildDbgUtil.BUILD_INFO_LOAD, "build info load: build info found");
		}

		return buildInfo;
	}

	synchronized static ManagedBuildInfo getLoadedBuildInfo(IProject project) throws CoreException{
		// Check if there is any build info associated with this project for this session
		ManagedBuildInfo buildInfo = (ManagedBuildInfo)fInfoMap.get(project);//project.getSessionProperty(buildInfoProperty);
			// Make sure that if a project has build info, that the info is not corrupted
		if (buildInfo != null) {
			buildInfo.updateOwner(project);
		}
		return buildInfo;
	}

	/**
	 * Determine if build information can be found. Various attempts are made
	 * to find the information, and if successful, true is returned; false otherwise.
	 * Typically, this routine would be called prior to findBuildInfo, to deterimine
	 * if findBuildInfo should be called to actually do the loading of build
	 * information, if possible
	 */
	private static boolean canFindBuildInfo(IResource resource) {

		if (resource == null) return false;

		// Make sure the extension information is loaded first
		try {
			loadExtensions();
		} catch (BuildException e) {
			e.printStackTrace();
			return false;
		}

		ManagedBuildInfo buildInfo = null;

		// Check if there is any build info associated with this project for this session
		try {
			buildInfo = getLoadedBuildInfo(resource.getProject());
		} catch (CoreException e) {
			// Continue, to see if any of the upcoming checks are successful
		}

		if (buildInfo == null && resource instanceof IProject) {
			// Check weather getBuildInfo is called from converter
			buildInfo = UpdateManagedProjectManager.getConvertedManagedBuildInfo((IProject)resource);
			if (buildInfo != null) return true;
			// Check if the build information can be loaded from the .cdtbuild file
			return canLoadBuildInfo(((IProject)resource));
		}

		return (buildInfo != null);
	}

	/**
	 * this method is called if managed build info session property
	 * was not set. The caller will use the project rule
	 * to synchronize with other callers
	 * findBuildInfoSynchronized could also be called from project converter
	 * in this case the ManagedBuildInfo saved in the converter would be returned
	 */
/*	synchronized private static ManagedBuildInfo findBuildInfoSynchronized(IProject project, boolean forceLoad) {
		ManagedBuildInfo buildInfo = null;

		// Check if there is any build info associated with this project for this session
		try {
			buildInfo = (ManagedBuildInfo)project.getSessionProperty(buildInfoProperty);
			// Make sure that if a project has build info, that the info is not corrupted
			if (buildInfo != null) {
				buildInfo.updateOwner(project);
			}
		} catch (CoreException e) {
	//		return null;
		}

		if(buildInfo == null && forceLoad){
			// Make sure the extension information is loaded first
			try {
				loadExtensions();
			} catch (BuildException e) {
				e.printStackTrace();
				return null;
			}


			// Check weather getBuildInfo is called from converter
			buildInfo = UpdateManagedProjectManager.getConvertedManagedBuildInfo(project);

			// Nothing in session store, so see if we can load it from cdtbuild
			if (buildInfo == null) {
				try {
					buildInfo = loadBuildInfo(project);
				} catch (Exception e) {
					// Issue error regarding not being able to load the project file (.cdtbuild)
					if (buildInfo == null) {
						buildInfo = createBuildInfo(project);
					}
					buildInfo.setValid(false);
					//  Display error message
					IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
					if(window == null){
						IWorkbenchWindow windows[] = PlatformUI.getWorkbench().getWorkbenchWindows();
						window = windows[0];
					}

					final Shell shell = window.getShell();
					final String exceptionMsg = e.getMessage();
					//using syncExec could cause a dead-lock
					//that is why asyncExec is used
					shell.getDisplay().asyncExec( new Runnable() {
						public void run() {
							MessageDialog.openError(shell,
									ManagedMakeMessages.getResourceString("ManagedBuildManager.error.open_failed_title"),	//$NON-NLS-1$
									ManagedMakeMessages.getFormattedString("ManagedBuildManager.error.open_failed",			//$NON-NLS-1$
											exceptionMsg));
						}
					} );
				}

				if (buildInfo != null && !buildInfo.isContainerInited()) {
					//  NOTE:  If this is called inside the above rule, then an IllegalArgumentException can
					//         occur when the CDT project file is saved - it uses the Workspace Root as the scheduling rule.
					//
					try {
						// Check if the project needs its container initialized
						initBuildInfoContainer(buildInfo);
					} catch (CoreException e) {
						// We can live without a path entry container if the build information is valid
					}
				}
			}
		}

		return buildInfo;
	}
*/
	/**
	 * Finds, but does not create, the managed build information for the
	 * argument.
	 * Loads the build info in case it is not currently loaded
	 * Calling this method is the same as calling getBuildInfo(IResource resource, boolean forceLoad)
	 * with the "forceLoad" argument set to true
	 *
	 * @param resource The resource to search for managed build information on.
	 * @return IManagedBuildInfo The build information object for the resource, or null if it doesn't exist
	 */
	public static IManagedBuildInfo getBuildInfo(IResource resource) {
		return getBuildInfo(resource, true);
	}

	public static IManagedBuildInfo getOldStyleBuildInfo(IProject project) throws CoreException {
		IManagedBuildInfo info = null;
		try {
			info = getLoadedBuildInfo(project);
		} catch (CoreException e) {
		}

		if(info == null){
			try {
				info = loadOldStyleBuildInfo(project);

				if(info != null)
					doSetLoaddedInfo(project, info, false);
			} catch (Exception e) {
				throw new CoreException(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, e.getLocalizedMessage(), e));
			}
		}

		return info;

	}

	public static synchronized IManagedBuildInfo getBuildInfoLegacy(IProject project){
		try {
			return getOldStyleBuildInfo(project);
		} catch (CoreException e) {
			ManagedBuilderCorePlugin.log(e);
			return null;
		}
	}
	/**
	 * Finds, but does not create, the managed build information for the
	 * argument.
	 * If the build info is not currently loaded and "forceLoad" argument is set to true,
	 * loads the build info from the .cdtbuild file
	 * In case "forceLoad" is false, does not load the build info and returns null in case it is not loaded
	 *
	 * @param resource The resource to search for managed build information on.
	 * @param forceLoad specifies whether the build info should be loaded in case it is not loaded currently.
	 * @return IManagedBuildInfo The build information object for the resource.
	 */
	public static IManagedBuildInfo getBuildInfo(IResource resource, boolean forceLoad) {
		return findBuildInfo(resource.getProject(), forceLoad);
	}

	/**
	 * Determines if the managed build information for the
	 * argument can be found.
	 *
	 * @param resource The resource to search for managed build information on.
	 * @return boolean True if the build info can be found; false otherwise.
	 */
	public static boolean canGetBuildInfo(IResource resource) {
		return canFindBuildInfo(resource.getProject());
	}

	/**
	 * Answers the current version of the managed builder plugin.
	 *
	 * @return the current version of the managed builder plugin
	 * @since 8.0
	 */
	public static Version getBuildInfoVersion() {
		return buildInfoVersion;
	}

	/**
	 * Get the full URL for a path that is relative to the plug-in
	 * in which .buildDefinitions are defined
	 *
	 * @return the full URL for a path relative to the .buildDefinitions
	 *         plugin
	 */
	public static URL getURLInBuildDefinitions(DefaultManagedConfigElement element, IPath path) {

		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID);
		if( extensionPoint != null) {
			IExtension[] extensions = extensionPoint.getExtensions();
			if (extensions != null) {

				// Iterate over all extensions that contribute to .buildDefinitions
				for (IExtension extension : extensions) {
					// Determine whether the configuration element that is
					// associated with the path, is valid for the extension that
					// we are currently processing.
					//
					// Note: If not done, icon file names would have to be unique
					// across several plug-ins.
					if (element.getExtension().getExtensionPointUniqueIdentifier()
						 == extension.getExtensionPointUniqueIdentifier())
					{
						// Get the path-name
						Bundle bundle = Platform.getBundle( extension.getNamespace() );
						URL url = Platform.find(bundle, path);
						if ( url != null )
						{
							try {
								return Platform.asLocalURL(url);
							} catch (IOException e) {
								// Ignore the exception
								return null;
							}
						}
						else
						{
							// Print a warning
							outputIconError(path.toString());
						}
					}
				}
			}
		}
		return null;
	}

	/*
	 * @return
	 */
	private static Map<IResource, List<IScannerInfoChangeListener>> getBuildModelListeners() {
		if (buildModelListeners == null) {
			buildModelListeners = new HashMap<IResource, List<IScannerInfoChangeListener>>();
		}
		return buildModelListeners;
	}

	private static Map<IBuildObject, IManagedConfigElement> getConfigElementMap() {
		if(!projectTypesLoading)
			throw new IllegalStateException();

		if (configElementMap == null) {
			configElementMap = new HashMap<IBuildObject, IManagedConfigElement>();
		}
		return configElementMap;
	}

	/**
	 * @noreference This method public for implementation reasons.  Not intended for use
	 * by clients.
	 *
	 */
	public static void putConfigElement(IBuildObject buildObj, IManagedConfigElement configElement) {
		getConfigElementMap().put(buildObj, configElement);
	}

	/**
	 * Removes an item from the map
	 */
	private static void removeConfigElement(IBuildObject buildObj) {
		getConfigElementMap().remove(buildObj);
	}

	/**
	 * @noreference This method public for implementation reasons.  Not intended for use
	 * by clients.
	 */
	public static IManagedConfigElement getConfigElement(IBuildObject buildObj) {
		return getConfigElementMap().get(buildObj);
	}

	public static void optionValidError(int errorId, String id) {
		String[] msgs = new String[1];
		msgs[0] = id;
		switch (errorId) {
		case ERROR_CATEGORY:
			ManagedBuildManager.outputManifestError(
					ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_OPTION_CATEGORY, msgs));
			break;
		case ERROR_FILTER:
			ManagedBuildManager.outputManifestError(
					ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_OPTION_FILTER, msgs));
			break;
		}
	}

	public static void optionValueHandlerError(String attribute, String id) {
		String[] msgs = new String[2];
		msgs[0] = attribute;
		msgs[1] = id;
		ManagedBuildManager.outputManifestError(
			ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_OPTION_VALUEHANDLER, msgs));
	}

	public static void outputResolveError(String attribute, String lookupId, String type, String id) {
		String[] msgs = new String[4];
		msgs[0] = attribute;
		msgs[1] = lookupId;
		msgs[2] = type;
		msgs[3] = id;
		ManagedBuildManager.outputManifestError(
			ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_RESOLVING, msgs));
	}

	public static void outputDuplicateIdError(String type, String id) {
		String[] msgs = new String[2];
		msgs[0] = type;
		msgs[1] = id;
		ManagedBuildManager.outputManifestError(
			ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_DUPLICATE, msgs));
	}

	public static void outputManifestError(String message) {
		System.err.println(ManagedMakeMessages.getResourceString(MANIFEST_ERROR_HEADER) + message + NEWLINE);
	}

	public static void outputIconError(String iconLocation) {
		String[] msgs = new String[1];
		msgs[0]= iconLocation;
		ManagedBuildManager.outputManifestError(
			ManagedMakeMessages.getFormattedString(ManagedBuildManager.MANIFEST_ERROR_ICON, msgs));
	}

	/**
	 * @return the instance of the Environment Variable Provider
	 */
	public static IEnvironmentVariableProvider getEnvironmentVariableProvider(){
		return EnvironmentVariableProvider.getDefault();
	}

	/**
	 * @return the version, if 'id' contains a valid version
	 *   or {@code null} otherwise.
	 */

	public static String getVersionFromIdAndVersion(String idAndVersion) {

//		 Get the index of the separator '_' in tool id.
		int index = idAndVersion.lastIndexOf('_');

		//Validate the version number if exists.
		if ( index != -1) {
			// Get the version number from tool id.
			String version = idAndVersion.substring(index+1);

			try {
				// If there is a valid version then return 'version'
				Version.parseVersion(version);
				return version;
			} catch (IllegalArgumentException e) {
				// ignore exception and return null
			}
		}
		// If there is no version information or not a valid version, return null
		return null;
	}

	/**
	 * @return If the input to this function contains 'id & a valid version', it returns only the 'id' part
	 * Otherwise it returns the received input back.
	 */
	public static String getIdFromIdAndVersion(String idAndVersion) {
		// If there is a valid version return only 'id' part
		if ( getVersionFromIdAndVersion(idAndVersion) != null) {
			// Get the index of the separator '_' in tool id.
			int index = idAndVersion.lastIndexOf('_');
			return idAndVersion.substring(0,index);
		}
		else {
			// if there is no version or no valid version
			return idAndVersion;
		}
	}

	/**
	 * @return the instance of the Build Macro Provider
	 */
	public static IBuildMacroProvider getBuildMacroProvider(){
		return BuildMacroProvider.getDefault();
	}

	/**
	 * Send event to value handlers of relevant configuration including
	 * all its child resource configurations, if they exist.
	 *
	 * @param config configuration for which to send the event
	 * @param event to be sent
	 *
	 * @since 3.0
	 */
	public static void performValueHandlerEvent(IConfiguration config, int event) {
		performValueHandlerEvent(config, event, true);
	}

	/**
	 * Send event to value handlers of relevant configuration.
	 *
	 * @param config configuration for which to send the event
	 * @param event to be sent
	 * @param doChildren - if true, also perform the event for all
	 *        resource configurations that are children if this configuration.
	 *
	 * @since 3.0
	 */
	public static void performValueHandlerEvent(IConfiguration config, int event, boolean doChildren) {

		IToolChain toolChain = config.getToolChain();
		if (toolChain == null)
			return;

		IOption[] options = toolChain.getOptions();
		// Get global options directly under Toolchain (not associated with a particular tool)
		// This has to be sent to all the Options associated with this configuration.
		for (IOption option : options) {
			// Ignore invalid options
			if (option.isValid()) {
				// Call the handler
				if (option.getValueHandler().handleValue(
						config,
						toolChain,
						option,
						option.getValueHandlerExtraArgument(),
						event)) {
					// TODO : Event is handled successfully and returned true.
					// May need to do something here say logging a message.
				} else {
					// Event handling Failed.
				}
			}
		}

		// Get options associated with tools under toolChain
		ITool[] tools = config.getFilteredTools();
		for (ITool tool : tools) {
			IOption[] toolOptions = tool.getOptions();
			for (IOption toolOption : toolOptions) {
				// Ignore invalid options
				if (toolOption.isValid()) {
					// Call the handler
					if (toolOption.getValueHandler().handleValue(
							config,
							tool,
							toolOption,
							toolOption.getValueHandlerExtraArgument(),
							event)) {
						// TODO : Event is handled successfully and returned true.
						// May need to do something here say logging a message.
					} else {
						// Event handling Failed.
					}
				}
			}
		}

		// Call backs for Resource Configurations associated with this config.
		if (doChildren == true) {
			IResourceConfiguration[] resConfigs = config.getResourceConfigurations();
			for (IResourceConfiguration resConfig : resConfigs) {
				ManagedBuildManager.performValueHandlerEvent(resConfig, event);
			}
		}
	}

	/**
	 * Send event to value handlers of relevant configuration.
	 *
	 * @param config configuration for which to send the event
	 * @param event to be sent
	 *
	 * @since 3.0
	 */
	public static void performValueHandlerEvent(IResourceInfo config, int event) {

		// Note: Resource configurations have no toolchain options

		// Get options associated with the resource configuration
		ITool[] tools = config instanceof IFileInfo ?
				((IFileInfo)config).getToolsToInvoke() :
					((IFolderInfo)config).getFilteredTools();
		for (ITool tool : tools) {
			IOption[] toolOptions = tool.getOptions();
			for (IOption toolOption : toolOptions) {
				// Ignore invalid options
				if (toolOption.isValid()) {
					// Call the handler
					if (toolOption.getValueHandler().handleValue(
							config,
							tool,
							toolOption,
							toolOption.getValueHandlerExtraArgument(),
							event)) {
						// TODO : Event is handled successfully and returned true.
						// May need to do something here say logging a message.
					} else {
						// Event handling Failed.
					}
				}
			}
		}
	}

	private static boolean checkForMigrationSupport(ManagedBuildInfo buildInfo,
			boolean forCurrentMbsVersion) {

		IConfigurationElement element = null;

		// Get the managed project from buildInfo
		IManagedProject managedProject = buildInfo.getManagedProject();

		IProjectType projectType = managedProject.getProjectType();
		if (forCurrentMbsVersion) {
			element = ((ProjectType) projectType)
					.getCurrentMbsVersionConversionElement();
		} else {
			element = ((ProjectType) projectType)
					.getPreviousMbsVersionConversionElement();
		}

		if (element != null) {
			// If there is a converter element for projectType, invoke it.
			// projectType converter should take care of invoking converters of
			// it's children

			if (invokeConverter(buildInfo, managedProject, element) == null) {
				buildInfo.getManagedProject().setValid(false);
				return false;
			}
		} else {
			// other wise, walk through the hierarchy of the project and
			// call the converters if available for each configuration
			IConfiguration[] configs = managedProject.getConfigurations();
			for (IConfiguration configuration : configs) {
				IToolChain toolChain = configuration.getToolChain();

				if (forCurrentMbsVersion) {
					element = ((ToolChain) toolChain)
							.getCurrentMbsVersionConversionElement();
				} else {
					element = ((ToolChain) toolChain)
							.getPreviousMbsVersionConversionElement();
				}

				if (element != null) {
					// If there is a converter element for toolChain, invoke it
					// toolChain converter should take care of invoking
					// converters of it's children
					if (invokeConverter(buildInfo, toolChain, element) == null) {
						buildInfo.getManagedProject().setValid(false);
						return false;
					}
				} else {
					// If there are no converters for toolChain, walk through
					// it's children
					ITool[] tools = toolChain.getTools();
					for (ITool tool : tools) {
						if (forCurrentMbsVersion) {
							element = ((Tool) tool)
									.getCurrentMbsVersionConversionElement();
						} else {
							element = ((Tool) tool)
									.getPreviousMbsVersionConversionElement();
						}
						if (element != null) {
							if (invokeConverter(buildInfo, tool, element) == null) {
								buildInfo.getManagedProject().setValid(false);
								return false;
							}
						}
					}
					IBuilder builder = toolChain.getBuilder();
					if (builder != null) {
						if (forCurrentMbsVersion) {
							element = ((Builder) builder)
									.getCurrentMbsVersionConversionElement();
						} else {
							element = ((Builder) builder)
									.getPreviousMbsVersionConversionElement();
						}

						if (element != null) {
							if (invokeConverter(buildInfo, builder, element) == null) {
								buildInfo.getManagedProject().setValid(false);
								return false;
							}
						}
					}
				}

				// walk through each resource configuration and look if there
				// are any converters
				// available. If so, invoke them.
				IResourceConfiguration[] resourceConfigs = configuration
						.getResourceConfigurations();
				if ((resourceConfigs != null) && (resourceConfigs.length > 0)) {
					for (IResourceConfiguration resConfig : resourceConfigs) {
						ITool[] resTools = resConfig.getTools();
						for (ITool resTool : resTools) {
							if (forCurrentMbsVersion) {
								element = ((Tool) resTool)
										.getCurrentMbsVersionConversionElement();
							} else {
								element = ((Tool) resTool)
										.getPreviousMbsVersionConversionElement();
							}
							if (element != null) {
								if (invokeConverter(buildInfo, resTool, element) == null) {
									buildInfo.getManagedProject().setValid(
											false);
									return false;
								}
							}
						}
					}
				} // end of if
			}
		}
		// If control comes here, it means either there is no converter element
		// or converters are invoked successfully

		return true;
	}

	private static IBuildObject invokeConverter(ManagedBuildInfo bi, IBuildObject buildObject, IConfigurationElement element) {

		if (element != null) {
			IConvertManagedBuildObject convertBuildObject = null;
			String toId = element.getAttribute("toId"); //$NON-NLS-1$
			String fromId = element.getAttribute("fromId"); //$NON-NLS-1$

			try {
				convertBuildObject = (IConvertManagedBuildObject) element
						.createExecutableExtension("class"); //$NON-NLS-1$
			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (convertBuildObject != null) {
				// invoke the converter
				IProject prj = null;
				IBuildObject result = null;
				try {
					if (bi != null) {
						prj = (IProject)bi.getManagedProject().getOwner();
						UpdateManagedProjectManager.addInfo(prj, bi);
					}
					result = convertBuildObject.convert(buildObject, fromId, toId, false);
				} finally {
					if (bi != null)
						UpdateManagedProjectManager.delInfo(prj);
				}
				return result;
			}
		}
		// if control comes here, it means that either 'convertBuildObject' is null or
		// converter did not convert the object successfully
		return null;
	}

	/*
	 * Generic Converter function.
	 * If the converter is available for the given Build Object, it calls the corresponding converter.
	 * It returns null if there are no converters or if the conversion is not successful
	 * It returns 'IBuildObject' if the conversion is successful.
	 */

	public static IBuildObject convert(IBuildObject buildObj, String toId,
			boolean userhasConfirmed) {

		String tmpToId = null;

		// Get the Converter Extension Point
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
				.getExtensionPoint("org.eclipse.cdt.managedbuilder.core", //$NON-NLS-1$
						"projectConverter"); //$NON-NLS-1$
		if (extensionPoint != null) {
			// Get the extensions
			IExtension[] extensions = extensionPoint.getExtensions();
			for (IExtension extension : extensions) {
				// Get the configuration elements of each extension
				IConfigurationElement[] configElements = extension
						.getConfigurationElements();
				for (IConfigurationElement element : configElements) {

					if (element.getName().equals("converter") && (isBuildObjectApplicableForConversion(buildObj, element) == true)) { //$NON-NLS-1$
						tmpToId = element.getAttribute("toId");	//$NON-NLS-1$
						if (tmpToId.equals(toId)) {
							return invokeConverter(null, buildObj, element);
						}
					}
				}
			}
		}
		return null;
	}

	/**
	 * Generic routine for checking the availability of converters for the given
	 * Build Object.
	 *
	 * @return true if there are converters for the given Build Object.
	 * Returns false if there are no converters.
	 */
	public static boolean hasTargetConversionElements(IBuildObject buildObj) {

		// Get the Converter Extension Point
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
				.getExtensionPoint("org.eclipse.cdt.managedbuilder.core", //$NON-NLS-1$
						"projectConverter"); //$NON-NLS-1$
		if (extensionPoint != null) {
			// Get the extensions
			IExtension[] extensions = extensionPoint.getExtensions();
			for (IExtension extension : extensions) {
				// Get the configuration elements of each extension
				IConfigurationElement[] configElements = extension.getConfigurationElements();
				for (IConfigurationElement element : configElements) {
					if (element.getName().equals("converter") && (isBuildObjectApplicableForConversion(buildObj, element) == true)) //$NON-NLS-1$
						return true;
				}
			}
		}
		return false;
	}

	/*
	 * Generic function for getting the list of converters for the given Build Object
	 */

	public static Map<String, IConfigurationElement> getConversionElements(IBuildObject buildObj) {

		Map<String, IConfigurationElement> conversionTargets = new HashMap<String, IConfigurationElement>();

		// Get the Converter Extension Point
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
				.getExtensionPoint("org.eclipse.cdt.managedbuilder.core", //$NON-NLS-1$
						"projectConverter"); //$NON-NLS-1$
		if (extensionPoint != null) {
			// Get the extensions
			IExtension[] extensions = extensionPoint.getExtensions();
			for (IExtension extension : extensions) {
				// Get the configuration elements of each extension
				IConfigurationElement[] configElements = extension.getConfigurationElements();
				for (IConfigurationElement element : configElements) {
					if (element.getName().equals("converter") && (isBuildObjectApplicableForConversion(buildObj, element) == true)) { //$NON-NLS-1$
						conversionTargets.put(element.getAttribute("name"), element); //$NON-NLS-1$
					}
				}
			}
		}
		return conversionTargets;
	}

	/*
	 * Generic function that checks whether the given conversion element can be used to convert the given
	 * build object. It returns true if the given build object is convertable, otherwise it returns false.
	 */

	private static boolean isBuildObjectApplicableForConversion(
			IBuildObject buildObj, IConfigurationElement element) {

		String id = null;
		String fromId = element.getAttribute("fromId"); //$NON-NLS-1$

		// Check whether the current converter can be used for conversion

		if (buildObj instanceof IProjectType) {
			IProjectType projType = (IProjectType) buildObj;

			// Check whether the converter's 'fromId' and the
			// given projType 'id' are equal
			while (projType != null) {
				id = projType.getId();

				if (fromId.equals(id)) {
					return true;
				}
				projType = projType.getSuperClass();
			}
		} else if (buildObj instanceof IToolChain) {
			IToolChain toolChain = (IToolChain) buildObj;

			// Check whether the converter's 'fromId' and the
			// given toolChain 'id' are equal
			while (toolChain != null) {
				id = toolChain.getId();

				if (fromId.equals(id)) {
					return true;
				}
				toolChain = toolChain.getSuperClass();
			}
		} else if (buildObj instanceof ITool) {
			ITool tool = (ITool) buildObj;

			// Check whether the converter's 'fromId' and the
			// given tool 'id' are equal
			while (tool != null) {
				id = tool.getId();

				if (fromId.equals(id)) {
					return true;
				}
				tool = tool.getSuperClass();
			}
		} else if (buildObj instanceof IBuilder) {
			IBuilder builder = (IBuilder) buildObj;

			// Check whether the converter's 'fromId' and the
			// given builder 'id' are equal
			while (builder != null) {
				id = builder.getId();

				if (fromId.equals(id)) {
					return true;
				}
				builder = builder.getSuperClass();
			}
		}
		return false;
	}

	/*
	 * if the suffix is null, then the random number will be appended to the superId
	 */
	static public String calculateChildId(String superId, String suffix){
		if(suffix == null)
			suffix = new Integer(getRandomNumber()).toString();

		String version = getVersionFromIdAndVersion(superId);
        if(version != null)
            return ManagedBuildManager.getIdFromIdAndVersion(superId) + "." + suffix + "_" + version;             //$NON-NLS-1$ //$NON-NLS-2$
        return superId + "." + suffix;                     //$NON-NLS-1$
	}


	private static int isInt(String s) {
		try {
			return Integer.parseInt(s);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	/**
	 * @return base id when the given id was generated by {@link #calculateChildId(String, String)}.
	 * @since 8.0
	 */
	public static String calculateBaseId(String id) {
		int index = id.lastIndexOf('.');
		if (index<0)
			return id;

		String lastSeg = id.substring(index+1,id.length());
		if (isInt(lastSeg)>0) {
			String baseId = id.substring(0,index);
			return baseId;
		}
		return getIdFromIdAndVersion(id);
	}

	/**
	 * @return calculated relative path given the full path to a folder and a file
	 */
	public static IPath calculateRelativePath(IPath container, IPath contents){
		IPath path = contents;
		if(container.isPrefixOf(contents)){
			path = contents.setDevice(null).removeFirstSegments(container.segmentCount());
		} else {
			String file = null;
			container = container.addTrailingSeparator();
			if(!contents.hasTrailingSeparator()){
				file = contents.lastSegment();
				contents = contents.removeLastSegments(1);
				contents = contents.addTrailingSeparator();
			}

			IPath prefix = contents;
			for(;prefix.segmentCount() > 0 && !prefix.isPrefixOf(container);prefix = prefix.removeLastSegments(1)){
			}
			if(prefix.segmentCount() > 0){
				int diff = container.segmentCount() - prefix.segmentCount();
				StringBuffer buff = new StringBuffer();
				while(diff-- > 0)
					buff.append("../");	//$NON-NLS-1$
				path = new Path(buff.toString()).append(contents.removeFirstSegments(prefix.segmentCount()));
				if(file != null)
					path = path.append(file);
			}
		}
		return path;
	}

/*	private static IBuildObject getBuildObjectFromDataObject(CDataObject data){
		if(data instanceof BuildConfigurationData)
			return ((BuildConfigurationData)data).getConfiguration();
		else if(data instanceof BuildFolderData)
			return ((BuildFolderData)data).getFolderInfo();
		else if(data instanceof BuildFileData)
			return ((BuildFileData)data).getFileInfo();
		return null;
	}
*/
	private static final boolean TEST_CONSISTENCE = false;

	public static IConfiguration getConfigurationForDescription(ICConfigurationDescription cfgDes){
		return getConfigurationForDescription(cfgDes, TEST_CONSISTENCE);
	}

	private static IConfiguration getConfigurationForDescription(ICConfigurationDescription cfgDes, boolean checkConsistance){
		if(cfgDes == null)
			return null;

		if (cfgDes instanceof ICMultiConfigDescription) {
			ICMultiConfigDescription mcd = (ICMultiConfigDescription)cfgDes;
			ICConfigurationDescription[] cfds = (ICConfigurationDescription[])mcd.getItems();
			return new MultiConfiguration(cfds);
		}

		CConfigurationData cfgData = cfgDes.getConfigurationData();
		if(cfgData instanceof BuildConfigurationData){
			IConfiguration cfg = ((BuildConfigurationData)cfgData).getConfiguration();
			if(checkConsistance){
				if(cfgDes != getDescriptionForConfiguration(cfg, false)){
					throw new IllegalStateException();
				}
			}
			return cfg;
		}
		return null;
	}

	/**
	 * Convert the IOption integer type ID to the {@link ICSettingEntry#getKind()} type ID
	 * @param type {@link IOption#getValueType()}
	 * @return ICSettingEntry type
	 */
	public static int optionTypeToEntryKind(int type){
		switch(type){
		case IOption.INCLUDE_PATH:
			return ICSettingEntry.INCLUDE_PATH;
		case IOption.PREPROCESSOR_SYMBOLS:
			return ICSettingEntry.MACRO;
		case IOption.INCLUDE_FILES:
			return ICSettingEntry.INCLUDE_FILE;
		case IOption.LIBRARY_PATHS:
			return ICSettingEntry.LIBRARY_PATH;
		case IOption.LIBRARIES:
		case IOption.LIBRARY_FILES:
			return ICSettingEntry.LIBRARY_FILE;
		case IOption.MACRO_FILES:
			return ICSettingEntry.MACRO_FILE;
		}
		return 0;
	}

	/**
	 * Convert the IOption integer type ID to the {@link ICSettingEntry#getKind()} type ID
	 * @param type {@link IOption#getValueType()}
	 * @return ICSettingEntry type
	 */
	public static int optionUndefTypeToEntryKind(int type){
		switch(type){
		case IOption.UNDEF_INCLUDE_PATH:
			return ICSettingEntry.INCLUDE_PATH;
		case IOption.UNDEF_PREPROCESSOR_SYMBOLS:
			return ICSettingEntry.MACRO;
		case IOption.UNDEF_INCLUDE_FILES:
			return ICSettingEntry.INCLUDE_FILE;
		case IOption.UNDEF_LIBRARY_PATHS:
			return ICSettingEntry.LIBRARY_PATH;
		case IOption.UNDEF_LIBRARY_FILES:
			return ICSettingEntry.LIBRARY_FILE;
		case IOption.UNDEF_MACRO_FILES:
			return ICSettingEntry.MACRO_FILE;
		}
		return 0;
	}

	public static int entryKindToOptionType(int kind){
		switch(kind){
		case ICSettingEntry.INCLUDE_PATH:
			return IOption.INCLUDE_PATH;
		case ICSettingEntry.INCLUDE_FILE:
			return IOption.INCLUDE_FILES;
		case ICSettingEntry.MACRO:
			return IOption.PREPROCESSOR_SYMBOLS;
		case ICSettingEntry.MACRO_FILE:
			return IOption.MACRO_FILES;
		case ICSettingEntry.LIBRARY_PATH:
			return IOption.LIBRARY_PATHS;//TODO IOption.LIBRARIES;
		case ICSettingEntry.LIBRARY_FILE:
			return IOption.LIBRARY_FILES;
		}
		return 0;
	}

	public static int entryKindToUndefOptionType(int kind){
		switch(kind){
		case ICSettingEntry.INCLUDE_PATH:
			return IOption.UNDEF_INCLUDE_PATH;
		case ICSettingEntry.INCLUDE_FILE:
			return IOption.UNDEF_INCLUDE_FILES;
		case ICSettingEntry.MACRO:
			return IOption.UNDEF_PREPROCESSOR_SYMBOLS;
		case ICSettingEntry.MACRO_FILE:
			return IOption.UNDEF_MACRO_FILES;
		case ICSettingEntry.LIBRARY_PATH:
			return IOption.UNDEF_LIBRARY_PATHS;//TODO IOption.LIBRARIES;
		case ICSettingEntry.LIBRARY_FILE:
			return IOption.UNDEF_LIBRARY_FILES;
		}
		return 0;
	}
	public static ICConfigurationDescription getDescriptionForConfiguration(IConfiguration cfg){
		return getDescriptionForConfiguration(cfg, TEST_CONSISTENCE);
	}

	private static ICConfigurationDescription getDescriptionForConfiguration(IConfiguration cfg, boolean checkConsistance){
		if(cfg.isExtensionElement())
			return null;
		ICConfigurationDescription des = ((Configuration)cfg).getConfigurationDescription();
		if(des == null){
			if(checkConsistance)
				throw new IllegalStateException();
			if(((Configuration)cfg).isPreference()){
				try {
					des = CCorePlugin.getDefault().getPreferenceConfiguration(CFG_DATA_PROVIDER_ID);
				} catch (CoreException e) {
					ManagedBuilderCorePlugin.log(e);
				}
			} else {
				IProject project = cfg.getOwner().getProject();
				ICProjectDescription projDes = CoreModel.getDefault().getProjectDescription(project, false);
				if(projDes != null){
					des = projDes.getConfigurationById(cfg.getId());
				}
			}
		}
		if(checkConsistance){
			if(cfg != getConfigurationForDescription(des, false)){
				throw new IllegalStateException();
			}
		}
		return des;
	}

	public static IPath getBuildFullPath(IConfiguration cfg, IBuilder builder){
		IProject project = cfg.getOwner().getProject();
//		String path = builder.getBuildPath();

		IPath buildDirectory = builder.getBuildLocation();
		IPath fullPath = null;
		if (buildDirectory != null && !buildDirectory.isEmpty()) {
			IResource res = project.getParent().findMember(buildDirectory);
			if (res instanceof IContainer && res.exists()) {
				fullPath = res.getFullPath();
			} else {
				IContainer crs[] = ((IWorkspaceRoot)project.getParent()).findContainersForLocation(buildDirectory);
				if(crs.length != 0){
					String projName = project.getName();
					for (IContainer cr : crs) {
						IPath path = cr.getFullPath();
						if(path.segmentCount() != 0 && path.segment(0).equals(projName)){
							fullPath = path;
							break;
						}
					}

					if(fullPath == null){
						fullPath = crs[0].getFullPath();
					}
				}
			}
		} else {
			fullPath = cfg.getOwner().getProject().getFullPath();
			if(builder.isManagedBuildOn())
				fullPath = fullPath.append(cfg.getName());
		}

		return fullPath;
	}

	/**
	 * Returns a string representing the workspace relative path with ${workspace_loc: stripped
	 * or null if the String path doesn't contain workspace_log
	 * @param path String path to have workspace_loc removed
	 * @return workspace path or null
	 */
	public static String locationToFullPath(String path){
		path = path.trim();
		if(!path.startsWith("${"))  //$NON-NLS-1$
			return null;
		final int index = path.lastIndexOf('}');
		if(index == -1)
			return null;

		String varName = "workspace_loc"; //$NON-NLS-1$
		String str1 = path.substring(2, index);
		String result = null;
		if(str1.startsWith(varName)){
			str1 = str1.substring(varName.length());
			if(str1.length() != 0){
				if(str1.startsWith(":")){ //$NON-NLS-1$
					result = str1.substring(1);
				}
			} else {
				result = "/"; //$NON-NLS-1$
			}
			// If the user has a path like ${workspace_loc:/thing}/other/thing
			// ensure we return /thing/other/thing
			if (index < path.length() - 1)
				result += path.substring(index + 1);
		}

		return result;
	}

	public static String fullPathToLocation(String path){
		StringBuffer buf = new StringBuffer();
		return buf.append("${").append("workspace_loc:").append(path).append("}").toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	public static IPath getBuildLocation(IConfiguration cfg, IBuilder builder) {
		if(cfg.getOwner() == null)
			return Path.EMPTY;

		IProject project = cfg.getOwner().getProject();
		IPath buildDirectory = builder.getBuildLocation();
		if (buildDirectory != null && !buildDirectory.isEmpty()) {
			IResource res = project.getParent().findMember(buildDirectory);
			if (res instanceof IContainer && res.exists()) {
				buildDirectory = res.getLocation();
			}
		} else {
			buildDirectory = getPathForResource(project);

			if (buildDirectory != null) {
				if (builder.isManagedBuildOn())
					buildDirectory = buildDirectory.append(cfg.getName());
			}
		}
		return buildDirectory;
	}

	/**
	 * @return build location URI or null if one couldn't be found
	 * @since 6.0
	 */
	public static URI getBuildLocationURI(IConfiguration cfg, IBuilder builder) {
		if(cfg.getOwner() == null)
			return null;

		IProject project = cfg.getOwner().getProject();
		IPath buildDirectory = builder.getBuildLocation();
		if (buildDirectory != null && !buildDirectory.isEmpty()) {
			IResource res = project.getParent().findMember(buildDirectory);
			if (res instanceof IContainer && res.exists()) {
				return res.getLocationURI();
			}
		} else {
			URI uri = project.getLocationURI();
			if (buildDirectory != null && builder.isManagedBuildOn())
				return URIUtil.append(uri, cfg.getName());
			return uri;
		}
		return org.eclipse.core.filesystem.URIUtil.toURI(buildDirectory);
	}

	private static IPath getPathForResource(IResource resource) {
		URI uri = resource.getLocationURI();
		return new Path(uri.getPath());
	}

	public static IBuilder[] createBuilders(IProject project, Map<String, String> args){
		return ManagedBuilderCorePlugin.createBuilders(project, args);
	}

	public static IBuilder createCustomBuilder(IConfiguration cfg, String builderId) throws CoreException{
		return ManagedBuilderCorePlugin.createCustomBuilder(cfg, builderId);
	}

	public static IBuilder createCustomBuilder(IConfiguration cfg, IBuilder base){
		return ManagedBuilderCorePlugin.createCustomBuilder(cfg, base);
	}

	public static IBuilder createBuilderForEclipseBuilder(IConfiguration cfg, String eclipseBuilderID) throws CoreException {
		return ManagedBuilderCorePlugin.createBuilderForEclipseBuilder(cfg, eclipseBuilderID);
	}

/*	public static IToolChain[] getExtensionsToolChains(String propertyType, String propertyValue){
		List all = getSortedToolChains();
		List result = new ArrayList();
		for(int i = 0; i < all.size(); i++){
			List list = (List)all.get(i);
			IToolChain tc = findToolChain(list, propertyType, propertyValue);
			if(tc != null)
				result.add(tc);
		}
		return (IToolChain[])result.toArray(new ToolChain[result.size()]);
	}
*/
/*	public static void resortToolChains(){
		sortedToolChains = null;
		getSortedToolChains();
	}
*/
/*	private static List getSortedToolChains(){
		if(sortedToolChains == null){
			sortedToolChains = new ArrayList();
			SortedMap map = getExtensionToolChainMapInternal();
			for(Iterator iter = map.values().iterator(); iter.hasNext();){
				ToolChain tc = (ToolChain)iter.next();
				if(tc.isAbstract())
					continue;
				List list = searchIdentical(sortedToolChains, tc);
				if(list == null){
					list = new ArrayList();
					sortedToolChains.add(list);
				}
				list.add(tc);
				tc.setIdenticalList(list);
			}
		}
		return sortedToolChains;
	}
*/
//	private static List findIdenticalToolChains(IToolChain tc){
//		ToolChain tCh = (ToolChain)tc;
//		List list = tCh.getIdenticalList();
//		if(list == null){
//			resortToolChains();
//			list = tCh.getIdenticalList();
//			if(list == null){
//				list = new ArrayList(0);
//				tCh.setIdenticalList(list);
//			}
//		}
//
//		return ((ToolChain)tc).getIdenticalList();
//	}

	public static IToolChain[] getExtensionToolChains(IProjectType type){
		List<IToolChain> result = new ArrayList<IToolChain>();
		IConfiguration cfgs[] = type.getConfigurations();

		for (IConfiguration cfg : cfgs) {
			IToolChain tc = cfg.getToolChain();
			if(tc == null)
				continue;

			List<ToolChain> list = findIdenticalElements((ToolChain)tc, fToolChainSorter);
			int k = 0;
			for(; k < result.size(); k++){
				if(findIdenticalElements((ToolChain)result.get(k), fToolChainSorter) == list)
					break;
			}

			if(k == result.size()){
				result.add(tc);
			}
		}
		return result.toArray(new IToolChain[result.size()]);
	}

	public static IConfiguration[] getExtensionConfigurations(IToolChain tChain, IProjectType type){
		List<IConfiguration> list = new ArrayList<IConfiguration>();
		IConfiguration cfgs[] = type.getConfigurations();
		for (IConfiguration cfg : cfgs) {
			IToolChain cur = cfg.getToolChain();
			if(cur != null
					&& findIdenticalElements((ToolChain)cur, fToolChainSorter) == findIdenticalElements((ToolChain)tChain, fToolChainSorter)){
				list.add(cfg);
			}
		}
		return list.toArray(new Configuration[list.size()]);
	}

	public static IConfiguration getFirstExtensionConfiguration(IToolChain tChain){
		if(tChain.getParent() != null)
			return tChain.getParent();

		List<ToolChain> list = findIdenticalElements((ToolChain)tChain, fToolChainSorter);
		if(list != null){
			for(int i = 0; i < list.size(); i++){
				ToolChain cur = list.get(i);
				if(cur.getParent() != null)
					return cur.getParent();
			}
		}

		return null;
	}

	public static IConfiguration[] getExtensionConfigurations(IToolChain tChain, String propertyType, String propertyValue){
//		List all = getSortedToolChains();
		List<ToolChain> list = findIdenticalElements((ToolChain)tChain, fToolChainSorter);
		LinkedHashSet<IConfiguration> result = new LinkedHashSet<IConfiguration>();
		boolean tcFound = false;
		if(list != null){
			for(int i = 0; i < list.size(); i++){
				ToolChain cur = list.get(i);
				if(cur == tChain){
					tcFound = true;
				}

				IConfiguration cfg = cur.getParent();
				if(cfg != null){
					IBuildObjectProperties props = cfg.getBuildProperties();
					if(props.containsValue(propertyType, propertyValue)){
						result.add(cfg);
					}
				}
			}

		}

		if(!tcFound) {
			IConfiguration cfg = tChain.getParent();
			if(cfg != null){
				IBuildObjectProperties props = cfg.getBuildProperties();
				if(props.containsValue(propertyType, propertyValue)){
					result.add(cfg);
				}
			}
		}

//		if(result.size() == 0){
//			if(((ToolChain)tChain).supportsValue(propertyType, propertyValue)){
//				IConfiguration cfg = getFirstExtensionConfiguration(tChain);
//				if(cfg != null){
//					result.add(cfg);
//				}
//			}
//		}
		return result.toArray(new IConfiguration[result.size()]);
	}

/*	public static IToolChain[] getRealToolChains(){
		List all = getSortedToolChains();
		IToolChain tcs[] = new ToolChain[all.size()];
		for(int i = 0; i < tcs.length; i++){
			List list = (List)all.get(i);
			tcs[i] = (ToolChain)list.get(0);
		}
		return tcs;
	}
*/

	private static HashMap<MatchKey<ToolChain>, List<ToolChain>> getSortedToolChains(){
		if(fSortedToolChains == null){
			Collection<ToolChain> toolChains = getExtensionToolChainMapInternal().values();
			fSortedToolChains = getSortedElements(toolChains);
		}
		return fSortedToolChains;
	}

	private static HashMap<MatchKey<Tool>, List<Tool>> getSortedTools(){
		if(fSortedTools == null){
			Collection<Tool> tools = getExtensionToolMapInternal().values();
			fSortedTools = getSortedElements(tools);
		}
		return fSortedTools;
	}

	private static HashMap<MatchKey<Builder>, List<Builder>> getSortedBuilders(){
		if(fSortedBuilders == null){
			Collection<Builder> builders = getExtensionBuilderMapInternal().values();
			fSortedBuilders = getSortedElements(builders);
		}
		return fSortedBuilders;
	}

	private static <T extends BuildObject & IMatchKeyProvider<T>> HashMap<MatchKey<T>, List<T>> getSortedElements(Collection<T> elements){
		HashMap<MatchKey<T>, List<T>> map = new HashMap<MatchKey<T>, List<T>>();
		for (T p : elements) {
			MatchKey<T> key = p.getMatchKey();
			if(key == null)
				continue;

			List<T> list = map.get(key);
			if(list == null){
				list = new ArrayList<T>();
				map.put(key, list);
			}
			list.add(p);
			p.setIdenticalList(list);
		}

		Collection<List<T>> values = map.values();
		for (List<T> list : values) {
			Collections.sort(list);
		}
		return map;
	}

	public static IToolChain[] getRealToolChains(){
		HashMap<MatchKey<ToolChain>, List<ToolChain>> map = getSortedToolChains();
		IToolChain tcs[] = new ToolChain[map.size()];
		int i = 0;
		for (List<ToolChain> list : map.values()) {
			tcs[i++] = list.get(0);
		}
		return tcs;
	}

	public static ITool[] getRealTools(){
		HashMap<MatchKey<Tool>, List<Tool>> map = getSortedTools();
		Tool ts[] = new Tool[map.size()];
		int i = 0;
		for (List<Tool> list : map.values()) {
			ts[i++] = list.get(0);
		}
		return ts;
	}

	public static IBuilder[] getRealBuilders(){
		HashMap<MatchKey<Builder>, List<Builder>> map = getSortedBuilders();
		IBuilder bs[] = new Builder[map.size()];
		int i = 0;
		for (List<Builder> list : map.values()) {
			bs[i++] = list.get(0);
		}
		return bs;
	}

	public static IBuilder getRealBuilder(IBuilder builder){
		IBuilder extBuilder = builder;
		IBuilder realBuilder = null;
		for(;extBuilder != null && !extBuilder.isExtensionElement(); extBuilder = extBuilder.getSuperClass()) {
			// empty body
		}

		if(extBuilder != null){
			List<Builder> list = findIdenticalElements((Builder)extBuilder, fBuilderSorter);
			if(list.size() == 0){
				realBuilder = extBuilder;
			} else {
				for (IBuilder realBldr : getRealBuilders()) {
					List<Builder> rList = findIdenticalElements((Builder)realBldr, fBuilderSorter);
					if(rList == list){
						realBuilder = realBldr;
						break;
					}
				}
			}
		} else {
			//TODO:
		}
		return realBuilder;
	}

	public static ITool getRealTool(ITool tool){
		if(tool == null)
			return null;
		ITool extTool = tool;
		ITool realTool = null;
		for(;extTool != null && !extTool.isExtensionElement(); extTool= extTool.getSuperClass()) {
			// empty body
		}

		if(extTool != null){
			List<Tool> list = findIdenticalElements((Tool)extTool, fToolSorter);
			if(list.size() == 0){
				realTool = extTool;
			} else {
				for (ITool realT : getRealTools()) {
					List<Tool> rList = findIdenticalElements((Tool)realT, fToolSorter);
					if(rList == list){
						realTool = realT;
						break;
					}
				}
			}
		} else {
			realTool = getExtensionTool(Tool.DEFAULT_TOOL_ID);
		}
		return realTool;
	}

	public static IToolChain getExtensionToolChain(IToolChain tc){
		IToolChain extTc = tc;
		for(;extTc != null && !extTc.isExtensionElement(); extTc= extTc.getSuperClass()) {
			// empty body
		}
		return extTc;
	}

	public static IToolChain getRealToolChain(IToolChain tc){
		IToolChain extTc = tc;
		IToolChain realToolChain = null;
		for(;extTc != null && !extTc.isExtensionElement(); extTc= extTc.getSuperClass()) {
			// empty body
		}

		if(extTc != null){
			List<ToolChain> list = findIdenticalElements((ToolChain)extTc, fToolChainSorter);
			if(list.size() == 0){
				realToolChain = extTc;
			} else {
				for (IToolChain realTc : getRealToolChains()) {
					List<ToolChain> rList = findIdenticalElements((ToolChain)realTc, fToolChainSorter);
					if(rList == list){
						realToolChain = realTc;
						break;
					}
				}
			}
		} else {
			//TODO:
		}
		return realToolChain;
	}

	public static IToolChain[] findIdenticalToolChains(IToolChain tc){
		List<ToolChain> list = findIdenticalElements((ToolChain)tc, fToolChainSorter);
		return list.toArray(new ToolChain[list.size()]);
	}

	public static ITool[] findIdenticalTools(ITool tool){
		List<Tool> list = findIdenticalElements((Tool)tool, fToolSorter);
		return list.toArray(new Tool[list.size()]);
	}

	public static IBuilder[] findIdenticalBuilders(IBuilder b){
		List<Builder> list = findIdenticalElements((Builder)b, fBuilderSorter);
		return list.toArray(new Builder[list.size()]);
	}

	public static IToolChain[] getExtensionsToolChains(String propertyType, String propertyValue){
		return getExtensionsToolChains(propertyType, propertyValue, true);
	}

	public static IToolChain[] getExtensionsToolChains(String propertyType, String propertyValue, boolean supportedPropsOnly){
		HashMap<MatchKey<ToolChain>, List<ToolChain>> all = getSortedToolChains();
		List<IToolChain> result = new ArrayList<IToolChain>();
		for (List<ToolChain> list : all.values()) {
			IToolChain tc = findToolChain(list, propertyType, propertyValue, supportedPropsOnly);
			if(tc != null)
				result.add(tc);
		}
		return result.toArray(new ToolChain[result.size()]);
	}

	public static void resortToolChains(){
		fSortedToolChains = null;
		getSortedToolChains();
	}

	public static void resortTools(){
		fSortedTools = null;
		getSortedTools();
	}

	public static void resortBuilders(){
		fSortedBuilders = null;
		getSortedBuilders();
	}

	private static IToolChain findToolChain(List<ToolChain> list, String propertyType, String propertyValue, boolean supportedOnly){
		ToolChain bestMatch = null;
		IConfiguration cfg = null;
		IProjectType type = null;
		boolean valueSupported = false;

		for(int i = 0; i < list.size(); i++){
			ToolChain tc = list.get(i);
			if(tc.supportsValue(propertyType, propertyValue)){
				valueSupported = true;
			} else if (valueSupported){
				continue;
			}

			if(!tc.supportsBuild(true))
				return null;

			if(bestMatch == null && valueSupported)
				bestMatch = tc;

			IConfiguration tcCfg = tc.getParent();
			if(tcCfg != null){
				if(cfg == null && valueSupported){
					bestMatch = tc;
					cfg = tcCfg;
				}

				IBuildObjectProperties props =tcCfg.getBuildProperties();
				IBuildProperty prop = props.getProperty(propertyType);
				if(valueSupported && prop != null && propertyValue.equals(prop.getValue().getId())){
					bestMatch = tc;
					cfg = tcCfg;
				}

				IProjectType tcType = tcCfg.getProjectType();
				if(tcType != null){
					if(type == null && valueSupported){
						type = tcType;
						bestMatch = tc;
					}
					props = tcType.getBuildProperties();
					prop = props.getProperty(propertyType);
					if(prop != null && propertyValue.equals(prop.getValue().getId())){
						bestMatch = tc;
						if(valueSupported){
							type = tcType;
							break;
						}
					}
				}
			}
		}

		if(valueSupported || ! supportedOnly)
			return bestMatch;
		return null;
	}

	private static <T extends BuildObject & IMatchKeyProvider<T>> List<T> findIdenticalElements(T p, ISorter sorter){
		List<T> list = p.getIdenticalList();
		if(list == null){
			sorter.sort();
			list = p.getIdenticalList();
			if(list == null){
				list = new ArrayList<T>(0);
				p.setIdenticalList(list);
			}
		}

		return list;
	}



	public static IBuildPropertyManager getBuildPropertyManager(){
		return BuildPropertyManager.getInstance();
	}

	/**
	 * Returns the configurations referenced by this configuration.
	 * Returns an empty array if there are no referenced configurations.
	 *
	 * @see CoreModelUtil#getReferencedConfigurationDescriptions(ICConfigurationDescription, boolean)
	 * @return an array of IConfiguration objects referenced by this IConfiguration
	 */
	public static IConfiguration[] getReferencedConfigurations(IConfiguration config){
		ICConfigurationDescription cfgDes = getDescriptionForConfiguration(config);
		if(cfgDes != null){
			ICConfigurationDescription[] descs= CoreModelUtil.getReferencedConfigurationDescriptions(cfgDes, false);
			List<IConfiguration> result = new ArrayList<IConfiguration>();
			for (ICConfigurationDescription desc : descs) {
				IConfiguration cfg = getConfigurationForDescription(desc);
				if(cfg != null) {
					result.add(cfg);
				}
			}
			return result.toArray(new IConfiguration[result.size()]);
		}

		return new Configuration[0];
	}

	/**
	 * Build the specified build configurations
	 * @param configs - configurations to build
	 * @param monitor - progress monitor
	 */
	public static void buildConfigurations(IConfiguration[] configs, IProgressMonitor monitor) throws CoreException{
		buildConfigurations(configs, null, monitor);
	}

	/**
	 * Build the specified build configurations
	 * @param configs - configurations to build
	 * @param builder - builder to retrieve build arguments
	 * @param monitor - progress monitor
	 */
	public static void buildConfigurations(IConfiguration[] configs, IBuilder builder, IProgressMonitor monitor) throws CoreException{
		buildConfigurations(configs, builder, monitor, true);
	}

	/**
	 * Build the specified build configurations.
	 *
	 * @param configs - configurations to build
	 * @param builder - builder to retrieve build arguments
	 * @param monitor - progress monitor
	 * @param allBuilders - {@code true} if all builders need to be building
	 *    or {@code false} to build with {@link CommonBuilder}
	 */
	public static void buildConfigurations(IConfiguration[] configs, IBuilder builder, IProgressMonitor monitor, boolean allBuilders) throws CoreException{
		buildConfigurations(configs, builder, monitor, allBuilders, IncrementalProjectBuilder.FULL_BUILD);
	}

	/**
	 * Build the specified build configurations.
	 *
	 * @param configs - configurations to build
	 * @param builder - builder to retrieve build arguments
	 * @param monitor - progress monitor
	 * @param allBuilders - {@code true} if all builders need to be building
	 *    or {@code false} to build with {@link CommonBuilder}
	 * @param buildKind - one of
	 *    <li>{@link IncrementalProjectBuilder#CLEAN_BUILD}</li>
	 *    <li>{@link IncrementalProjectBuilder#INCREMENTAL_BUILD}</li>
	 *    <li>{@link IncrementalProjectBuilder#FULL_BUILD}</li>
	 *
	 * @since 7.0
	 */
	public static void buildConfigurations(IConfiguration[] configs, IBuilder builder, IProgressMonitor monitor,
			boolean allBuilders, int buildKind) throws CoreException{

		Map<IProject, IConfiguration[]> map = sortConfigs(configs);
		for (Entry<IProject, IConfiguration[]> entry : map.entrySet()) {
			IProject proj = entry.getKey();
			IConfiguration[] cfgs = entry.getValue();
			buildConfigurations(proj, cfgs, builder, monitor, allBuilders, buildKind);
		}
	}

	private static Map<IProject, IConfiguration[]> sortConfigs(IConfiguration cfgs[]){
		Map<IProject, Set<IConfiguration>> cfgSetMap = new HashMap<IProject, Set<IConfiguration>>();
		for (IConfiguration cfg : cfgs) {
			IProject proj = cfg.getOwner().getProject();
			Set<IConfiguration> set = cfgSetMap.get(proj);
			if(set == null){
				set = new HashSet<IConfiguration>();
				cfgSetMap.put(proj, set);
			}
			set.add(cfg);
		}

		Map<IProject, IConfiguration[]> cfgArrayMap = new HashMap<IProject, IConfiguration[]>();
		if(cfgSetMap.size() != 0){
			Set<Entry<IProject, Set<IConfiguration>>> entrySet = cfgSetMap.entrySet();
			for (Entry<IProject, Set<IConfiguration>> entry : entrySet) {
				IProject key = entry.getKey();
				Set<IConfiguration> set = entry.getValue();
				cfgArrayMap.put(key, set.toArray(new Configuration[set.size()]));
			}
		}

		return cfgArrayMap;
	}

	/**
	 * Build the specified build configurations for a given project.
	 *
	 * @param project - project the configurations belong to
	 * @param configs - configurations to build
	 * @param builder - builder to retrieve build arguments
	 * @param monitor - progress monitor
	 * @param allBuilders - {@code true} if all builders need to be building
	 *    or {@code false} to build with {@link CommonBuilder}
	 * @param buildKind - one of
	 *    <li>{@link IncrementalProjectBuilder#CLEAN_BUILD}</li>
	 *    <li>{@link IncrementalProjectBuilder#INCREMENTAL_BUILD}</li>
	 *    <li>{@link IncrementalProjectBuilder#FULL_BUILD}</li>
	 *
	 * @throws CoreException
	 */
	private static void buildConfigurations(final IProject project, final IConfiguration[] configs,
			final IBuilder builder, final IProgressMonitor monitor, final boolean allBuilders, final int buildKind) throws CoreException{

		IWorkspaceRunnable op = new IWorkspaceRunnable() {
			/*
			 * (non-Javadoc)
			 *
			 * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
			 */
			@Override
			public void run(IProgressMonitor monitor) throws CoreException {
				int ticks = 1;
				if (buildKind==IncrementalProjectBuilder.CLEAN_BUILD) {
					if (allBuilders) {
						ICommand[] commands = project.getDescription().getBuildSpec();
						ticks = commands.length;
					}
					ticks = ticks*configs.length;
				}
				monitor.beginTask(project.getName(), ticks);

				if (buildKind==IncrementalProjectBuilder.CLEAN_BUILD) {
					// It is not possible to pass arguments to clean() method of a builder
					// So we iterate setting active configuration
					IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
					IConfiguration savedCfg = buildInfo.getDefaultConfiguration();

					try {
						for (IConfiguration config : configs) {
							if (monitor.isCanceled())
								break;

							buildInfo.setDefaultConfiguration(config);
							buildProject(project, null, allBuilders, buildKind, monitor);
						}
					} finally {
						buildInfo.setDefaultConfiguration(savedCfg);
					}
				} else {
					// configuration IDs are passed in args to CDT builder
					Map<String, String> args = builder!=null ? BuilderFactory.createBuildArgs(configs, builder)
							: BuilderFactory.createBuildArgs(configs);
					buildProject(project, args, allBuilders, buildKind, monitor);
				}

				monitor.done();
			}

			private void buildProject(IProject project, Map<String, String> args, boolean allBuilders, int buildKind, IProgressMonitor monitor)
					throws CoreException {

				if (allBuilders) {
					ICommand[] commands = project.getDescription().getBuildSpec();
					for (ICommand command : commands) {
						if (monitor.isCanceled())
							break;

						String builderName = command.getBuilderName();
						Map<String, String> newArgs = null;
						if (buildKind!=IncrementalProjectBuilder.CLEAN_BUILD) {
							newArgs = new HashMap<String, String>(args);
							if (!builderName.equals(CommonBuilder.BUILDER_ID)) {
								newArgs.putAll(command.getArguments());
							}
						}
						project.build(buildKind, builderName, newArgs, new SubProgressMonitor(monitor, 1));
					}
				} else {
					project.build(buildKind, CommonBuilder.BUILDER_ID, args, new SubProgressMonitor(monitor, 1));
				}
			}
		};

		try {
			ResourcesPlugin.getWorkspace().run(op, monitor);
		} finally {
			monitor.done();
		}
	}

	public static IBuilder getInternalBuilder(){
		return getExtensionBuilder(INTERNAL_BUILDER_ID);
	}

	public static ITool getExtensionTool(ITool tool){
		ITool extTool = tool;
		for(;extTool != null && !extTool.isExtensionElement(); extTool = extTool.getSuperClass()) {}
		return extTool;
	}

	public static IInputType getExtensionInputType(IInputType inType){
		IInputType extIT = inType;
		for(;extIT != null && !extIT.isExtensionElement(); extIT = extIT.getSuperClass()) {}
		return extIT;
	}

	public static IConfiguration getPreferenceConfiguration(boolean write){
		try {
			ICConfigurationDescription des = CCorePlugin.getDefault().getPreferenceConfiguration(CFG_DATA_PROVIDER_ID, write);
			if(des != null)
				return getConfigurationForDescription(des);
		} catch (CoreException e) {
			ManagedBuilderCorePlugin.log(e);
		}
		return null;
	}

	public static void setPreferenceConfiguration(IConfiguration cfg) throws CoreException{
		ICConfigurationDescription des = getDescriptionForConfiguration(cfg);
		if(des != null)
			CCorePlugin.getDefault().setPreferenceConfiguration(CFG_DATA_PROVIDER_ID, des);
	}

	static synchronized void updateLoaddedInfo(IProject fromProject, IProject toProject, IManagedBuildInfo info){
		try {
			setLoaddedBuildInfo(fromProject, null);
			setLoaddedBuildInfo(toProject, info);
		} catch (CoreException e) {
		}
	}

	/**
	 * entry-point for the tool-chain modification validation functionality
	 */
	public static IToolChainModificationManager getToolChainModificationManager(){
		return ToolChainModificationManager.getInstance();
	}

	// Check toolchain for platform compatibility
	public static boolean isPlatformOk(IToolChain tc) {
		ITargetPlatform tp = tc.getTargetPlatform();
		if (tp != null) {
			List<String> osList = Arrays.asList(tc.getOSList());
			if (osList.contains(ALL) || osList.contains(os)) {
				List<String> archList = Arrays.asList(tc.getArchList());
				if (archList.contains(ALL) || archList.contains(arch))
					return true; // OS and ARCH fits
			}
			return false; // OS or ARCH does not fit
		}
		return true; // no target platform - nothing to check.
	}

	/*package*/ static void collectLanguageSettingsConsoleParsers(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker, List<IConsoleParser> parsers) {
		if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
			List<ILanguageSettingsProvider> lsProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
			for (ILanguageSettingsProvider lsProvider : lsProviders) {
				ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(lsProvider);
				if (rawProvider instanceof ICBuildOutputParser) {
					ICBuildOutputParser consoleParser = (ICBuildOutputParser) rawProvider;
					try {
						consoleParser.startup(cfgDescription, cwdTracker);
						parsers.add(consoleParser);
					} catch (CoreException e) {
						ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID,
								"Language Settings Provider failed to start up", e)); //$NON-NLS-1$
					}
				}
			}
		}

	}

	/**
	 * Generic routine for checking the availability of converters for the given list of Build Objects.
	 * 
	 * @return true if there are converters for at least one object in the given list of Build Objects.
	 *         Returns false if there are no converters.
	 * @since 8.1
	 */
	public static boolean hasAnyTargetConversionElements(List<IBuildObject> buildObjs) {
		if (buildObjs != null && !buildObjs.isEmpty()) {
			for (IBuildObject obj : buildObjs) {
				if (hasTargetConversionElements(obj)) {
					return true;
				}
			}
		}
		return false;
	}
}
