/******************************************************************************* * Copyright (c) 2007, 2011 Intel Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Intel Corporation - Initial API and implementation * IBM Corporation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.internal.core; import java.util.Arrays; import java.util.List; import java.util.Set; import org.eclipse.cdt.core.settings.model.ICSettingBase; import org.eclipse.cdt.core.settings.model.ICStorageElement; import org.eclipse.cdt.core.settings.model.extension.CResourceData; 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.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IFileInfo; import org.eclipse.cdt.managedbuilder.core.IFolderInfo; import org.eclipse.cdt.managedbuilder.core.IHoldsOptions; import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; import org.eclipse.cdt.managedbuilder.core.IResourceInfo; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.core.OptionStringValue; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; public abstract class ResourceInfo extends BuildObject implements IResourceInfo { private Configuration config; private IPath path; boolean isDirty; boolean needsRebuild; private ResourceInfoContainer rcInfo; private CResourceData resourceData; ResourceInfo(IConfiguration cfg, IManagedConfigElement element, boolean hasBody){ config = (Configuration)cfg; if(hasBody) loadFromManifest(element); } ResourceInfo(IConfiguration cfg, ResourceInfo base, String id) { config = (Configuration)cfg; path = normalizePath(base.path); setId(id); setName(base.getName()); if(id.equals(base.getId())){ isDirty = base.isDirty; needsRebuild = base.needsRebuild; } else { needsRebuild = true; isDirty = true; } } public boolean isRoot(){ return path.segmentCount() == 0; } ResourceInfo(IConfiguration cfg, IPath path, String id, String name) { config = (Configuration)cfg; path = normalizePath(path); this.path = path; setId(id); setName(name); } ResourceInfo(IFileInfo base, IPath path, String id, String name) { config = (Configuration)base.getParent(); setId(id); setName(name); path = normalizePath(path); this.path = path; needsRebuild = true; isDirty = true; } ResourceInfo(FolderInfo base, IPath path, String id, String name) { config = (Configuration)base.getParent(); setId(id); setName(name); path = normalizePath(path); this.path = path; needsRebuild = true; isDirty = true; } ResourceInfo(IConfiguration cfg, ICStorageElement element, boolean hasBody){ config = (Configuration)cfg; if(hasBody) loadFromProject(element); } private void loadFromManifest(IManagedConfigElement element) { // id setId(SafeStringInterner.safeIntern(element.getAttribute(ID))); // Get the name setName(SafeStringInterner.safeIntern(element.getAttribute(NAME))); // resourcePath String tmp = element.getAttribute(RESOURCE_PATH); if(tmp != null){ path = new Path(tmp); if(IResourceConfiguration.RESOURCE_CONFIGURATION_ELEMENT_NAME.equals(element.getName())){ path = path.removeFirstSegments(1); } path = normalizePath(path); } else { Status status = new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "ResourceInfo.loadFromManifest() : resourcePath=NULL", null); //$NON-NLS-1$ ManagedBuilderCorePlugin.log(status); } // exclude String excludeStr = element.getAttribute(EXCLUDE); if (excludeStr != null){ config.setExcluded(getPath(), isFolderInfo(), ("true".equals(excludeStr))); //$NON-NLS-1$ } } private void loadFromProject(ICStorageElement element) { // id (unique, do not intern) setId(element.getAttribute(ID)); // name if (element.getAttribute(NAME) != null) { setName(SafeStringInterner.safeIntern(element.getAttribute(NAME))); } // resourcePath if (element.getAttribute(RESOURCE_PATH) != null) { String tmp = element.getAttribute(RESOURCE_PATH); if(tmp != null){ path = new Path(tmp); if(IResourceConfiguration.RESOURCE_CONFIGURATION_ELEMENT_NAME.equals(element.getName())){ path = path.removeFirstSegments(1); } path = normalizePath(path); } else { Status status = new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "ResourceInfo.loadFromProject() : resourcePath=NULL", null); //$NON-NLS-1$ ManagedBuilderCorePlugin.log(status); } } // exclude if (element.getAttribute(EXCLUDE) != null) { String excludeStr = element.getAttribute(EXCLUDE); if (excludeStr != null){ config.setExcluded(getPath(), isFolderInfo(), ("true".equals(excludeStr))); //$NON-NLS-1$ } } } public IConfiguration getParent() { return config; } public IPath getPath() { return normalizePath(path); } public boolean isDirty() { return isDirty; } public boolean isExcluded() { return config.isExcluded(getPath()); } public boolean needsRebuild() { return needsRebuild; } public void setDirty(boolean dirty) { isDirty = dirty; } public void setExclude(boolean excluded) { if(isExcluded() == excluded) return; config.setExcluded(getPath(), isFolderInfo(), excluded); setDirty(true); setRebuildState(true); } public boolean canExclude(boolean exclude) { return config.canExclude(getPath(), isFolderInfo(), exclude); } public abstract boolean isFolderInfo(); public void setPath(IPath p) { p = normalizePath(p); if(path == null) path = p; else if (!p.equals(normalizePath(this.path))) { ResourceInfoContainer info = getRcInfo(); info.changeCurrentPath(p, true); this.path = p; setDirty(true); setRebuildState(true); } } private ResourceInfoContainer getRcInfo(){ if(rcInfo == null) rcInfo = (config).getRcInfoContainer(this); return rcInfo; } public void setRebuildState(boolean rebuild) { needsRebuild = rebuild; } void serialize(ICStorageElement element){ element.setAttribute(IBuildObject.ID, id); if (name != null) { element.setAttribute(IBuildObject.NAME, name); } if (path != null) { element.setAttribute(IResourceInfo.RESOURCE_PATH, path.toString()); } } void resolveReferences() {} public CResourceData getResourceData(){ return resourceData; } protected void setResourceData(CResourceData data){ resourceData = data; } void removed(){ config = null; } public boolean isValid(){ return config != null; } private void propagate(IHoldsOptions parent, IOption option, Object oldValue, Object value) { if (! (parent instanceof ITool)) return; ITool tool = (ITool)parent; String sup = option.getId(); IOption op = option; while (op.getSuperClass() != null) { op = op.getSuperClass(); sup = op.getId(); } for (IResourceInfo ri : getChildResourceInfos()) { for (ITool t : ri.getTools()) { if (t.getDefaultInputExtension() != tool.getDefaultInputExtension()) continue; op = t.getOptionBySuperClassId(sup); if (op == null) continue; try { if (value instanceof Boolean) { boolean b = ((Boolean)oldValue).booleanValue(); if (b == op.getBooleanValue() && b != ((Boolean)value).booleanValue()) ri.setOption(t, op, ((Boolean)value).booleanValue()); } else if (value instanceof String) { String s = (String)oldValue; if (s.equals(op.getStringValue()) && ! s.equals(value)) ri.setOption(t, op, (String)value); } else if (value instanceof String[]) { String[] s = (String[])oldValue; if (Arrays.equals(s, op.getStringListValue()) && ! Arrays.equals(s, (String[])value)) ri.setOption(t, op, (String[])value); } else if (value instanceof OptionStringValue[]) { OptionStringValue[] s = (OptionStringValue[])oldValue; if (Arrays.equals(s, op.getBasicStringListValueElements()) && ! Arrays.equals(s, (OptionStringValue[])value)) ri.setOption(t, op, (OptionStringValue[])value); } break; } catch (BuildException e) {} } } } public IOption setOption(IHoldsOptions parent, IOption option, boolean value) throws BuildException { // Is there a change? IOption retOpt = option; boolean oldVal = option.getBooleanValue(); if (oldVal != value) { retOpt = parent.getOptionToSet(option, false); retOpt.setValue(value); propagate(parent, option, (oldVal ? Boolean.TRUE : Boolean.FALSE), (value ? Boolean.TRUE : Boolean.FALSE)); NotificationManager.getInstance().optionChanged(this, parent, option, new Boolean(oldVal)); } return retOpt; } public IOption setOption(IHoldsOptions parent, IOption option, String value) throws BuildException { IOption retOpt = option; String oldValue; oldValue = option.getStringValue(); if (oldValue != null && !oldValue.equals(value)) { retOpt = parent.getOptionToSet(option, false); retOpt.setValue(value); propagate(parent, option, oldValue, value); NotificationManager.getInstance().optionChanged(this, parent, option, oldValue); } return retOpt; } public IOption setOption(IHoldsOptions parent, IOption option, String[] value) throws BuildException { IOption retOpt = option; // Is there a change? String[] oldValue; switch (option.getBasicValueType()) { case IOption.STRING_LIST : oldValue = option.getBasicStringListValue(); break; default : oldValue = new String[0]; break; } if(!Arrays.equals(value, oldValue)) { retOpt = parent.getOptionToSet(option, false); retOpt.setValue(value); propagate(parent, option, oldValue, value); NotificationManager.getInstance().optionChanged(this, parent, option, oldValue); } return retOpt; } public IOption setOption(IHoldsOptions parent, IOption option, OptionStringValue[] value) throws BuildException { IOption retOpt = option; // Is there a change? OptionStringValue[] oldValue; switch (option.getBasicValueType()) { case IOption.STRING_LIST : oldValue = ((Option)option).getBasicStringListValueElements(); break; default : oldValue = new OptionStringValue[0]; break; } if(!Arrays.equals(value, oldValue)) { retOpt = parent.getOptionToSet(option, false); ((Option)retOpt).setValue(value); propagate(parent, option, oldValue, value); NotificationManager.getInstance().optionChanged(this, parent, option, oldValue); } return retOpt; } public void propertiesChanged(){ if(isExtensionElement()) return; ITool tools[] = getTools(); for (ITool tool : tools) { ((Tool)tool).propertiesChanged(); } } public abstract boolean isExtensionElement(); public abstract Set<String> contributeErrorParsers(Set<String> set); protected Set<String> contributeErrorParsers(ITool[] tools, Set<String> set){ for (ITool tool : tools) { set = ((Tool)tool).contributeErrorParsers(set); } return set; } public abstract void resetErrorParsers(); protected void resetErrorParsers(ITool tools[]){ for (ITool tool : tools) { ((Tool)tool).resetErrorParsers(); } } abstract void removeErrorParsers(Set<String> set); protected void removeErrorParsers(ITool tools[], Set<String> set){ for (ITool tool : tools) { ((Tool)tool).removeErrorParsers(set); } } public ITool getToolById(String id) { ITool[] tools = getTools(); for (ITool tool : tools) { if(id.equals(tool.getId())) return tool; } return null; } public static IPath normalizePath(IPath path){ return path.makeRelative(); } public ResourceInfo getParentResourceInfo(){ if(isRoot()) return null; IPath path = getPath(); path = path.removeLastSegments(1); return (ResourceInfo)getParent().getResourceInfo(path, false); } public IFolderInfo getParentFolderInfo(){ ResourceInfo parentRc = getParentResourceInfo(); for(; parentRc != null && !parentRc.isFolderInfo(); parentRc = parentRc.getParentResourceInfo()) { // empty body, loop is to find parent only } return (IFolderInfo)parentRc; } abstract void resolveProjectReferences(boolean onLoad); abstract public boolean hasCustomSettings(); public ToolListModificationInfo getToolListModificationInfo(ITool[] tools) { ITool[] curTools = getTools(); return ToolChainModificationHelper.getModificationInfo(this, curTools, tools); } static ITool[][] getRealPairs(ITool[] tools){ ITool[][] pairs = new ITool[tools.length][]; for(int i = 0; i < tools.length; i++){ ITool[] pair = new ITool[2]; pair[0] = ManagedBuildManager.getRealTool(tools[i]); if(pair[0] == null) pair[0] = tools[i]; pair[1] = tools[i]; pairs[i] = pair; } return pairs; } abstract void applyToolsInternal(ITool[] resultingTools, ToolListModificationInfo info); void doApply(ToolListModificationInfo info){ ITool[] resulting = info.getResultingTools(); ITool[] removed = info.getRemovedTools(); BuildSettingsUtil.disconnectDepentents(getParent(), removed); applyToolsInternal(resulting, info); performPostModificationAdjustments(info); } void performPostModificationAdjustments(ToolListModificationInfo info){ propertiesChanged(); } public IResourceInfo[] getDirectChildResourceInfos(){ ResourceInfoContainer cr = getRcInfo(); return cr.getDirectChildResourceInfos(); } public IResourceInfo[] getChildResourceInfos(){ ResourceInfoContainer cr = getRcInfo(); return cr.getResourceInfos(); } public List<IResourceInfo> getChildResourceInfoList(boolean includeCurrent){ return getRcInfo().getRcInfoList(ICSettingBase.SETTING_FILE | ICSettingBase.SETTING_FOLDER, includeCurrent); } }