/******************************************************************************* * Copyright (c) 2003, 2016 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 * ARM Ltd. - basic tooltip support * Petri Tuononen - [321040] Get Library Search Paths * Baltasar Belyavsky (Texas Instruments) - [279633] Custom command-generator support *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.cdt.core.settings.model.ICStorageElement; import org.eclipse.cdt.internal.core.SafeStringInterner; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IBuildObject; import org.eclipse.cdt.managedbuilder.core.IBuildPropertiesRestriction; import org.eclipse.cdt.managedbuilder.core.IHoldsOptions; import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; import org.eclipse.cdt.managedbuilder.core.IManagedOptionValueHandler; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IOptionApplicability; import org.eclipse.cdt.managedbuilder.core.IOptionCategory; import org.eclipse.cdt.managedbuilder.core.IOptionCommandGenerator; import org.eclipse.cdt.managedbuilder.core.IProjectType; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.core.ManagedOptionValueHandler; import org.eclipse.cdt.managedbuilder.core.OptionStringValue; import org.eclipse.cdt.managedbuilder.internal.enablement.OptionEnablementExpression; import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData; import org.eclipse.cdt.managedbuilder.macros.IOptionContextData; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.osgi.framework.Version; public class Option extends BuildObject implements IOption, IBuildPropertiesRestriction { // Static default return values public static final String EMPTY_STRING = ""; public static final String[] EMPTY_STRING_ARRAY = new String[0]; public static final OptionStringValue[] EMPTY_LV_ARRAY = new OptionStringValue[0]; // Superclass private IOption superClass; private String superClassId; // Parent and children private IHoldsOptions holder; // Managed Build model attributes private String unusedChildren; private Integer browseType; private String browseFilterPath; private String[] browseFilterExtensions; private List<OptionStringValue> builtIns; private IOptionCategory category; private String categoryId; private String command; private IConfigurationElement commandGeneratorElement; private IOptionCommandGenerator commandGenerator; private String commandFalse; private Boolean isForScannerDiscovery; private String tip; private String contextId; private List<String> applicableValuesList; private Map<String, String> commandsMap; private Map<String, String> namesMap; private Object value; private Object defaultValue; private Integer valueType; private Boolean isAbstract; private Integer resourceFilter; private IConfigurationElement valueHandlerElement = null; private IManagedOptionValueHandler valueHandler = null; private String valueHandlerExtraArgument; private String fieldEditorId; private String fieldEditorExtraArgument; private IConfigurationElement applicabilityCalculatorElement = null; private IOptionApplicability applicabilityCalculator = null; private BooleanExpressionApplicabilityCalculator booleanExpressionCalculator = null; private ITreeRoot treeRoot; // Miscellaneous private boolean isExtensionOption = false; private boolean isDirty = false; private boolean resolved = true; private boolean verified = false; /** * False for options which are invalid. getOption() * routines will ignore invalid options. */ private boolean isValid = true; /** * True for options which are created because of an * MBS 2.0 model OptionReference element */ private boolean wasOptRef = false; private boolean isUdjusted = false; private boolean rebuildState; /** * This constructor is called to create an option defined by an extension point in * a plugin manifest file, or returned by a dynamic element provider * * @param parent The IHoldsOptions parent of this option, or <code>null</code> if * defined at the top level * @param element The option definition from the manifest file or a dynamic element * provider */ public Option(IHoldsOptions parent, IManagedConfigElement element) { this.holder = parent; isExtensionOption = true; // setup for resolving resolved = false; loadFromManifest(element); // Hook me up to the Managed Build Manager ManagedBuildManager.addExtensionOption(this); } /** * This constructor is called to create an Option whose attributes and children will be * added by separate calls. * * @param parent - the parent of the option, if any * @param superClass - the superClass, if any * @param Id - the id for the new option * @param name - the name for the new option * @param isExtensionElement - indicates whether this is an extension element or a managed project element */ public Option(IHoldsOptions parent, IOption superClass, String Id, String name, boolean isExtensionElement) { this.holder = parent; this.superClass = superClass; if (this.superClass != null) { superClassId = this.superClass.getId(); } setId(Id); setName(name); isExtensionOption = isExtensionElement; if (isExtensionElement) { // Hook me up to the Managed Build Manager ManagedBuildManager.addExtensionOption(this); } else { setDirty(true); setRebuildState(true); } } /** * Create an <code>Option</code> based on the specification stored in the * project file (.cdtbuild). * * @param parent The <code>IHoldsOptions</code> the option will be added to. * @param element The XML element that contains the option settings. */ public Option(IHoldsOptions parent, ICStorageElement element) { this.holder = parent; isExtensionOption = false; // Initialize from the XML attributes loadFromProject(element); } /** * Create an <code>Option</code> based upon an existing option. * * @param parent The <code>IHoldsOptions</code> the option will be added to. * @param Id New ID for the option. * @param name New name for the option. * @param option The existing option to clone, except for the above fields. */ public Option(IHoldsOptions parent, String Id, String name, Option option){ this.holder = parent; superClass = option.superClass; if (superClass != null) { superClassId = option.superClass.getId(); } else if (option.superClassId != null) { superClassId = option.superClassId; } setId(Id); setName(name); isExtensionOption = false; boolean copyIds = Id.equals(option.id); // Copy the remaining attributes if (option.unusedChildren != null) { unusedChildren = option.unusedChildren; } if (option.isAbstract != null) { isAbstract = option.isAbstract; } if (option.command != null) { command = option.command; } if (option.commandFalse != null) { commandFalse = option.commandFalse; } if (option.isForScannerDiscovery != null) { isForScannerDiscovery = option.isForScannerDiscovery; } if (option.tip != null) { tip = option.tip; } if (option.contextId != null) { contextId = option.contextId; } if (option.categoryId != null) { categoryId = option.categoryId; } if (option.builtIns != null) { builtIns = new ArrayList<OptionStringValue>(option.builtIns); } if (option.browseType != null) { browseType = option.browseType; } if (option.browseFilterPath != null) { browseFilterPath = option.browseFilterPath; } if (option.browseFilterExtensions != null) { browseFilterExtensions = option.browseFilterExtensions.clone(); } if (option.resourceFilter != null) { resourceFilter = option.resourceFilter; } if (option.applicableValuesList != null) { applicableValuesList = new ArrayList<String>(option.applicableValuesList); commandsMap = new HashMap<String, String>(option.commandsMap); namesMap = new HashMap<String, String>(option.namesMap); } if (option.treeRoot != null) { treeRoot = new TreeRoot((TreeRoot) option.treeRoot); } if (option.valueType != null) { valueType = option.valueType; } try { int vType = option.getValueType(); switch (vType) { case BOOLEAN: if (option.value != null) { value = (Boolean)option.value; } if (option.defaultValue != null) { defaultValue = (Boolean)option.defaultValue; } break; case STRING: case ENUMERATED: case TREE: if (option.value != null) { value = (String)option.value; } if (option.defaultValue != null) { defaultValue = (String)option.defaultValue; } break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: if (option.value != null) { @SuppressWarnings("unchecked") ArrayList<OptionStringValue> list = new ArrayList<OptionStringValue>((ArrayList<OptionStringValue>)option.value); value = list; } if (option.defaultValue != null) { @SuppressWarnings("unchecked") ArrayList<OptionStringValue> list = new ArrayList<OptionStringValue>((ArrayList<OptionStringValue>)option.defaultValue); defaultValue = list; } break; } } catch (BuildException be) { // TODO: should we ignore this?? } category = option.category; commandGeneratorElement = option.commandGeneratorElement; commandGenerator = option.commandGenerator; applicabilityCalculatorElement = option.applicabilityCalculatorElement; applicabilityCalculator = option.applicabilityCalculator; booleanExpressionCalculator = option.booleanExpressionCalculator; if (option.valueHandlerElement != null) { valueHandlerElement = option.valueHandlerElement; valueHandler = option.valueHandler; } if (option.valueHandlerExtraArgument != null) { valueHandlerExtraArgument = option.valueHandlerExtraArgument; } if (option.fieldEditorId != null) { fieldEditorId = option.fieldEditorId; } if (option.fieldEditorExtraArgument != null) { fieldEditorExtraArgument = option.fieldEditorExtraArgument; } if(copyIds){ isDirty = option.isDirty; rebuildState = option.rebuildState; } else { setDirty(true); setRebuildState(true); } } /* * 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 */ /** * Loads the option information from the ManagedConfigElement specified in the * argument. * * @param element Contains the option information */ protected void loadFromManifest(IManagedConfigElement element) { ManagedBuildManager.putConfigElement(this, element); // id setId(SafeStringInterner.safeIntern(element.getAttribute(IBuildObject.ID))); // Get the name setName(SafeStringInterner.safeIntern(element.getAttribute(IBuildObject.NAME))); // superClass superClassId = SafeStringInterner.safeIntern(element.getAttribute(IProjectType.SUPERCLASS)); // Get the unused children, if any unusedChildren = SafeStringInterner.safeIntern(element.getAttribute(IProjectType.UNUSED_CHILDREN)); // isAbstract String isAbs = element.getAttribute(IProjectType.IS_ABSTRACT); if (isAbs != null){ isAbstract = Boolean.parseBoolean(isAbs); } // Get the command defined for the option command = SafeStringInterner.safeIntern(element.getAttribute(COMMAND)); // Get the command-generator, if any String commandGeneratorStr = element.getAttribute(COMMAND_GENERATOR); if (commandGeneratorStr != null && element instanceof DefaultManagedConfigElement) { commandGeneratorElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } // Get the command defined for a Boolean option when the value is False commandFalse = SafeStringInterner.safeIntern(element.getAttribute(COMMAND_FALSE)); // isForScannerDiscovery String isForSD = element.getAttribute(USE_BY_SCANNER_DISCOVERY); if (isForSD != null){ isForScannerDiscovery = Boolean.parseBoolean(isForSD); } // Get the tooltip for the option tip = SafeStringInterner.safeIntern(element.getAttribute(TOOL_TIP)); // Get the contextID for the option contextId = SafeStringInterner.safeIntern(element.getAttribute(CONTEXT_ID)); // Options hold different types of values String valueTypeStr = element.getAttribute(VALUE_TYPE); if (valueTypeStr != null) { valueType = Integer.valueOf(ValueTypeStrToInt(valueTypeStr)); } // Note: The value and defaultValue attributes are loaded in the resolveReferences routine. // This is because we need to have the value-type, and this may be defined in a // superClass that is not yet loaded. // Determine if there needs to be a browse button String browseTypeStr = element.getAttribute(BROWSE_TYPE); if (browseTypeStr == null) { // Set to null, to indicate no browse type specification // This will allow any superclasses to be searched for the // browse type specification, and thus inherited, if found, // which they should be browseType = null; } else if (browseTypeStr.equals(NONE)) { browseType = BROWSE_NONE; } else if (browseTypeStr.equals(FILE)) { browseType = BROWSE_FILE; } else if (browseTypeStr.equals(DIR)) { browseType = BROWSE_DIR; } // Get the browseFilterPath attribute this.browseFilterPath = SafeStringInterner.safeIntern(element.getAttribute(BROWSE_FILTER_PATH)); // Get the browseFilterExtensions attribute String browseFilterExtensionsStr = element.getAttribute(BROWSE_FILTER_EXTENSIONS); if (browseFilterExtensionsStr != null) { this.browseFilterExtensions = SafeStringInterner.safeIntern(browseFilterExtensionsStr.split("\\s*,\\s*")); //$NON-NLS-1$ } categoryId = SafeStringInterner.safeIntern(element.getAttribute(CATEGORY)); // Get the resourceFilter attribute String resFilterStr = element.getAttribute(RESOURCE_FILTER); if (resFilterStr == null) { // Set to null, to indicate no resource filter specification // This will allow any superclasses to be searched for the // resource filter specification, and thus inherited, if found, // which they should be resourceFilter = null; } else if (resFilterStr.equals(ALL)) { resourceFilter = FILTER_ALL; } else if (resFilterStr.equals(FILE)) { resourceFilter = FILTER_FILE; } else if (resFilterStr.equals(PROJECT)) { resourceFilter = FILTER_PROJECT; } //get enablements IManagedConfigElement enablements[] = element.getChildren(OptionEnablementExpression.NAME); if(enablements.length > 0) { booleanExpressionCalculator = new BooleanExpressionApplicabilityCalculator(enablements); } // get the applicability calculator, if any String applicabilityCalculatorStr = element.getAttribute(APPLICABILITY_CALCULATOR); if (applicabilityCalculatorStr != null && element instanceof DefaultManagedConfigElement) { applicabilityCalculatorElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } else { applicabilityCalculator = booleanExpressionCalculator; } // valueHandler // Store the configuration element IFF there is a value handler defined String valueHandler = element.getAttribute(VALUE_HANDLER); if (valueHandler != null && element instanceof DefaultManagedConfigElement) { valueHandlerElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); } // valueHandlerExtraArgument valueHandlerExtraArgument = SafeStringInterner.safeIntern(element.getAttribute(VALUE_HANDLER_EXTRA_ARGUMENT)); // fieldEditor and optional argument fieldEditorId = element.getAttribute(FIELD_EDITOR_ID); fieldEditorExtraArgument = element.getAttribute(FIELD_EDITOR_EXTRA_ARGUMENT); } /** * Initialize the option information from the XML element * specified in the argument * * @param element An XML element containing the option information */ protected void loadFromProject(ICStorageElement element) { // id (unique, don't intern) setId(element.getAttribute(IBuildObject.ID)); // name if (element.getAttribute(IBuildObject.NAME) != null) { setName(SafeStringInterner.safeIntern(element.getAttribute(IBuildObject.NAME))); } // superClass superClassId = SafeStringInterner.safeIntern(element.getAttribute(IProjectType.SUPERCLASS)); if (superClassId != null && superClassId.length() > 0) { superClass = ManagedBuildManager.getExtensionOption(superClassId); if (superClass == null) { // TODO: Report error } } // Get the unused children, if any if (element.getAttribute(IProjectType.UNUSED_CHILDREN) != null) { unusedChildren = SafeStringInterner.safeIntern(element.getAttribute(IProjectType.UNUSED_CHILDREN)); } // isAbstract if (element.getAttribute(IProjectType.IS_ABSTRACT) != null) { String isAbs = element.getAttribute(IProjectType.IS_ABSTRACT); if (isAbs != null){ isAbstract = Boolean.parseBoolean(isAbs); } } // Get the command defined for the option if (element.getAttribute(COMMAND) != null) { command = SafeStringInterner.safeIntern(element.getAttribute(COMMAND)); } // Get the command defined for a Boolean option when the value is False if (element.getAttribute(COMMAND_FALSE) != null) { commandFalse = SafeStringInterner.safeIntern(element.getAttribute(COMMAND_FALSE)); } // isForScannerDiscovery if (element.getAttribute(USE_BY_SCANNER_DISCOVERY) != null) { String isForSD = element.getAttribute(USE_BY_SCANNER_DISCOVERY); if (isForSD != null){ isForScannerDiscovery = Boolean.parseBoolean(isForSD); } } // Get the tooltip for the option if (element.getAttribute(TOOL_TIP) != null) { tip = SafeStringInterner.safeIntern(element.getAttribute(TOOL_TIP)); } // Get the contextID for the option if (element.getAttribute(CONTEXT_ID) != null) { contextId = SafeStringInterner.safeIntern(element.getAttribute(CONTEXT_ID)); } // Options hold different types of values if (element.getAttribute(VALUE_TYPE) != null) { String valueTypeStr = element.getAttribute(VALUE_TYPE); valueType = Integer.valueOf(ValueTypeStrToInt(valueTypeStr)); } // Now get the actual value based upon value-type try { int valType = getValueType(); switch (valType) { case BOOLEAN: // Convert the string to a boolean if (element.getAttribute(VALUE) != null) { value = Boolean.valueOf(element.getAttribute(VALUE)); } if (element.getAttribute(DEFAULT_VALUE) != null) { defaultValue = Boolean.valueOf(element.getAttribute(DEFAULT_VALUE)); } break; case STRING: // Just get the value out of the option directly if (element.getAttribute(VALUE) != null) { value = SafeStringInterner.safeIntern(element.getAttribute(VALUE)); } if (element.getAttribute(DEFAULT_VALUE) != null) { defaultValue = SafeStringInterner.safeIntern(element.getAttribute(DEFAULT_VALUE)); } break; case ENUMERATED: if (element.getAttribute(VALUE) != null) { value = SafeStringInterner.safeIntern(element.getAttribute(VALUE)); } if (element.getAttribute(DEFAULT_VALUE) != null) { defaultValue = SafeStringInterner.safeIntern(element.getAttribute(DEFAULT_VALUE)); } // Do we have enumeratedOptionValue children? If so, load them // to define the valid values and the default value. ICStorageElement configElements[] = element.getChildren(); for (int i = 0; i < configElements.length; ++i) { ICStorageElement configNode = configElements[i]; if (configNode.getName().equals(ENUM_VALUE)) { ICStorageElement configElement = configNode; String optId = SafeStringInterner.safeIntern(configElement.getAttribute(ID)); if (i == 0) { applicableValuesList = new ArrayList<String>(); if (defaultValue == null) { defaultValue = optId; // Default value to be overridden is default is specified } } applicableValuesList.add(optId); if (configElement.getAttribute(COMMAND) != null) { getCommandMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(COMMAND))); } else { getCommandMap().put(optId, EMPTY_STRING); } getNameMap().put(optId, SafeStringInterner.safeIntern(configElement.getAttribute(NAME))); if (configElement.getAttribute(IS_DEFAULT) != null) { Boolean isDefault = Boolean.valueOf(configElement.getAttribute(IS_DEFAULT)); if (isDefault.booleanValue()) { defaultValue = optId; } } } } break; case TREE: if (element.getAttribute(VALUE) != null) { value = element.getAttribute(VALUE); } if (element.getAttribute(DEFAULT_VALUE) != null) { defaultValue = element.getAttribute(DEFAULT_VALUE); } break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: // Note: These string-list options do not load either the "value" or // "defaultValue" attributes. Instead, the ListOptionValue children // are loaded in the value field. List<OptionStringValue> vList = null; List<OptionStringValue> biList = null; configElements = element.getChildren(); for (ICStorageElement veNode : configElements) { if (vList==null) { vList = new ArrayList<OptionStringValue>(); } if (biList==null) { biList = new ArrayList<OptionStringValue>(); } if (veNode.getName().equals(LIST_VALUE)) { OptionStringValue ve = new OptionStringValue(veNode); if(ve.isBuiltIn()) { biList.add(ve); } else { vList.add(ve); } } } if(vList != null && vList.size() != 0) { value = vList; } else { value = null; } if(biList != null && biList.size() != 0) { builtIns = biList; } else { builtIns = null; } break; default : break; } } catch (BuildException e) { // TODO: report error } // Determine if there needs to be a browse button if (element.getAttribute(BROWSE_TYPE) != null) { String browseTypeStr = element.getAttribute(BROWSE_TYPE); if (browseTypeStr == null) { // Set to null, to indicate no browse type specification // This will allow any superclasses to be searched for the // browse type specification, and thus inherited, if found, // which they should be browseType = null; } else if (browseTypeStr.equals(NONE)) { browseType = BROWSE_NONE; } else if (browseTypeStr.equals(FILE)) { browseType = BROWSE_FILE; } else if (browseTypeStr.equals(DIR)) { browseType = BROWSE_DIR; } } // Get the browseFilterPath attribute if (element.getAttribute(BROWSE_FILTER_PATH) != null) { this.browseFilterPath = SafeStringInterner.safeIntern(element.getAttribute(BROWSE_FILTER_PATH)); } // Get the browseFilterExtensions attribute if (element.getAttribute(BROWSE_FILTER_EXTENSIONS) != null) { String browseFilterExtensionsStr = element.getAttribute(BROWSE_FILTER_EXTENSIONS); if (browseFilterExtensionsStr != null) { this.browseFilterExtensions = SafeStringInterner.safeIntern(browseFilterExtensionsStr.split("\\s*,\\s*")); //$NON-NLS-1$ } } if (element.getAttribute(CATEGORY) != null) { categoryId = SafeStringInterner.safeIntern(element.getAttribute(CATEGORY)); if (categoryId != null) { category = holder.getOptionCategory(categoryId); } } // Get the resourceFilter attribute if (element.getAttribute(RESOURCE_FILTER) != null) { String resFilterStr = element.getAttribute(RESOURCE_FILTER); if (resFilterStr == null) { // Set to null, to indicate no resource filter specification // This will allow any superclasses to be searched for the // resource filter specification, and thus inherited, if found, // which they should be resourceFilter = null; } else if (resFilterStr.equals(ALL)) { resourceFilter = FILTER_ALL; } else if (resFilterStr.equals(FILE)) { resourceFilter = FILTER_FILE; } else if (resFilterStr.equals(PROJECT)) { resourceFilter = FILTER_PROJECT; } } // Note: valueHandlerElement and VALUE_HANDLER are not restored, // as they are not saved. See note in serialize(). // valueHandlerExtraArgument if (element.getAttribute(VALUE_HANDLER_EXTRA_ARGUMENT) != null) { valueHandlerExtraArgument = SafeStringInterner.safeIntern(element.getAttribute(VALUE_HANDLER_EXTRA_ARGUMENT)); } } private int ValueTypeStrToInt(String valueTypeStr) { if (valueTypeStr == null) { return -1; } if (valueTypeStr.equals(TYPE_STRING)) { return STRING; } else if (valueTypeStr.equals(TYPE_STR_LIST)) { return STRING_LIST; } else if (valueTypeStr.equals(TYPE_BOOL)) { return BOOLEAN; } else if (valueTypeStr.equals(TYPE_ENUM)) { return ENUMERATED; } else if (valueTypeStr.equals(TYPE_INC_PATH)) { return INCLUDE_PATH; } else if (valueTypeStr.equals(TYPE_LIB)) { return LIBRARIES; } else if (valueTypeStr.equals(TYPE_USER_OBJS)) { return OBJECTS; } else if (valueTypeStr.equals(TYPE_DEFINED_SYMBOLS)) { return PREPROCESSOR_SYMBOLS; } else if (valueTypeStr.equals(TYPE_LIB_PATHS)) { return LIBRARY_PATHS; } else if (valueTypeStr.equals(TYPE_LIB_FILES)) { return LIBRARY_FILES; } else if (valueTypeStr.equals(TYPE_INC_FILES)) { return INCLUDE_FILES; } else if (valueTypeStr.equals(TYPE_SYMBOL_FILES)) { return MACRO_FILES; } else if (valueTypeStr.equals(TYPE_UNDEF_INC_PATH)) { return UNDEF_INCLUDE_PATH; } else if (valueTypeStr.equals(TYPE_UNDEF_DEFINED_SYMBOLS)) { return UNDEF_PREPROCESSOR_SYMBOLS; } else if (valueTypeStr.equals(TYPE_UNDEF_LIB_PATHS)) { return UNDEF_LIBRARY_PATHS; } else if (valueTypeStr.equals(TYPE_UNDEF_LIB_FILES)) { return UNDEF_LIBRARY_FILES; } else if (valueTypeStr.equals(TYPE_UNDEF_INC_FILES)) { return UNDEF_INCLUDE_FILES; } else if (valueTypeStr.equals(TYPE_UNDEF_SYMBOL_FILES)) { return UNDEF_MACRO_FILES; } else if (valueTypeStr.equals(TYPE_TREE)) { return TREE; } else { ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Invalid option type=\"" + valueTypeStr + "\" specified for option " + getId() )); //$NON-NLS-1$ //$NON-NLS-2$ // This was the CDT 2.0 default return PREPROCESSOR_SYMBOLS; } } /** * Persist the option to the {@link ICStorageElement}. * * @param element - storage element to persist the option */ public void serialize(ICStorageElement element) throws BuildException { if (superClass != null) { element.setAttribute(IProjectType.SUPERCLASS, superClass.getId()); } else if (superClassId != null) { element.setAttribute(IProjectType.SUPERCLASS, superClassId); } element.setAttribute(IBuildObject.ID, id); if (name != null) { element.setAttribute(IBuildObject.NAME, name); } if (unusedChildren != null) { element.setAttribute(IProjectType.UNUSED_CHILDREN, unusedChildren); } if (isAbstract != null) { element.setAttribute(IProjectType.IS_ABSTRACT, isAbstract.toString()); } if (command != null) { element.setAttribute(COMMAND, command); } if (commandFalse != null) { element.setAttribute(COMMAND_FALSE, commandFalse); } if (isForScannerDiscovery != null) { element.setAttribute(USE_BY_SCANNER_DISCOVERY, isForScannerDiscovery.toString()); } if (tip != null) { element.setAttribute(TOOL_TIP, tip); } if (contextId != null) { element.setAttribute(CONTEXT_ID, contextId); } /* * Note: We store value & value-type as a pair, so we know what type of value we are * dealing with when we read it back in. * This is also true of defaultValue. */ boolean storeValueType = false; // value if (value != null) { storeValueType = true; switch (getValueType()) { case BOOLEAN: element.setAttribute(VALUE, ((Boolean)value).toString()); break; case STRING: case ENUMERATED: case TREE: element.setAttribute(VALUE, (String)value); break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: if (value != null) { @SuppressWarnings("unchecked") ArrayList<OptionStringValue> stringList = (ArrayList<OptionStringValue>)value; for (OptionStringValue optValue : stringList) { ICStorageElement valueElement = element.createChild(LIST_VALUE); optValue.serialize(valueElement); } } // Serialize the built-ins that have been overridden if (builtIns != null) { for (OptionStringValue optionValue : builtIns) { ICStorageElement valueElement = element.createChild(LIST_VALUE); optionValue.serialize(valueElement); } } break; } } // defaultValue if (defaultValue != null) { storeValueType = true; switch (getValueType()) { case BOOLEAN: element.setAttribute(DEFAULT_VALUE, ((Boolean)defaultValue).toString()); break; case STRING: case ENUMERATED: case TREE: element.setAttribute(DEFAULT_VALUE, (String)defaultValue); break; default: break; } } if (storeValueType) { String str; switch (getValueType()) { case BOOLEAN: str = TYPE_BOOL; break; case STRING: str = TYPE_STRING; break; case ENUMERATED: str = TYPE_ENUM; break; case STRING_LIST: str = TYPE_STR_LIST; break; case INCLUDE_PATH: str = TYPE_INC_PATH; break; case LIBRARIES: str = TYPE_LIB; break; case OBJECTS: str = TYPE_USER_OBJS; break; case PREPROCESSOR_SYMBOLS: str = TYPE_DEFINED_SYMBOLS; break; case INCLUDE_FILES: str = TYPE_INC_FILES; break; case LIBRARY_PATHS: str = TYPE_LIB_PATHS; break; case LIBRARY_FILES: str = TYPE_LIB_FILES; break; case MACRO_FILES: str = TYPE_SYMBOL_FILES; break; case UNDEF_INCLUDE_PATH: str = TYPE_UNDEF_INC_PATH; break; case UNDEF_PREPROCESSOR_SYMBOLS: str = TYPE_UNDEF_DEFINED_SYMBOLS; break; case UNDEF_INCLUDE_FILES: str = TYPE_UNDEF_INC_FILES; break; case UNDEF_LIBRARY_PATHS: str = TYPE_UNDEF_LIB_PATHS; break; case UNDEF_LIBRARY_FILES: str = TYPE_UNDEF_LIB_FILES; break; case UNDEF_MACRO_FILES: str = TYPE_UNDEF_SYMBOL_FILES; break; case TREE: str = TYPE_TREE; break; default: // TODO; is this a problem... str = EMPTY_STRING; break; } element.setAttribute(VALUE_TYPE, str); } // browse type if (browseType != null) { String str; switch (getBrowseType()) { case BROWSE_NONE: str = NONE; break; case BROWSE_FILE: str = FILE; break; case BROWSE_DIR: str = DIR; break; default: str = EMPTY_STRING; break; } element.setAttribute(BROWSE_TYPE, str); } // browse filter path if (browseFilterPath != null) { element.setAttribute(BROWSE_FILTER_PATH, browseFilterPath); } // browse filter extensions if (browseFilterExtensions != null) { StringBuilder sb = new StringBuilder(); for(String ext : browseFilterExtensions) { sb.append(ext).append(','); } element.setAttribute(BROWSE_FILTER_EXTENSIONS, sb.toString()); } if (categoryId != null) { element.setAttribute(CATEGORY, categoryId); } // resource filter if (resourceFilter != null) { String str; switch (getResourceFilter()) { case FILTER_ALL: str = ALL; break; case FILTER_FILE: str = FILE; break; case FILTER_PROJECT: str = PROJECT; break; default: str = EMPTY_STRING; break; } element.setAttribute(RESOURCE_FILTER, str); } // Note: applicability calculator cannot be specified in a project file because // an IConfigurationElement is needed to load it! if (applicabilityCalculatorElement != null) { // TODO: issue warning? } // Note: a value handler cannot be specified in a project file because // an IConfigurationElement is needed to load it! if (valueHandlerElement != null) { // TODO: Issue warning? Stuck with behavior of this elsewhere in // CDT, e.g. the implementation of Tool } if (valueHandlerExtraArgument != null) { element.setAttribute(VALUE_HANDLER_EXTRA_ARGUMENT, valueHandlerExtraArgument); } // I am clean now isDirty = false; } @Override public IOptionContextData getOptionContextData(IHoldsOptions holder) { return new OptionContextData(this, holder); } /* * P A R E N T A N D C H I L D H A N D L I N G */ @Override public IBuildObject getParent() { return holder; } @Override public IHoldsOptions getOptionHolder() { // Do not take superclasses into account return holder; } /* * M O D E L A T T R I B U T E A C C E S S O R S */ @Override public IOption getSuperClass() { return superClass; } @Override public String getName() { return (name == null && superClass != null) ? superClass.getName() : name; } @Override public String[] getApplicableValues() { // Does this option instance have the list of values? if (applicableValuesList == null) { if (superClass != null) { return superClass.getApplicableValues(); } else { return EMPTY_STRING_ARRAY; } } // Get all of the enumerated names from the option if (applicableValuesList.size() == 0) { return EMPTY_STRING_ARRAY; } else { // Return the elements in the order they are specified in the manifest String[] enumNames = new String[applicableValuesList.size()]; for (int index = 0; index < applicableValuesList.size(); ++ index) { enumNames[index] = getNameMap().get(applicableValuesList.get(index)); } return enumNames; } } @Override public boolean getBooleanValue() { return ((Boolean)getValue()).booleanValue(); } @Override public int getBrowseType() { if (browseType == null) { if (superClass != null) { return superClass.getBrowseType(); } else { return BROWSE_NONE; } } return browseType.intValue(); } @Override public String getBrowseFilterPath() { if (browseFilterPath == null) { if (superClass != null) { return superClass.getBrowseFilterPath(); } else { return null; } } return browseFilterPath; } @Override public String[] getBrowseFilterExtensions() { if (browseFilterExtensions == null) { if (superClass != null) { return superClass.getBrowseFilterExtensions(); } else { return null; } } return browseFilterExtensions.clone(); } @Override public int getResourceFilter() { if (resourceFilter == null) { if (superClass != null) { return superClass.getResourceFilter(); } else { return FILTER_ALL; } } return resourceFilter.intValue(); } public IConfigurationElement getApplicabilityCalculatorElement() { /* if (applicabilityCalculatorElement == null) { if (superClass != null) { return ((Option)superClass).getApplicabilityCalculatorElement(); } } */ return applicabilityCalculatorElement; } @Override public IOptionApplicability getApplicabilityCalculator() { if (applicabilityCalculator == null) { if (applicabilityCalculatorElement != null) { try { if (applicabilityCalculatorElement.getAttribute(APPLICABILITY_CALCULATOR) != null) { applicabilityCalculator = (IOptionApplicability) applicabilityCalculatorElement .createExecutableExtension(APPLICABILITY_CALCULATOR); } } catch (CoreException e) { ManagedBuilderCorePlugin.log(e); } } else if(superClass != null) { applicabilityCalculator = superClass.getApplicabilityCalculator(); } } return applicabilityCalculator; } @Override public String[] getBuiltIns() { // Return the list of built-ins as an array List<OptionStringValue> list = getExactBuiltinsList(); List<String> valueList = listValueListToValueList(list); if(valueList == null) { return EMPTY_STRING_ARRAY; } return valueList.toArray(new String[valueList.size()]); } public List<OptionStringValue> getExactBuiltinsList() { // Return the list of built-ins as an array if (builtIns == null) { if (superClass != null) { return ((Option)superClass).getExactBuiltinsList(); } else { return null; } } return builtIns; } @Override public IOptionCategory getCategory() { if (category == null) { if (superClass != null) { return superClass.getCategory(); } else { if (getOptionHolder() instanceof ITool) { return ((ITool)getOptionHolder()).getTopOptionCategory(); } else { return null; } } } return category; } @Override public String getCommand() { if (command == null) { if (superClass != null) { return superClass.getCommand(); } else { return EMPTY_STRING; } } return command; } @Override public IOptionCommandGenerator getCommandGenerator() { if (commandGenerator == null) { if (commandGeneratorElement != null) { try { if (commandGeneratorElement.getAttribute(COMMAND_GENERATOR) != null) { commandGenerator = (IOptionCommandGenerator) commandGeneratorElement .createExecutableExtension(COMMAND_GENERATOR); } } catch (CoreException e) { ManagedBuilderCorePlugin.log(e); } } else if(superClass != null) { commandGenerator = superClass.getCommandGenerator(); } } return commandGenerator; } @Override public String getCommandFalse() { if (commandFalse == null) { if (superClass != null) { return superClass.getCommandFalse(); } else { return EMPTY_STRING; } } return commandFalse; } @Override public boolean isForScannerDiscovery() { if (isForScannerDiscovery == null) { isForScannerDiscovery = superClass != null && superClass.isForScannerDiscovery(); } return isForScannerDiscovery; } @Override public String getToolTip() { if (tip == null) { if (superClass != null) { return superClass.getToolTip(); } else { return EMPTY_STRING; } } return tip; } @Override public String getContextId() { if (contextId == null) { if (superClass != null) { return superClass.getContextId(); } else { return EMPTY_STRING; } } return contextId; } @Override public String[] getDefinedSymbols() throws BuildException { if (getValueType() != PREPROCESSOR_SYMBOLS) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String getCommand(String id) throws BuildException { // Sanity if (id == null) { return EMPTY_STRING; } // Does this option instance have the list of values? if (applicableValuesList == null) { if (superClass != null) { return superClass.getCommand(id); } else { return EMPTY_STRING; } } if (getValueType() != ENUMERATED && getValueType() != TREE) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } // First check for the command in ID->command map String cmd = getCommandMap().get(id); if (cmd == null) { // This may be a 1.2 project or plugin manifest. If so, the argument is the human readable // name of the enumeration. Search for the ID that maps to the name and use that to find the // command. for (String realID : applicableValuesList) { String name = getNameMap().get(realID); if (id.equals(name)) { cmd = getCommandMap().get(realID); break; } } } return cmd == null ? EMPTY_STRING : cmd; } @Override public String getEnumCommand(String id) throws BuildException { return getCommand(id); } @Override public String getEnumName(String id) throws BuildException { return getName(id); } @Override public String getName(String id) throws BuildException { // Sanity if (id == null) { return EMPTY_STRING; } // Does this option instance have the list of values? if (applicableValuesList == null) { if (superClass != null) { return superClass.getName(id); } else { return EMPTY_STRING; } } if (getValueType() != ENUMERATED) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } // First check for the command in ID->name map String name = getNameMap().get(id); if (name == null) { // This may be a 1.2 project or plugin manifest. If so, the argument is the human readable // name of the enumeration. name = id; } return name; } /** * A memory-safe accessor to the map of enumerated option value IDs to the commands * that a tool understands. * * @return a Map of enumerated option value IDs to actual commands that are passed * to a tool on the command line. */ private Map<String, String> getCommandMap() { if (commandsMap == null) { commandsMap = new HashMap<String, String>(); } return commandsMap; } @Override public String getEnumeratedId(String name) throws BuildException { return getId(name); } @Override public String getId(String name) throws BuildException { if (name == null) { return null; } // Does this option instance have the list of values? if (applicableValuesList == null) { if (superClass != null) { return superClass.getId(name); } else { return EMPTY_STRING; } } if (getValueType() != ENUMERATED && getValueType() != TREE) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } Set<String> idSet = getNameMap().keySet(); for (String id : idSet) { String enumName = getNameMap().get(id); if (name.equals(enumName)) { return id; } } return null; } /** * @return a Map of enumerated option value IDs to the selection displayed to the user. */ private Map<String, String> getNameMap() { if (namesMap == null) { namesMap = new HashMap<String, String>(); } return namesMap; } @Override public String[] getIncludePaths() throws BuildException { if (getValueType() != INCLUDE_PATH) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String[] getLibraries() throws BuildException { if (getValueType() != LIBRARIES) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String[] getLibraryFiles() throws BuildException { if (getValueType() != LIBRARY_FILES) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String[] getLibraryPaths() throws BuildException { if (getValueType() != LIBRARY_PATHS) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String getSelectedEnum() throws BuildException { if (getValueType() != ENUMERATED) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } return getStringValue(); } @Override public String[] getStringListValue() throws BuildException { if (getValueType() != STRING_LIST) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public String getStringValue() throws BuildException { if (getValueType() != STRING && getValueType() != ENUMERATED && getValueType() != TREE) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } return getValue() == null ? EMPTY_STRING : (String)getValue(); } @Override public String[] getUserObjects() throws BuildException { if (getValueType() != OBJECTS) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } // This is the right puppy, so return its list value @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } else { v.trimToSize(); return v.toArray(new String[v.size()]); } } @Override public int getValueType() throws BuildException { if (valueType == null) { if (superClass != null) { return superClass.getValueType(); } else { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$; } } return valueType.intValue(); } /** * Gets the value, applying appropriate defaults if necessary. */ @Override public Object getValue() { /* * In order to determine the current value of an option, perform the following steps until a value is found: * 1. Examine the value attribute of the option. * 2. Examine the value attribute of the option's superClass recursively. * 3. Examine the dynamicDefaultValue attribute of the option and invoke it if specified. (not yet implemented) * 4. Examine the defaultValue attribute of the option. * 5. Examine the dynamicDefaultValue attribute of the option's superClass and invoke it if specified. (not yet implemented) * 6. Examine the defaultValue attribute of the option's superClass. * 7. Go to step 5 recursively until no more super classes. * 8. Use the default value for the option type. */ Object val = getRawValue(); if (val == null) { val = getDefaultValue(); if (val == null) { int valType; try { valType = getValueType(); } catch (BuildException e) { return EMPTY_STRING; } switch (valType) { case BOOLEAN: val = Boolean.FALSE; break; case STRING: case TREE: val = EMPTY_STRING; break; case ENUMERATED: // TODO: Can we default to the first enumerated id? val = EMPTY_STRING; break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: val = new ArrayList<String>(); break; default: val = EMPTY_STRING; break; } } } return val; } public Object getExactValue() { /* * In order to determine the current value of an option, perform the following steps until a value is found: * 1. Examine the value attribute of the option. * 2. Examine the value attribute of the option's superClass recursively. * 3. Examine the dynamicDefaultValue attribute of the option and invoke it if specified. (not yet implemented) * 4. Examine the defaultValue attribute of the option. * 5. Examine the dynamicDefaultValue attribute of the option's superClass and invoke it if specified. (not yet implemented) * 6. Examine the defaultValue attribute of the option's superClass. * 7. Go to step 5 recursively until no more super classes. * 8. Use the default value for the option type. */ Object val = getExactRawValue(); if (val == null) { val = getExactDefaultValue(); if (val == null) { int valType; try { valType = getValueType(); } catch (BuildException e) { return EMPTY_STRING; } switch (valType) { case BOOLEAN: val = Boolean.FALSE; break; case STRING: case TREE: val = EMPTY_STRING; break; case ENUMERATED: // TODO: Can we default to the first enumerated id? val = EMPTY_STRING; break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: val = new ArrayList<OptionStringValue>(); break; default: val = EMPTY_STRING; break; } } } return val; } /** * Gets the raw value, applying appropriate defauls if necessary. */ public Object getRawValue() { Object ev = getExactRawValue(); if(ev instanceof List<?>) { @SuppressWarnings("unchecked") List<String> evList = listValueListToValueList((List<OptionStringValue>)ev); return evList; } return ev; } public Object getExactRawValue() { if (value == null) { if (superClass != null) { Option mySuperClass = (Option)superClass; return mySuperClass.getExactRawValue(); } } return value; } private List<String> listValueListToValueList(List<OptionStringValue> list){ if(list == null) { return null; } List<String> valueList = new ArrayList<String>(list.size()); for(int i = 0; i < list.size(); i++){ OptionStringValue el = list.get(i); valueList.add(el.getValue()); } return valueList; } private List<OptionStringValue> valueListToListValueList(List<String> list, boolean builtIn){ if(list == null) { return null; } List<OptionStringValue> lvList = new ArrayList<OptionStringValue>(list.size()); for(int i = 0; i < list.size(); i++){ String v = list.get(i); lvList.add(new OptionStringValue(v, builtIn)); } return lvList; } /** * Gets the raw default value. */ @Override public Object getDefaultValue() { Object ev = getExactDefaultValue(); if(ev instanceof List<?>) { @SuppressWarnings("unchecked") List<String> evList = listValueListToValueList((List<OptionStringValue>)ev); return evList; } return ev; } public Object getExactDefaultValue() { // Note: string-list options do not have a default value if (defaultValue == null) { if (superClass != null) { return ((Option)superClass).getExactDefaultValue(); } } return defaultValue; } @Override public void setDefaultValue(Object v) { if(v instanceof List<?>) { @SuppressWarnings("unchecked") List<OptionStringValue> vList = valueListToListValueList((List<String>)v, false); defaultValue = vList; } else { defaultValue = v; } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public void setCategory(IOptionCategory category) { if (this.category != category) { this.category = category; if (category != null) { categoryId = category.getId(); } else { categoryId = null; } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } } @Override public void setCommand(String cmd) { if (cmd == null && command == null) { return; } if (cmd == null || command == null || !cmd.equals(command)) { command = cmd; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setCommandFalse(String cmd) { if (cmd == null && commandFalse == null) { return; } if (cmd == null || commandFalse == null || !cmd.equals(commandFalse)) { commandFalse = cmd; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setToolTip(String tooltip) { if (tooltip == null && tip == null) { return; } if (tooltip == null || tip == null || !tooltip.equals(tip)) { tip = tooltip; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setContextId(String id) { if (id == null && contextId == null) { return; } if (id == null || contextId == null || !id.equals(contextId)) { contextId = id; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setResourceFilter(int filter) { if (resourceFilter == null || !(filter == resourceFilter.intValue())) { resourceFilter = Integer.valueOf(filter); if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setBrowseType(int type) { if (browseType == null || !(type == browseType.intValue())) { browseType = Integer.valueOf(type); if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public void setBrowseFilterPath(String path) { if (browseFilterPath == null || !(browseFilterPath.equals(path))) { browseFilterPath = path; if(!isExtensionElement()) { isDirty = true; rebuildState = true; } } } @Override public void setBrowseFilterExtensions(String[] extensions) { if (browseFilterExtensions == null || !(browseFilterExtensions.equals(extensions))) { browseFilterExtensions = extensions; if(!isExtensionElement()) { isDirty = true; rebuildState = true; } } } @Override public void setValue(boolean value) throws BuildException { if (/*!isExtensionElement() && */getValueType() == BOOLEAN){ this.value = value; } else { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public void setValue(String value) throws BuildException { // Note that we can still set the human-readable value here if (/*!isExtensionElement() && */(getValueType() == STRING || getValueType() == ENUMERATED || getValueType() == TREE)) { this.value = value; } else { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public void setValue(String [] value) throws BuildException { if (/*!isExtensionElement() && */ (getValueType() == STRING_LIST || getValueType() == INCLUDE_PATH || getValueType() == PREPROCESSOR_SYMBOLS || getValueType() == LIBRARIES || getValueType() == OBJECTS || getValueType() == INCLUDE_FILES || getValueType() == LIBRARY_PATHS || getValueType() == LIBRARY_FILES || getValueType() == MACRO_FILES || getValueType() == UNDEF_INCLUDE_PATH || getValueType() == UNDEF_PREPROCESSOR_SYMBOLS || getValueType() == UNDEF_INCLUDE_FILES || getValueType() == UNDEF_LIBRARY_PATHS || getValueType() == UNDEF_LIBRARY_FILES || getValueType() == UNDEF_MACRO_FILES )) { // Just replace what the option reference is holding onto if(value == null) { this.value = null; } else { this.value = valueListToListValueList(Arrays.asList(value), false); } } else { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } public void setValue(OptionStringValue [] value) throws BuildException { if (/*!isExtensionElement() && */ (getValueType() == STRING_LIST || getValueType() == INCLUDE_PATH || getValueType() == PREPROCESSOR_SYMBOLS || getValueType() == LIBRARIES || getValueType() == OBJECTS || getValueType() == INCLUDE_FILES || getValueType() == LIBRARY_PATHS || getValueType() == LIBRARY_FILES || getValueType() == MACRO_FILES || getValueType() == UNDEF_INCLUDE_PATH || getValueType() == UNDEF_PREPROCESSOR_SYMBOLS || getValueType() == UNDEF_INCLUDE_FILES || getValueType() == UNDEF_LIBRARY_PATHS || getValueType() == UNDEF_LIBRARY_FILES || getValueType() == UNDEF_MACRO_FILES )) { // Just replace what the option reference is holding onto if(value == null) { this.value = null; } else { this.value = new ArrayList<OptionStringValue>(Arrays.asList(value)); } } else { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public void setValue(Object v) { if(v instanceof List<?>) { @SuppressWarnings("unchecked") List<OptionStringValue> vList = valueListToListValueList((List<String>)v, false); value = vList; } else { value = v; } if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public void setValueType(int type) { // TODO: Verify that this is a valid type if (valueType == null || valueType.intValue() != type) { valueType = Integer.valueOf(type); if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } } public IConfigurationElement getValueHandlerElement() { if (valueHandlerElement == null) { if (superClass != null) { return ((Option)superClass).getValueHandlerElement(); } } return valueHandlerElement; } public void setValueHandlerElement(IConfigurationElement element) { valueHandlerElement = element; if(!isExtensionElement()){ setDirty(true); rebuildState = true; } } @Override public IManagedOptionValueHandler getValueHandler() { if (valueHandler != null) { return valueHandler; } IConfigurationElement element = getValueHandlerElement(); if (element != null) { try { if (element.getAttribute(VALUE_HANDLER) != null) { valueHandler = (IManagedOptionValueHandler) element.createExecutableExtension(VALUE_HANDLER); return valueHandler; } } catch (CoreException e) { ManagedBuildManager.optionValueHandlerError(element.getAttribute(VALUE_HANDLER), getId()); // Assign the default handler to avoid further error messages valueHandler = ManagedOptionValueHandler.getManagedOptionValueHandler(); return valueHandler; } } // If no handler is provided, then use the default handler return ManagedOptionValueHandler.getManagedOptionValueHandler(); } @Override public String getValueHandlerExtraArgument() { if (valueHandlerExtraArgument == null) { if (superClass != null) { return superClass.getValueHandlerExtraArgument(); } else { return EMPTY_STRING; } } return valueHandlerExtraArgument; } @Override public void setValueHandlerExtraArgument(String extraArgument) { if (extraArgument == null && valueHandlerExtraArgument == null) { return; } if (extraArgument == null || valueHandlerExtraArgument == null || !extraArgument.equals(valueHandlerExtraArgument)) { valueHandlerExtraArgument = extraArgument; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } @Override public String getFieldEditorId() { if (fieldEditorId == null) { if (superClass != null) { return ((Option)superClass).getFieldEditorId(); } } return fieldEditorId; } @Override public String getFieldEditorExtraArgument() { if (fieldEditorExtraArgument == null) { if (superClass != null) { return superClass.getFieldEditorExtraArgument(); } else { return null; } } return fieldEditorExtraArgument; } @Override public void setFieldEditorExtraArgument(String extraArgument) { if (extraArgument == null && fieldEditorExtraArgument == null) { return; } if (extraArgument == null || fieldEditorExtraArgument == null || !extraArgument.equals(fieldEditorExtraArgument)) { fieldEditorExtraArgument = extraArgument; if(!isExtensionElement()){ isDirty = true; rebuildState = true; } } } /* * O B J E C T S T A T E M A I N T E N A N C E */ @Override public boolean isExtensionElement() { return isExtensionOption; } public boolean isDirty() { // This shouldn't be called for an extension option if (isExtensionOption) { return false; } return isDirty; } public void setDirty(boolean isDirty) { this.isDirty = isDirty; } public void resolveReferences() { if (!resolved) { resolved = true; // Resolve superClass if (superClassId != null && superClassId.length() > 0) { superClass = ManagedBuildManager.getExtensionOption(superClassId); if (superClass == null) { // Report error ManagedBuildManager.outputResolveError( "superClass", //$NON-NLS-1$ superClassId, "option", //$NON-NLS-1$ getId()); } else { // All of our superclasses must be resolved in order to call // getValueType below. ((Option)superClass).resolveReferences(); } } if (categoryId != null) { category = holder.getOptionCategory(categoryId); if (category == null) { // Report error ManagedBuildManager.outputResolveError( "category", //$NON-NLS-1$ categoryId, "option", //$NON-NLS-1$ getId()); } } // Process the value and default value attributes. This is delayed until now // because we may not know the valueType until after we have resolved the superClass above // Now get the actual value try { IManagedConfigElement element = ManagedBuildManager.getConfigElement(this); switch (getValueType()) { case BOOLEAN: // Convert the string to a boolean String val = element.getAttribute(VALUE); if (val != null) { value = Boolean.valueOf(val); } val = element.getAttribute(DEFAULT_VALUE); if (val != null) { defaultValue = Boolean.valueOf(val); } break; case STRING: // Just get the value out of the option directly value = element.getAttribute(VALUE); defaultValue = element.getAttribute(DEFAULT_VALUE); break; case ENUMERATED: value = element.getAttribute(VALUE); defaultValue = element.getAttribute(DEFAULT_VALUE); // Do we have enumeratedOptionValue children? If so, load them // to define the valid values and the default value. IManagedConfigElement[] enumElements = element.getChildren(ENUM_VALUE); for (int i = 0; i < enumElements.length; ++i) { String optId = SafeStringInterner.safeIntern(enumElements[i].getAttribute(ID)); if (i == 0) { applicableValuesList = new ArrayList<String>(); if (defaultValue == null) { defaultValue = optId; // Default value to be overridden if default is specified } } applicableValuesList.add(optId); getCommandMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(COMMAND))); getNameMap().put(optId, SafeStringInterner.safeIntern(enumElements[i].getAttribute(NAME))); Boolean isDefault = Boolean.valueOf(enumElements[i].getAttribute(IS_DEFAULT)); if (isDefault.booleanValue()) { defaultValue = optId; } } break; case TREE: value = element.getAttribute(VALUE); defaultValue = element.getAttribute(DEFAULT_VALUE); IManagedConfigElement[] treeRootConfigs = element.getChildren(TREE_ROOT); if (treeRootConfigs != null && treeRootConfigs.length == 1) { IManagedConfigElement treeRootConfig = treeRootConfigs[0]; treeRoot = new TreeRoot(treeRootConfig, element, getParent() instanceof IToolChain); applicableValuesList = new ArrayList<String>(); iterateOnTree(treeRoot, new ITreeNodeIterator() { @Override public void iterateOnNode(ITreeOption node) {} @Override public void iterateOnLeaf(ITreeOption leafNode) { applicableValuesList.add(leafNode.getID()); getCommandMap().put(leafNode.getID(), leafNode.getCommand()); getNameMap().put(leafNode.getID(), leafNode.getName()); } }); } break; case STRING_LIST: case INCLUDE_PATH: case PREPROCESSOR_SYMBOLS: case LIBRARIES: case OBJECTS: case INCLUDE_FILES: case LIBRARY_PATHS: case LIBRARY_FILES: case MACRO_FILES: case UNDEF_INCLUDE_PATH: case UNDEF_PREPROCESSOR_SYMBOLS: case UNDEF_INCLUDE_FILES: case UNDEF_LIBRARY_PATHS: case UNDEF_LIBRARY_FILES: case UNDEF_MACRO_FILES: // Note: These string-list options do not load either the "value" or // "defaultValue" attributes. Instead, the ListOptionValue children // are loaded in the value field. List<OptionStringValue> vList = null; IManagedConfigElement[] vElements = element.getChildren(LIST_VALUE); for (IManagedConfigElement vElement : vElements) { if (vList==null) { vList = new ArrayList<OptionStringValue>(); builtIns = new ArrayList<OptionStringValue>(); } OptionStringValue ve = new OptionStringValue(vElement); if(ve.isBuiltIn()) { builtIns.add(ve); } else { vList.add(ve); } } value = vList; break; default : break; } } catch (BuildException e) { // TODO: report error } } } /** * @return Returns the managedBuildRevision. */ @Override public String getManagedBuildRevision() { if ( managedBuildRevision == null) { if ( getParent() != null) { return getParent().getManagedBuildRevision(); } } return managedBuildRevision; } /* (non-Javadoc) * For now implement this method just as a utility to make code * within the Option class cleaner. * TODO: In future we may want to move this to IOption */ protected boolean isAbstract() { if (isAbstract != null) { return isAbstract.booleanValue(); } else { return false; // Note: no inheritance from superClass } } /** * Verifies whether the option is valid and handles * any errors for the option. The following errors * can occur: * (a) Options that are children of a ToolChain must * ALWAYS have a category * (b) Options that are children of a ToolChain must * NEVER have a resourceFilter of "file". * If an error occurs, the option is set to being invalid. * * @pre All references have been resolved. */ private void verify() { if (verified) { return; } verified = true; // Ignore elements that are superclasses if ( getOptionHolder() instanceof IToolChain && isAbstract() == false ) { // Check for error (a) if (getCategory() == null) { ManagedBuildManager.optionValidError(ManagedBuildManager.ERROR_CATEGORY, getId()); // Object becomes invalid isValid = false; } // Check for error (b). Not specifying an attribute is OK. // Do not use getResourceFilter as it does not allow // differentiating between "all" and no attribute specified. if ( resourceFilter != null ) { switch (getResourceFilter()) { case IOption.FILTER_FILE: // TODO: Cannot differentiate between "all" and attribute not // specified. Thus do not produce an error. We can argue that "all" // means all valid resource configurations. ManagedBuildManager.optionValidError(ManagedBuildManager.ERROR_FILTER, getId()); // Object becomes invalid isValid = false; } } } } @Override public boolean isValid() { // We use a lazy scheme to check whether the option is valid. // Note that by default an option is valid. verify() is only called if // the option has been resolved. This gets us around having to deal with // ordering problems during a resolve, or introducing another global // stage to verify the configuration after a resolve. // The trade-off is that errors in the MBS grammar may not be // detected on load, but only when a particular grammar element // is used, say in the GUI. if (verified == false && resolved == true) { verify(); } return isValid; } /** * @return Returns true if this Option was created from an MBS 2.0 model * OptionReference element. */ public boolean wasOptRef() { return wasOptRef; } public void setWasOptRef(boolean was) { wasOptRef = was; } /** * @return Returns the version. */ @Override public Version getVersion() { if ( version == null) { if ( getParent() != null) { return getParent().getVersion(); } } return version; } @Override public void setVersion(Version version) { // Do nothing } public BooleanExpressionApplicabilityCalculator getBooleanExpressionCalculator(boolean isExtensionAdjustment){ if(booleanExpressionCalculator == null && !isExtensionAdjustment){ if(superClass != null){ return ((Option)superClass).getBooleanExpressionCalculator(isExtensionAdjustment); } } return booleanExpressionCalculator; } public boolean isAdjustedExtension(){ return isUdjusted; } public void setAdjusted(boolean adjusted) { isUdjusted = adjusted; } public void setSuperClass(IOption superClass) { if ( this.superClass != superClass ) { this.superClass = superClass; if ( this.superClass == null) { superClassId = null; } else { superClassId = this.superClass.getId(); } if(!isExtensionElement()) { setDirty(true); } } } public boolean needsRebuild() { return rebuildState; } public void setRebuildState(boolean rebuild) { if(isExtensionElement() && rebuild) { return; } rebuildState = rebuild; } public boolean matches(IOption option){ try { if(option.getValueType() != getValueType()) { return false; } if(!option.getName().equals(getName())) { return false; } } catch (BuildException e) { return false; } return true; } @Override public String[] getRequiredTypeIds() { return new String[0]; } @Override public String[] getSupportedTypeIds() { String referenced[] = null; BooleanExpressionApplicabilityCalculator calc = getBooleanExpressionCalculator(false); if(calc != null){ referenced = calc.getReferencedPropertyIds(); } if(referenced == null) { referenced = new String[0]; } return referenced; } @Override public String[] getSupportedValueIds(String typeId) { String referenced[] = null; BooleanExpressionApplicabilityCalculator calc = getBooleanExpressionCalculator(false); if(calc != null){ referenced = calc.getReferencedValueIds(typeId); } if(referenced == null) { referenced = new String[0]; } return referenced; } @Override public boolean requiresType(String typeId) { return false; } @Override public boolean supportsType(String id) { boolean supports = false; BooleanExpressionApplicabilityCalculator calc = getBooleanExpressionCalculator(false); if(calc != null){ if(calc.referesProperty(id)){ supports = true; } } return supports; } @Override public boolean supportsValue(String typeId, String valueId) { boolean supports = false; BooleanExpressionApplicabilityCalculator calc = getBooleanExpressionCalculator(false); if(calc != null){ if(calc.referesPropertyValue(typeId, valueId)){ supports = true; } } return supports; } @Override public String[] getBasicStringListValue() throws BuildException { if (getBasicValueType() != STRING_LIST) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<String> v = (ArrayList<String>)getValue(); if (v == null) { return EMPTY_STRING_ARRAY; } return v.toArray(new String[v.size()]); } @Override public OptionStringValue[] getBasicStringListValueElements() throws BuildException { if (getBasicValueType() != STRING_LIST) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } @SuppressWarnings("unchecked") ArrayList<OptionStringValue> v = (ArrayList<OptionStringValue>)getExactValue(); if (v == null) { return EMPTY_LV_ARRAY; } return v.toArray(new OptionStringValue[v.size()]); } @Override public int getBasicValueType() throws BuildException { switch(getValueType()){ case IOption.BOOLEAN: return IOption.BOOLEAN; case IOption.STRING: return IOption.STRING; case IOption.ENUMERATED: return IOption.ENUMERATED; case IOption.TREE: return IOption.TREE; default: return IOption.STRING_LIST; } } public boolean hasCustomSettings(){ if(superClass == null) { return true; } if(value != null && !value.equals(superClass.getValue())){ return true; } return false; } public static int getOppositeType(int type){ switch(type){ case INCLUDE_PATH: return UNDEF_INCLUDE_PATH; case PREPROCESSOR_SYMBOLS: return UNDEF_PREPROCESSOR_SYMBOLS; case INCLUDE_FILES: return UNDEF_INCLUDE_FILES; case LIBRARY_PATHS: return UNDEF_LIBRARY_PATHS; case LIBRARY_FILES: return UNDEF_LIBRARY_FILES; case MACRO_FILES: return UNDEF_MACRO_FILES; case UNDEF_INCLUDE_PATH: return INCLUDE_PATH; case UNDEF_PREPROCESSOR_SYMBOLS: return PREPROCESSOR_SYMBOLS; case UNDEF_INCLUDE_FILES: return INCLUDE_FILES; case UNDEF_LIBRARY_PATHS: return LIBRARY_PATHS; case UNDEF_LIBRARY_FILES: return LIBRARY_FILES; case UNDEF_MACRO_FILES: return MACRO_FILES; } return 0; } public static class TreeRoot extends TreeOption implements ITreeRoot { private boolean selectLeafOnly = true; TreeRoot(IManagedConfigElement element, IManagedConfigElement buildOption, boolean readTool) { super(element, null, readTool); String leaf = element.getAttribute(SELECT_LEAF_ONLY); if (leaf != null) { selectLeafOnly = Boolean.valueOf(leaf); } String toolTip = buildOption.getAttribute(TOOL_TIP); if (description == null && toolTip != null) { description = toolTip; } } public TreeRoot() { super("", "", null); //$NON-NLS-1$ //$NON-NLS-2$ } public TreeRoot(TreeRoot clone) { super(clone, null); selectLeafOnly = clone.selectLeafOnly; } @Override public boolean isSelectLeafsOnly() { return selectLeafOnly; } @Override public ITreeOption findNode(String id) { if(id == null) { return null; } return find(id, children); } private ITreeOption find(String id, List<ITreeOption> children) { ITreeOption found = null; if (children != null) { for (ITreeOption child : children) { if (id.equals(child.getID())) { found = child; break; } found = find(id, ((TreeOption)child).children); if (found != null) { break; } } } return found; } @Override public ITreeOption addNode(String id, String name, String category, Integer order) { ITreeOption parent = this; if (category != null && category.length() > 0) { ITreeOption tempParent; String[] categories = category.split("\\."); //$NON-NLS-1$ for (String cat : categories) { tempParent = parent.getChild(cat); if (tempParent == null) { tempParent = parent.addChild(cat, cat); if (order != null) { tempParent.setOrder(order); } } parent = tempParent; } } ITreeOption child = parent.addChild(id, name); if (order != null) { child.setOrder(order); } return child; } } private static class TreeOption implements ITreeOption { private String treeNodeId; private String treeNodeName; protected String description; protected String icon; protected String command; protected List<ITreeOption> children = null; private int order = DEFAULT_ORDER; private ITreeOption parent; TreeOption(IManagedConfigElement element, ITreeOption parent, boolean readTool) { treeNodeId = element.getAttribute(ID); treeNodeName = element.getAttribute(NAME); description = element.getAttribute(DESCRIPTION); command = element.getAttribute(COMMAND); icon = element.getAttribute(ICON); String orderStr = element.getAttribute(ORDER); if (orderStr != null && orderStr.trim().length() > 0) { try { order = Integer.parseInt(orderStr); } catch (NumberFormatException e) { // Do nothing, default value is used. } } this.parent = parent; IManagedConfigElement[] treeChildren = element.getChildren(TREE_VALUE); if (treeChildren != null && treeChildren.length > 0) { children = new ArrayList<IOption.ITreeOption>(); for (IManagedConfigElement configElement : treeChildren) { children.add(new TreeOption(configElement, this, readTool)); } } } TreeOption(TreeOption clone, ITreeOption parent) { treeNodeId = clone.treeNodeId; treeNodeName = clone.treeNodeName; description = clone.description; command = clone.command; icon = clone.icon; order = clone.order; this.parent = parent; if (clone.children != null) { children = new ArrayList<IOption.ITreeOption>(); for (ITreeOption cloneChild : clone.children) { children.add(new TreeOption((TreeOption) cloneChild, this)); } } } private TreeOption(String id, String name, ITreeOption parent) { this.treeNodeId = id; this.treeNodeName = name; this.parent = parent; } @Override public ITreeOption addChild(String id, String name) { ITreeOption option = new TreeOption(id, name, this); if (children == null) { children = new ArrayList<IOption.ITreeOption>(); } children.add(0, option); return option; } @Override public boolean isContainer() { return children != null && !children.isEmpty(); // TODO do we need explicit marking as container for empty ones } @Override public String getName() { return treeNodeName; } @Override public String getID() { return treeNodeId; } @Override public String getDescription() { return description; } @Override public String getCommand() { return command; } @Override public String getIcon() { return icon; } @Override public ITreeOption[] getChildren() { if (children == null) { return null; } return children.toArray(new ITreeOption[children.size()]); } @Override public ITreeOption getChild(String name) { if (children == null || name == null) { return null; } for (ITreeOption child : children) { if (name.equals(child.getName())) { return child; } } return null; } @Override public ITreeOption getParent() { return parent; } @Override public int getOrder() { return order; } @Override public void setOrder(int order) { this.order = order; } @Override public void remove() { ((TreeOption)parent).children.remove(this); } @Override public String toString() { return getName(); } } /** * Calls the iterator (visitor) on the passed parent as well as all nodes in its subtree. */ public static void iterateOnTree(ITreeOption parent, ITreeNodeIterator it) { it.iterateOnNode(parent); if (!parent.isContainer()) { it.iterateOnLeaf(parent); } ITreeOption[] children = parent.getChildren(); if (children != null) { for (ITreeOption option : children) { iterateOnTree(option, it); } } } public interface ITreeNodeIterator { void iterateOnNode(ITreeOption node); void iterateOnLeaf(ITreeOption leafNode); } @Override public ITreeRoot getTreeRoot() throws BuildException { if (getValueType() != TREE) { throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } if (treeRoot == null) { if (superClass != null) { return superClass.getTreeRoot(); } else { return null; } } return treeRoot; } }