blob: a223de8147c95af7925a991c1315a7daa0a58d7e [file] [log] [blame]
/**********************************************************************
* 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);
}
}