| /********************************************************************** |
| * Copyright (c) 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM - Initial API and implementation |
| **********************************************************************/ |
| package org.eclipse.cdt.managedbuilder.internal.core; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.CCProjectNature; |
| import org.eclipse.cdt.core.CProjectNature; |
| import org.eclipse.cdt.managedbuilder.core.BuildException; |
| import org.eclipse.cdt.managedbuilder.core.IConfiguration; |
| import org.eclipse.cdt.managedbuilder.core.IOption; |
| import org.eclipse.cdt.managedbuilder.core.ITarget; |
| import org.eclipse.cdt.managedbuilder.core.ITool; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * |
| */ |
| public class Configuration extends BuildObject implements IConfiguration { |
| |
| private ITarget target; |
| private IConfiguration parent; |
| private List toolReferences; |
| |
| /** |
| * A fresh new configuration for a target. |
| * |
| * @param target |
| * @param id |
| */ |
| public Configuration(Target target, String id) { |
| this.id = id; |
| this.target = target; |
| |
| target.addConfiguration(this); |
| } |
| |
| /** |
| * Create a new configuration based on one already defined. |
| * |
| * @param target The <code>Target</code> the receiver will be added to. |
| * @param parent The <code>IConfiguration</code> to copy the settings from. |
| * @param id A unique ID for the configuration. |
| */ |
| public Configuration(Target target, IConfiguration parent, String id) { |
| this.id = id; |
| this.name = parent.getName(); |
| this.target = target; |
| this.parent = parent; |
| |
| // Check that the tool and the project match |
| IProject project = (IProject) target.getOwner(); |
| |
| // Get the tool references from the parent |
| List parentToolRefs = ((Configuration)parent).getLocalToolReferences(); |
| Iterator iter = parentToolRefs.listIterator(); |
| while (iter.hasNext()) { |
| ToolReference toolRef = (ToolReference)iter.next(); |
| |
| // Make a new ToolReference based on the tool in the ref |
| ToolReference newRef = new ToolReference(this, toolRef.getTool()); |
| List optRefs = toolRef.getLocalOptionRefs(); |
| Iterator optIter = optRefs.listIterator(); |
| while (optIter.hasNext()) { |
| OptionReference optRef = (OptionReference)optIter.next(); |
| IOption opt = optRef.getOption(); |
| try { |
| switch (opt.getValueType()) { |
| case IOption.BOOLEAN: |
| new OptionReference(newRef, opt).setValue(optRef.getBooleanValue()); |
| break; |
| case IOption.STRING: |
| new OptionReference(newRef, opt).setValue(optRef.getStringValue()); |
| break; |
| case IOption.ENUMERATED: |
| new OptionReference(newRef, opt).setValue(optRef.getSelectedEnum()); |
| break; |
| case IOption.STRING_LIST : |
| new OptionReference(newRef, opt).setValue(optRef.getStringListValue()); |
| break; |
| case IOption.INCLUDE_PATH : |
| new OptionReference(newRef, opt).setValue(optRef.getIncludePaths()); |
| break; |
| case IOption.PREPROCESSOR_SYMBOLS : |
| new OptionReference(newRef, opt).setValue(optRef.getDefinedSymbols()); |
| break; |
| case IOption.LIBRARIES : |
| new OptionReference(newRef, opt).setValue(optRef.getLibraries()); |
| break; |
| case IOption.OBJECTS : |
| new OptionReference(newRef, opt).setValue(optRef.getUserObjects()); |
| break; |
| } |
| } catch (BuildException e) { |
| continue; |
| } |
| } |
| } |
| |
| target.addConfiguration(this); |
| } |
| |
| /** |
| * Create a new <code>Configuration</code> based on the specification in the plugin manifest. |
| * |
| * @param target The <code>Target</code> the receiver will be added to. |
| * @param element The element from the manifest that contains the default configuration settings. |
| */ |
| public Configuration(Target target, IConfigurationElement element) { |
| this.target = target; |
| |
| // id |
| setId(element.getAttribute(IConfiguration.ID)); |
| |
| // hook me up |
| target.addConfiguration(this); |
| |
| // name |
| setName(element.getAttribute(IConfiguration.NAME)); |
| |
| IConfigurationElement[] configElements = element.getChildren(); |
| for (int l = 0; l < configElements.length; ++l) { |
| IConfigurationElement configElement = configElements[l]; |
| if (configElement.getName().equals(IConfiguration.TOOL_REF)) { |
| new ToolReference(this, configElement); |
| } |
| } |
| } |
| |
| /** |
| * Build a configuration from the project manifest file. |
| * |
| * @param target The <code>Target</code> the configuration belongs to. |
| * @param element The element from the manifest that contains the overridden configuration information. |
| */ |
| public Configuration(Target target, Element element) { |
| this.target = target; |
| |
| // id |
| setId(element.getAttribute(IConfiguration.ID)); |
| |
| // hook me up |
| target.addConfiguration(this); |
| |
| // name |
| if (element.hasAttribute(IConfiguration.NAME)) |
| setName(element.getAttribute(IConfiguration.NAME)); |
| |
| if (element.hasAttribute(IConfiguration.PARENT)) { |
| // See if the target has a parent |
| ITarget targetParent = target.getParent(); |
| // If so, then get my parent from it |
| if (targetParent != null) { |
| parent = targetParent.getConfiguration(element.getAttribute(IConfiguration.PARENT)); |
| } |
| else { |
| parent = null; |
| } |
| } |
| |
| NodeList configElements = element.getChildNodes(); |
| for (int i = 0; i < configElements.getLength(); ++i) { |
| Node configElement = configElements.item(i); |
| if (configElement.getNodeName().equals(IConfiguration.TOOL_REF)) { |
| new ToolReference(this, (Element)configElement); |
| } |
| } |
| |
| } |
| |
| /** |
| * Persist receiver to project file. |
| * |
| * @param doc |
| * @param element |
| */ |
| public void serialize(Document doc, Element element) { |
| element.setAttribute(IConfiguration.ID, id); |
| |
| if (name != null) |
| element.setAttribute(IConfiguration.NAME, name); |
| |
| if (parent != null) |
| element.setAttribute(IConfiguration.PARENT, parent.getId()); |
| |
| // Serialize only the tool references defined in the configuration |
| Iterator iter = getLocalToolReferences().listIterator(); |
| while (iter.hasNext()) { |
| ToolReference toolRef = (ToolReference) iter.next(); |
| Element toolRefElement = doc.createElement(IConfiguration.TOOL_REF); |
| element.appendChild(toolRefElement); |
| toolRef.serialize(doc, toolRefElement); |
| } |
| } |
| |
| /* (non-javadoc) |
| * A safety method to avoid NPEs. It answers the tool reference list in the |
| * receiver. It does not look at the tool references defined in the parent. |
| * |
| * @return List |
| */ |
| protected List getLocalToolReferences() { |
| if (toolReferences == null) { |
| toolReferences = new ArrayList(); |
| } |
| return toolReferences; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#getName() |
| */ |
| public String getName() { |
| return (name == null && parent != null) ? parent.getName() : name; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#getTools() |
| */ |
| public ITool[] getTools() { |
| ITool[] tools = parent != null |
| ? parent.getTools() |
| : target.getTools(); |
| |
| // Validate that the tools correspond to the nature |
| IProject project = (IProject)target.getOwner(); |
| if (project != null) { |
| List validTools = new ArrayList(); |
| |
| // The target is associated with a real project |
| for (int i = 0; i < tools.length; ++i) { |
| ITool tool = tools[i]; |
| // Make sure the tool filter and project nature agree |
| switch (tool.getNatureFilter()) { |
| case ITool.FILTER_C: |
| try { |
| if (project.hasNature(CProjectNature.C_NATURE_ID) && !project.hasNature(CCProjectNature.CC_NATURE_ID)) { |
| validTools.add(tool); |
| } |
| } catch (CoreException e) { |
| continue; |
| } |
| break; |
| case ITool.FILTER_CC: |
| try { |
| if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { |
| validTools.add(tool); |
| } |
| } catch (CoreException e) { |
| continue; |
| } |
| break; |
| case ITool.FILTER_BOTH: |
| validTools.add(tool); |
| break; |
| } |
| } |
| // Now put the valid tools back into the array |
| tools = (ITool[]) validTools.toArray(new ITool[validTools.size()]); |
| } |
| |
| // Replace tools with local overrides |
| for (int i = 0; i < tools.length; ++i) { |
| ITool tool = tools[i]; |
| if (tool == null) { |
| // May have been filtered out |
| continue; |
| } |
| ToolReference ref = getToolReference(tools[i]); |
| if (ref != null) |
| tools[i] = ref; |
| } |
| |
| return tools; |
| } |
| |
| /** |
| * @param targetElement |
| */ |
| public void reset(IConfigurationElement element) { |
| // I just need to reset the tool references |
| getLocalToolReferences().clear(); |
| IConfigurationElement[] configElements = element.getChildren(); |
| for (int l = 0; l < configElements.length; ++l) { |
| IConfigurationElement configElement = configElements[l]; |
| if (configElement.getName().equals(IConfiguration.TOOL_REF)) { |
| new ToolReference(this, configElement); |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#getParent() |
| */ |
| public IConfiguration getParent() { |
| return parent; |
| } |
| |
| /* (non-javadoc) |
| * |
| * @param tool |
| * @return List |
| */ |
| protected List getOptionReferences(ITool tool) { |
| List references = new ArrayList(); |
| |
| // Get all the option references I add for this tool |
| ToolReference toolRef = getToolReference(tool); |
| if (toolRef != null) { |
| references.addAll(toolRef.getLocalOptionRefs()); |
| } |
| |
| // See if there is anything that my parents add that I don't |
| if (parent != null) { |
| List temp = ((Configuration)parent).getOptionReferences(tool); |
| Iterator iter = temp.listIterator(); |
| while (iter.hasNext()) { |
| OptionReference ref = (OptionReference) iter.next(); |
| if (!references.contains(ref)) { |
| references.add(ref); |
| } |
| } |
| } |
| |
| return references; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#getTarget() |
| */ |
| public ITarget getTarget() { |
| return (target == null && parent != null) ? parent.getTarget() : target; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#getOwner() |
| */ |
| public IResource getOwner() { |
| return getTarget().getOwner(); |
| } |
| |
| /** |
| * Returns the reference for a given tool or <code>null</code> if one is not |
| * found. |
| * |
| * @param tool |
| * @return ToolReference |
| */ |
| private ToolReference getToolReference(ITool tool) { |
| // See if the receiver has a reference to the tool |
| ToolReference ref = null; |
| Iterator iter = getLocalToolReferences().listIterator(); |
| while (iter.hasNext()) { |
| ToolReference temp = (ToolReference)iter.next(); |
| if (temp.references(tool)) { |
| ref = temp; |
| break; |
| } |
| } |
| |
| return ref; |
| } |
| |
| public void addToolReference(ToolReference toolRef) { |
| getLocalToolReferences().add(toolRef); |
| } |
| |
| public OptionReference createOptionReference(IOption option) { |
| if (option instanceof OptionReference) { |
| OptionReference optionRef = (OptionReference)option; |
| ToolReference toolRef = optionRef.getToolReference(); |
| if (toolRef.getConfiguration().equals(this)) |
| return optionRef; |
| else { |
| toolRef = new ToolReference(this, toolRef); |
| return toolRef.createOptionReference(option); |
| } |
| } else { |
| ToolReference toolRef = getToolReference(option.getTool()); |
| if (toolRef == null) |
| toolRef = new ToolReference(this, option.getTool()); |
| return toolRef.createOptionReference(option); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, boolean) |
| */ |
| public void setOption(IOption option, boolean value) throws BuildException { |
| // Is there a delta |
| if (option.getBooleanValue() != value) |
| createOptionReference(option).setValue(value); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, java.lang.String) |
| */ |
| public void setOption(IOption option, String value) throws BuildException { |
| String oldValue; |
| // Check whether this is an enumerated option |
| if (option.getValueType() == IOption.ENUMERATED) { |
| oldValue = option.getSelectedEnum(); |
| } |
| else { |
| oldValue = option.getStringValue(); |
| } |
| if (!oldValue.equals(value)) |
| createOptionReference(option).setValue(value); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, java.lang.String[]) |
| */ |
| public void setOption(IOption option, String[] value) throws BuildException { |
| // Is there a delta |
| String[] oldValue; |
| switch (option.getValueType()) { |
| case IOption.STRING_LIST : |
| oldValue = option.getStringListValue(); |
| break; |
| case IOption.INCLUDE_PATH : |
| oldValue = option.getIncludePaths(); |
| break; |
| case IOption.PREPROCESSOR_SYMBOLS : |
| oldValue = option.getDefinedSymbols(); |
| break; |
| case IOption.LIBRARIES : |
| oldValue = option.getLibraries(); |
| break; |
| case IOption.OBJECTS : |
| oldValue = option.getUserObjects(); |
| break; |
| default : |
| oldValue = new String[0]; |
| break; |
| } |
| if(!Arrays.equals(value, oldValue)) |
| createOptionReference(option).setValue(value); |
| } |
| |
| |
| } |