/******************************************************************************* * Copyright (c) 2004, 2011 Intel 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: * Intel Corporation - Initial API and implementation * IBM Corporation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.cdt.internal.core.SafeStringInterner; import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty; import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyType; import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue; import org.eclipse.cdt.managedbuilder.core.IBuildObjectProperties; import org.eclipse.cdt.managedbuilder.core.IBuildPropertiesRestriction; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IConfigurationNameProvider; import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; import org.eclipse.cdt.managedbuilder.core.IProjectType; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.envvar.IProjectEnvironmentVariableSupplier; import org.eclipse.cdt.managedbuilder.macros.IProjectBuildMacroSupplier; 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.Platform; import org.osgi.framework.Version; public class ProjectType extends BuildObject implements IProjectType, IBuildPropertiesRestriction, IBuildPropertyChangeListener { private static final String EMPTY_STRING = new String(); //private static final IConfiguration[] emptyConfigs = new IConfiguration[0]; // Superclass private IProjectType superClass; private String superClassId; // Parent and children private List<Configuration> configList; // Configurations of this project type private Map<String, IConfiguration> configMap; // Managed Build model attributes private Boolean isAbstract; private Boolean isTest; private String unusedChildren; private String convertToId; private IConfigurationElement configurationNameProviderElement = null; private IConfigurationNameProvider configurationNameProvider = null; private IConfigurationElement environmentVariableSupplierElement = null; private IProjectEnvironmentVariableSupplier environmentVariableSupplier = null; private IConfigurationElement buildMacroSupplierElement = null; private IProjectBuildMacroSupplier buildMacroSupplier = null; BuildObjectProperties buildProperties; // Miscellaneous private boolean resolved = true; private IConfigurationElement previousMbsVersionConversionElement; private IConfigurationElement currentMbsVersionConversionElement; /* * C O N S T R U C T O R S */ /** * This constructor is called to create a projectType defined by an extension point in * a plugin manifest file. */ public ProjectType(IManagedConfigElement element, String managedBuildRevision) { // setup for resolving resolved = false; setManagedBuildRevision(managedBuildRevision); loadFromManifest(element); // Hook me up to the Managed Build Manager ManagedBuildManager.addExtensionProjectType(this); // Load the configuration children IManagedConfigElement[] configs = element.getChildren(IConfiguration.CONFIGURATION_ELEMENT_NAME); String [] usedConfigNames = new String[configs.length]; IConfigurationNameProvider configurationNameProvder = getConfigurationNameProvider(); if ( configurationNameProvder != null ) { // Tool Integrator provided 'ConfigurationNameProvider' class // to get configuration names dynamically based architecture, os, toolchain version etc. for (int n = 0; n < configs.length; ++n) { Configuration config = new Configuration(this, configs[n], managedBuildRevision); String newConfigName = configurationNameProvder.getNewConfigurationName(config, usedConfigNames); config.setName(newConfigName); usedConfigNames[n] = newConfigName; } } else { for (int n = 0; n < configs.length; ++n) { Configuration config = new Configuration(this, configs[n], managedBuildRevision); } } } /** * This constructor is called to create a project type whose attributes and children will be * added by separate calls. * * @param superClass The superClass, if any * @param Id The id for the new project type * @param managedBuildRevision The name for the new project type */ public ProjectType(ProjectType superClass, String Id, String name, String managedBuildRevision) { // setup for resolving resolved = false; this.superClass = superClass; if (this.superClass != null) { superClassId = this.superClass.getId(); } setId(Id); setName(name); setManagedBuildRevision(managedBuildRevision); setVersion(getVersionFromId()); // Hook me up to the Managed Build Manager ManagedBuildManager.addExtensionProjectType(this); } /* * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S */ /** * Load the project-type information from the XML element specified in the * argument * @param element An XML element containing the project type information */ protected void loadFromManifest(IManagedConfigElement element) { ManagedBuildManager.putConfigElement(this, element); // id setId(SafeStringInterner.safeIntern(element.getAttribute(ID))); // Get the name setName(SafeStringInterner.safeIntern(element.getAttribute(NAME))); // version setVersion(getVersionFromId()); // superClass superClassId = SafeStringInterner.safeIntern(element.getAttribute(SUPERCLASS)); String props = SafeStringInterner.safeIntern(element.getAttribute(BUILD_PROPERTIES)); if(props != null) buildProperties = new BuildObjectProperties(props, this, this); String artType = SafeStringInterner.safeIntern(element.getAttribute(BUILD_ARTEFACT_TYPE)); if(artType != null){ if(buildProperties == null) buildProperties = new BuildObjectProperties(this, this); try { buildProperties.setProperty(ManagedBuildManager.BUILD_ARTEFACT_TYPE_PROPERTY_ID, artType, true); } catch (CoreException e) { ManagedBuilderCorePlugin.log(e); } } // Get the unused children, if any unusedChildren = SafeStringInterner.safeIntern(element.getAttribute(UNUSED_CHILDREN)); // isAbstract String isAbs = element.getAttribute(IS_ABSTRACT); if (isAbs != null){ isAbstract = new Boolean("true".equals(isAbs)); //$NON-NLS-1$ } // Is this a test project type String isTestStr = element.getAttribute(IS_TEST); if (isTestStr != null){ isTest = new Boolean("true".equals(isTestStr)); //$NON-NLS-1$ } // Store the configuration element IFF there is a configuration name provider defined if (element.getAttribute(CONFIGURATION_NAME_PROVIDER) != null && element instanceof DefaultManagedConfigElement) { configurationNameProviderElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } // Get the environmentVariableSupplier configuration element String environmentVariableSupplier = element.getAttribute(PROJECT_ENVIRONMENT_SUPPLIER); if(environmentVariableSupplier != null && element instanceof DefaultManagedConfigElement){ environmentVariableSupplierElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } // Get the buildMacroSupplier configuration element String buildMacroSupplier = element.getAttribute(PROJECT_MACRO_SUPPLIER); if(buildMacroSupplier != null && element instanceof DefaultManagedConfigElement){ buildMacroSupplierElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } // Get the 'convertToId' attribute if it is available convertToId = SafeStringInterner.safeIntern(element.getAttribute(CONVERT_TO_ID)); } /* * P A R E N T A N D C H I L D H A N D L I N G */ /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#createConfiguration(org.eclipse.cdt.core.build.managed.IConfiguration) */ public IConfiguration createConfiguration(IConfiguration parent, String id, String name) { Configuration config = new Configuration(this, parent, id, name); // ManagedBuildManager.performValueHandlerEvent(config, IManagedOptionValueHandler.EVENT_OPEN); return config; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#getConfiguration() */ public IConfiguration getConfiguration(String id) { return getConfigurationMap().get(id); } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IProjectType#getConfigurations() */ public IConfiguration[] getConfigurations() { IConfiguration[] configs = getConfigurationList().toArray(new IConfiguration[0]); return configs; } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IProjectType#removeConfiguration(java.lang.String) */ public void removeConfiguration(String id) { // Remove the specified configuration from the list and map Iterator<Configuration> iter = getConfigurationList().listIterator(); while (iter.hasNext()) { IConfiguration config = iter.next(); if (config.getId().equals(id)) { getConfigurationList().remove(config); getConfigurationMap().remove(id); break; } } } /** * Adds the Configuration to the Configuration list and map */ public void addConfiguration(Configuration configuration) { if(!configuration.isTemporary()){ getConfigurationList().add(configuration); getConfigurationMap().put(configuration.getId(), configuration); } } /** * Safe accessor for the list of configurations. * * @return List containing the configurations */ private List<Configuration> getConfigurationList() { if (configList == null) { configList = new ArrayList<Configuration>(); } return configList; } /** * Safe accessor for the map of configuration ids to configurations */ private Map<String, IConfiguration> getConfigurationMap() { if (configMap == null) { configMap = new HashMap<String, IConfiguration>(); } return configMap; } /* * M O D E L A T T R I B U T E A C C E S S O R S */ /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IBuildObject#getName() */ @Override public String getName() { String name = getNameAttribute(); if(name.length() == 0){ IBuildObjectProperties props = getBuildProperties(); IBuildProperty prop = props.getProperty(ManagedBuildManager.BUILD_ARTEFACT_TYPE_PROPERTY_ID); if(prop != null) name = prop.getValue().getName(); } return name; } public String getNameAttribute() { // If I am unnamed, see if I can inherit one from my parent if (name == null) { if (superClass != null) { return (superClass).getNameAttribute(); } else { return new String(""); //$NON-NLS-1$ } } else { return name; } } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IProjectType#getSuperClass() */ public IProjectType getSuperClass() { return superClass; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#isAbstract() */ public boolean isAbstract() { if (isAbstract != null) { return isAbstract.booleanValue(); } else { return false; // Note: no inheritance from superClass } } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#unusedChildren() */ public String getUnusedChildren() { if (unusedChildren != null) { return unusedChildren; } else return EMPTY_STRING; // Note: no inheritance from superClass } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#isTestProjectType() */ public boolean isTestProjectType() { if (isTest == null) { // If I have a superClass, ask it if (superClass != null) { return superClass.isTestProjectType(); } else { return false; } } return isTest.booleanValue(); } /** * Sets the isAbstract attribute */ public void setIsAbstract(boolean b) { isAbstract = new Boolean(b); } /** * Sets the isTest attribute */ public void setIsTest(boolean b) { isTest = new Boolean(b); } /* * O B J E C T S T A T E M A I N T E N A N C E */ /** * Resolve the element IDs to interface references */ public void resolveReferences() { if (!resolved) { resolved = true; // Resolve superClass if (superClassId != null && superClassId.length() > 0) { superClass = ManagedBuildManager.getExtensionProjectType(superClassId); if (superClass == null) { // Report error ManagedBuildManager.outputResolveError( "superClass", //$NON-NLS-1$ superClassId, "projectType", //$NON-NLS-1$ getId()); } } // Add configurations from our superClass that are not overridden here if (superClass != null) { ((ProjectType)superClass).resolveReferences(); IConfiguration[] superConfigs = superClass.getConfigurations(); for (int i = 0; i < superConfigs.length; i++) { String superId = superConfigs[i].getId(); check: { IConfiguration[] currentConfigs = getConfigurations(); for (int j = 0; j < currentConfigs.length; j++) { IConfiguration config = currentConfigs[j]; while (config.getParent() != null) { if (config.getParent().getId().equals(superId)) break check; config = config.getParent(); } } addConfiguration((Configuration)superConfigs[i]); } // end check } } // Call resolve references on any children List<Configuration> configurationList = getConfigurationList(); for (Configuration current : configurationList) { current.resolveReferences(); } } } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#isSupported() */ public boolean isSupported(){ List<Configuration> configurationList = getConfigurationList(); for (Configuration current : configurationList) { if(current.isSupported()) return true; } return false; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#getConfigurationNameProviderElement() */ public IConfigurationElement getConfigurationNameProviderElement() { if(configurationNameProviderElement == null){ if(superClass != null) { ProjectType tmpSuperClass = (ProjectType)superClass; return tmpSuperClass.getConfigurationNameProviderElement(); } } return configurationNameProviderElement; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#setConfigurationNameProviderElement(IConfigurationElement) */ public void setConfigurationNameProviderElement(IConfigurationElement configurationElement) { configurationNameProviderElement = configurationElement; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#getConfigurationNameProvider() */ public IConfigurationNameProvider getConfigurationNameProvider() { if (configurationNameProvider != null) { return configurationNameProvider; } IConfigurationElement element = getConfigurationNameProviderElement(); if (element != null) { try { if (element.getAttribute(CONFIGURATION_NAME_PROVIDER) != null) { configurationNameProvider = (IConfigurationNameProvider) element.createExecutableExtension(CONFIGURATION_NAME_PROVIDER); return configurationNameProvider; } } catch (CoreException e) {} } return null; } /** * Returns the plugin.xml element of the projectEnvironmentSupplier extension or <code>null</code> if none. * * @return IConfigurationElement */ public IConfigurationElement getEnvironmentVariableSupplierElement(){ if (environmentVariableSupplierElement == null) { if (superClass != null && superClass instanceof ProjectType) { return ((ProjectType)superClass).getEnvironmentVariableSupplierElement(); } } return environmentVariableSupplierElement; } /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IProjectType#getEnvironmentVariableSupplier() */ public IProjectEnvironmentVariableSupplier getEnvironmentVariableSupplier(){ if (environmentVariableSupplier != null) { return environmentVariableSupplier; } IConfigurationElement element = getEnvironmentVariableSupplierElement(); if (element != null) { try { if (element.getAttribute(PROJECT_ENVIRONMENT_SUPPLIER) != null) { environmentVariableSupplier = (IProjectEnvironmentVariableSupplier) element.createExecutableExtension(PROJECT_ENVIRONMENT_SUPPLIER); return environmentVariableSupplier; } } catch (CoreException e) {} } return null; } /** * Returns the plugin.xml element of the projectMacroSupplier extension or <code>null</code> if none. * * @return IConfigurationElement */ public IConfigurationElement getBuildMacroSupplierElement(){ if (buildMacroSupplierElement == null) { if (superClass != null && superClass instanceof ProjectType) { return ((ProjectType)superClass).getBuildMacroSupplierElement(); } } return buildMacroSupplierElement; } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IProjectType#getBuildMacroSupplier() */ public IProjectBuildMacroSupplier getBuildMacroSupplier(){ if (buildMacroSupplier != null) { return buildMacroSupplier; } IConfigurationElement element = getBuildMacroSupplierElement(); if (element != null) { try { if (element.getAttribute(PROJECT_MACRO_SUPPLIER) != null) { buildMacroSupplier = (IProjectBuildMacroSupplier) element.createExecutableExtension(PROJECT_MACRO_SUPPLIER); return buildMacroSupplier; } } catch (CoreException e) {} } return null; } public String getConvertToId() { if (convertToId == null) { // If I have a superClass, ask it if (getSuperClass() != null) { return getSuperClass().getConvertToId(); } else { return EMPTY_STRING; } } return convertToId; } public void setConvertToId(String convertToId) { if (convertToId == null && this.convertToId == null) return; if (convertToId == null || this.convertToId == null || !convertToId.equals(this.convertToId)) { this.convertToId = convertToId; } return; } /* * This function checks for migration support for the projectType while * loading the project. If migration support is needed, looks for the available * converters and adds them to the list. */ public boolean checkForMigrationSupport() { String convertToId = getConvertToId(); if ((convertToId == null) || (convertToId.equals(""))) { //$NON-NLS-1$ // It means there is no 'convertToId' attribute available and // the project type is still actively // supported by the tool integrator. So do nothing, just return return true; } else { // In case the 'convertToId' attribute is available, // it means that Tool integrator currently does not support this // project type. // Look for the converters available for this project type. return getConverter(convertToId); } } private boolean getConverter(String convertToId) { String fromId = null; String toId = 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 (int i = 0; i < extensions.length; i++) { // Get the configuration elements of each extension IConfigurationElement[] configElements = extensions[i] .getConfigurationElements(); for (int j = 0; j < configElements.length; j++) { IConfigurationElement element = configElements[j]; if (element.getName().equals("converter")) { //$NON-NLS-1$ fromId = element.getAttribute("fromId"); //$NON-NLS-1$ toId = element.getAttribute("toId"); //$NON-NLS-1$ // Check whether the current converter can be used for // the selected project type if (fromId.equals(getId()) && toId.equals(convertToId)) { // If it matches String mbsVersion = element .getAttribute("mbsVersion"); //$NON-NLS-1$ Version currentMbsVersion = ManagedBuildManager .getBuildInfoVersion(); // set the converter element based on the MbsVersion if (currentMbsVersion.compareTo(new Version(mbsVersion))>0) { previousMbsVersionConversionElement = element; } else { currentMbsVersionConversionElement = element; } return true; } } } } } // If control comes here, it means 'Tool Integrator' specified // 'convertToId' attribute in toolchain definition file, but // has not provided any converter. So, make the project is invalid return false; } public IConfigurationElement getPreviousMbsVersionConversionElement() { return previousMbsVersionConversionElement; } public IConfigurationElement getCurrentMbsVersionConversionElement() { return currentMbsVersionConversionElement; } public IBuildObjectProperties getBuildProperties() { if(buildProperties == null){ BuildObjectProperties parentProps = findBuildProperties(); if(parentProps != null) buildProperties = new BuildObjectProperties(parentProps, this, this); else buildProperties = new BuildObjectProperties(this, this); } return buildProperties; } BuildObjectProperties findBuildProperties(){ if(buildProperties == null){ if(superClass != null){ return ((ProjectType)superClass).findBuildProperties(); } return null; } return buildProperties; } public void propertiesChanged() { List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ list.get(i).propertiesChanged(); } } public boolean supportsType(IBuildPropertyType type) { return supportsType(type.getId()); } public boolean supportsValue(IBuildPropertyType type, IBuildPropertyValue value) { return supportsValue(type.getId(), value.getId()); } public boolean supportsType(String typeId) { List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ if(list.get(i).supportsType(typeId)) return true; } return false; } public boolean supportsValue(String typeId, String valueId) { List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ if(list.get(i).supportsValue(typeId, valueId)) return true; } return false; } public String[] getRequiredTypeIds() { List<String> result = new ArrayList<String>(); List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ result.addAll(Arrays.asList((list.get(i)).getRequiredTypeIds())); } return result.toArray(new String[result.size()]); } public String[] getSupportedTypeIds() { List<String> result = new ArrayList<String>(); List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ result.addAll(Arrays.asList((list.get(i)).getSupportedTypeIds())); } return result.toArray(new String[result.size()]); } public String[] getSupportedValueIds(String typeId) { List<String> result = new ArrayList<String>(); List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ result.addAll(Arrays.asList((list.get(i)).getSupportedValueIds(typeId))); } return result.toArray(new String[result.size()]); } public boolean requiresType(String typeId) { List<Configuration> list = getConfigurationList(); for(int i = 0; i < list.size(); i++){ if(list.get(i).requiresType(typeId)) return true; } return false; } public IBuildPropertyValue getBuildArtefactType() { IBuildObjectProperties props = findBuildProperties(); if(props != null){ IBuildProperty prop = props.getProperty(ManagedBuildManager.BUILD_ARTEFACT_TYPE_PROPERTY_ID); if(prop != null) return prop.getValue(); } return null; } public boolean isSystemObject() { return isTestProjectType() || getConvertToId().length() != 0; } }