/******************************************************************************* * Copyright (c) 2005, 2016 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 *******************************************************************************/ package org.eclipse.cdt.internal.core.envvar; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; import org.eclipse.cdt.core.envvar.EnvironmentVariable; import org.eclipse.cdt.core.envvar.IContributedEnvironment; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.internal.core.cdtvariables.DefaultVariableContextInfo; import org.eclipse.cdt.internal.core.cdtvariables.EnvironmentVariableSupplier; import org.eclipse.cdt.internal.core.cdtvariables.ICoreVariableContextInfo; import org.eclipse.cdt.utils.cdtvariables.ICdtVariableSupplier; import org.eclipse.cdt.utils.cdtvariables.IVariableContextInfo; import org.eclipse.cdt.utils.cdtvariables.IVariableSubstitutor; import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor; import org.eclipse.core.resources.IBuildConfiguration; /** * This class implements the IEnvironmentVariableProvider interface and provides all * build environment functionality to the MBS * * @since 3.0 */ public class EnvironmentVariableManager implements IEnvironmentVariableManager { private static final String DELIMITER_WIN32 = ";"; //$NON-NLS-1$ private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$ private static EnvironmentVariableManager fInstance = null; // private EnvVarVariableSubstitutor fVariableSubstitutor; public static final UserDefinedEnvironmentSupplier fUserSupplier = new UserDefinedEnvironmentSupplier(); public static final BuildSystemEnvironmentSupplier fExternalSupplier = new BuildSystemEnvironmentSupplier(); public static final EclipseEnvironmentSupplier fEclipseSupplier = new EclipseEnvironmentSupplier(); public static final ToolChainEnvironmentSupplier fToolChainSupplier = new ToolChainEnvironmentSupplier(); public static final BuildConfigEnvironmentSupplier fBuildConfigSupplier = new BuildConfigEnvironmentSupplier(); private ContributedEnvironment fContributedEnvironment; public class EnvVarVariableSubstitutor extends SupplierBasedCdtVariableSubstitutor { private String fDefaultDelimiter; /* public EnvVarMacroSubstitutor(int contextType, Object contextData, String inexistentMacroValue, String listDelimiter) { super(contextType,contextData,inexistentMacroValue,listDelimiter); fDefaultDelimiter = listDelimiter; } */ public EnvVarVariableSubstitutor(IVariableContextInfo contextInfo, String inexistentMacroValue, String listDelimiter) { super(contextInfo, inexistentMacroValue, listDelimiter, null ,inexistentMacroValue); fDefaultDelimiter = listDelimiter; } public IEnvironmentVariable resolveVariable(EnvVarDescriptor var) throws CdtVariableException { String value; if (var == null || (value = var.getValue()) == null || value.length() == 0 || var.getOperation() == IEnvironmentVariable.ENVVAR_REMOVE) return var; String listDelimiter = var.getDelimiter(); if (listDelimiter == null) listDelimiter = fDefaultDelimiter; setListDelimiter(listDelimiter); ICdtVariable macro = EnvironmentVariableSupplier.getInstance().createBuildMacro(var); IVariableContextInfo varMacroInfo = getVarMacroContextInfo(var); int varSupplierNum = getVarMacroSupplierNum(var,varMacroInfo); value = resolveToString(new MacroDescriptor(macro,varMacroInfo,varSupplierNum)); removeResolvedMacro(var.getName()); return new EnvironmentVariable(var.getName(),value,var.getOperation(),var.getDelimiter()); } protected IVariableContextInfo getVarMacroContextInfo(EnvVarDescriptor var) { IEnvironmentContextInfo info = var.getContextInfo(); if (info != null) return getMacroContextInfoForContext(info.getContext()); return null; } protected int getVarMacroSupplierNum(EnvVarDescriptor var, IVariableContextInfo varMacroInfo) { int varSupplierNum = -1; ICdtVariableSupplier macroSuppliers[] = varMacroInfo.getSuppliers(); if (macroSuppliers != null) { for(int i = 0; i < macroSuppliers.length; i++) { if (macroSuppliers[i] instanceof EnvironmentVariableSupplier) { varSupplierNum = i; break; } } } return varSupplierNum; } } protected EnvironmentVariableManager() { fContributedEnvironment = new ContributedEnvironment(this); } public static EnvironmentVariableManager getDefault() { if (fInstance == null) fInstance = new EnvironmentVariableManager(); return fInstance; } /** * @return a variable of a given name or null * the context information is taken from the contextInfo passed */ public static EnvVarDescriptor getVariable(String variableName, IEnvironmentContextInfo contextInfo, boolean includeParentLevels) { if (contextInfo == null) return null; if ((variableName = EnvVarOperationProcessor.normalizeName(variableName)) == null) return null; IEnvironmentContextInfo infos[] = getAllContextInfos(contextInfo); if (!includeParentLevels) { ICoreEnvironmentVariableSupplier suppliers[] = infos[0].getSuppliers(); boolean bVarFound = false; for (ICoreEnvironmentVariableSupplier supplier : suppliers) { if (supplier.getVariable(variableName,infos[0].getContext()) != null) { bVarFound = true; break; } } if (!bVarFound) return null; } IEnvironmentVariable variable = null; IEnvironmentContextInfo varContextInfo = null; int varSupplierNum = -1; ICoreEnvironmentVariableSupplier varSupplier = null; for(int i = infos.length-1 ; i >=0 ; i-- ) { IEnvironmentContextInfo info = infos[i]; ICoreEnvironmentVariableSupplier suppliers[] = info.getSuppliers(); for(int j = suppliers.length-1 ; j >= 0 ; j-- ) { ICoreEnvironmentVariableSupplier supplier = suppliers[j]; IEnvironmentVariable var = supplier.getVariable(variableName,info.getContext()); if (var == null) continue; varContextInfo = info; varSupplierNum = j; varSupplier = supplier; if (variable == null) variable = var; else variable = EnvVarOperationProcessor.performOperation(variable,var); } } if (variable != null) { // if (variable.getOperation() == IEnvironmentVariable.ENVVAR_REMOVE) // return null; return new EnvVarDescriptor(variable,varContextInfo,varSupplierNum,varSupplier); } return null; } @Override public IEnvironmentVariable getVariable(String variableName, ICConfigurationDescription cfg, boolean resolveMacros) { if (variableName == null || variableName.isEmpty()) return null; IEnvironmentContextInfo info = getContextInfo(cfg); EnvVarDescriptor var = getVariable(variableName,info,true); if (var != null && var.getOperation() != IEnvironmentVariable.ENVVAR_REMOVE) { return resolveMacros ? calculateResolvedVariable(var,info) : var; } return null; } @Override public IEnvironmentVariable getVariable(String name, IBuildConfiguration config, boolean resolveMacros) { if (name == null || name.isEmpty()) return null; IEnvironmentContextInfo info = getContextInfo(config); EnvVarDescriptor var = getVariable(name, info, true); if (var != null && var.getOperation() != IEnvironmentVariable.ENVVAR_REMOVE) { return resolveMacros ? calculateResolvedVariable(var, info) : var; } else { return null; } } IEnvironmentContextInfo getDefaultContextInfo(Object level) { DefaultEnvironmentContextInfo info = new DefaultEnvironmentContextInfo(level); if (info.getSuppliers() == null) return null; return info; } /** * @return the context info that should be used for the given level * or null if the the given level is not supported */ public IEnvironmentContextInfo getContextInfo(Object level) { if (level instanceof ICConfigurationDescription) { return fContributedEnvironment.appendEnvironment((ICConfigurationDescription)level) ? getDefaultContextInfo(level) : fContributedEnvironment.getContextInfo(level); } else { return getDefaultContextInfo(level); } } /** * @return a list of defined variables. * the context information is taken from the contextInfo passed */ public static EnvVarCollector getVariables(IEnvironmentContextInfo contextInfo, boolean includeParentLevels) { if (contextInfo == null) return null; IEnvironmentContextInfo infos[] = getAllContextInfos(contextInfo); HashSet<String> set = null; if (!includeParentLevels) { ICoreEnvironmentVariableSupplier suppliers[] = infos[0].getSuppliers(); set = new HashSet<String>(); for(int i = 0; i < suppliers.length; i++) { IEnvironmentVariable vars[] = suppliers[i].getVariables(infos[0].getContext()); if (vars != null) { for (IEnvironmentVariable var : vars) { String name = EnvVarOperationProcessor.normalizeName(var. getName()); if (name != null) set.add(name); } } if (!suppliers[i].appendEnvironment(infos[0].getContext())) break; } if (set.size() == 0) return new EnvVarCollector(); } EnvVarCollector envVarSet = new EnvVarCollector(); for(int i = infos.length-1 ; i >=0 ; i-- ) { IEnvironmentContextInfo info = infos[i]; ICoreEnvironmentVariableSupplier suppliers[] = info.getSuppliers(); for(int j = suppliers.length-1 ; j >= 0 ; j-- ) { ICoreEnvironmentVariableSupplier supplier = suppliers[j]; if (!supplier.appendEnvironment(info.getContext())) { envVarSet.clear(); } IEnvironmentVariable vars[] = null; if (set != null) { List<IEnvironmentVariable> varList = new ArrayList<IEnvironmentVariable>(); Iterator<String> iter = set.iterator(); while(iter.hasNext()) { IEnvironmentVariable var = supplier.getVariable(iter.next(),info.getContext()); if (var != null) varList.add(var); } vars = varList.toArray(new IEnvironmentVariable[varList.size()]); } else{ vars = supplier.getVariables(info.getContext()); } envVarSet.add(vars,info,j, supplier); } } return envVarSet; } @Override public IEnvironmentVariable[] getVariables(ICConfigurationDescription cfg, boolean resolveMacros) { IEnvironmentContextInfo info = getContextInfo(cfg); EnvVarCollector varSet = getVariables(info,true); EnvVarDescriptor vars[] = varSet != null ? varSet.toArray(false) : null; if (vars != null) { if (!resolveMacros) return vars; IEnvironmentVariable resolved[] = new IEnvironmentVariable[vars.length]; for(int i = 0; i < vars.length; i++) resolved[i] = calculateResolvedVariable(vars[i], info); return resolved; } return new EnvVarDescriptor[0]; } @Override public IEnvironmentVariable[] getVariables(IBuildConfiguration config, boolean resolveMacros) { IEnvironmentContextInfo info = getContextInfo(config); EnvVarCollector varSet = getVariables(info, true); EnvVarDescriptor vars[] = varSet != null ? varSet.toArray(false) : null; if (vars != null) { if (!resolveMacros) return vars; IEnvironmentVariable resolved[] = new IEnvironmentVariable[vars.length]; for (int i = 0; i < vars.length; i++) { resolved[i] = calculateResolvedVariable(vars[i], info); } return resolved; } return null; } /** * @return an array of the IContextInfo that holds the context informations * starting from the one passed to this method and including all subsequent parents */ public static IEnvironmentContextInfo[] getAllContextInfos(IEnvironmentContextInfo contextInfo) { if (contextInfo == null) return null; List<IEnvironmentContextInfo> list = new ArrayList<IEnvironmentContextInfo>(); list.add(contextInfo); while((contextInfo = contextInfo.getNext()) != null) list.add(contextInfo); return list.toArray(new IEnvironmentContextInfo[list.size()]); } private boolean isWin32() { String os = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ if (os.startsWith("windows ")) //$NON-NLS-1$ return true; return false; } @Override public String getDefaultDelimiter() { return isWin32() ? DELIMITER_WIN32 : DELIMITER_UNIX; } @Override public boolean isVariableCaseSensitive() { return !isWin32(); } public ICoreEnvironmentVariableSupplier[] getSuppliers(Object level) { IEnvironmentContextInfo info = getContextInfo(level); if (info != null) return info.getSuppliers(); return null; } /** * @return true if the first passed contextInfo is the child of the second one */ public boolean checkParentContextRelation(IEnvironmentContextInfo child, IEnvironmentContextInfo parent) { if (child == null || parent == null) return false; IEnvironmentContextInfo enumInfo = child; do{ if (parent.getContext() == enumInfo.getContext()) return true; }while((enumInfo = enumInfo.getNext()) != null); return false; } public IEnvironmentVariable calculateResolvedVariable(EnvVarDescriptor des, IEnvironmentContextInfo info) { if (des == null || info == null) return null; return calculateResolvedVariable(des,getVariableSubstitutor(getMacroContextInfoForContext(info.getContext()),""," ")); //$NON-NLS-1$ //$NON-NLS-2$ } public IEnvironmentVariable calculateResolvedVariable(EnvVarDescriptor des, IVariableSubstitutor sub) { if (des == null) return null; IEnvironmentVariable var = des; try{ if (sub instanceof EnvVarVariableSubstitutor) var = ((EnvVarVariableSubstitutor)sub).resolveVariable(des); else if (des.getOperation() != IEnvironmentVariable.ENVVAR_REMOVE) { String name = des.getName(); var = new EnvironmentVariable(name,sub.resolveToString(name),des.getOperation(),des.getDelimiter()); } } catch (CdtVariableException e) { } return var; } protected int getMacroContextTypeFromContext(Object context) { if (context instanceof ICConfigurationDescription) return ICoreVariableContextInfo.CONTEXT_CONFIGURATION; else return ICoreVariableContextInfo.CONTEXT_WORKSPACE; } public ICoreVariableContextInfo getMacroContextInfoForContext(Object context) { return new DefaultVariableContextInfo(getMacroContextTypeFromContext(context),context); } public IVariableSubstitutor getVariableSubstitutor(IVariableContextInfo info, String inexistentMacroValue, String listDelimiter) { return new EnvVarVariableSubstitutor(info,inexistentMacroValue,listDelimiter); // if (fVariableSubstitutor == null) // fVariableSubstitutor = new EnvVarVariableSubstitutor(info,inexistentMacroValue,listDelimiter); // else { // try { // fVariableSubstitutor.setMacroContextInfo(info); // fVariableSubstitutor.setInexistentMacroValue(inexistentMacroValue); // fVariableSubstitutor.setListDelimiter(listDelimiter); // } catch (CdtVariableException e) { // fVariableSubstitutor = new EnvVarVariableSubstitutor(info,inexistentMacroValue,listDelimiter); // } // } // return fVariableSubstitutor; } @Override public IContributedEnvironment getContributedEnvironment() { return fContributedEnvironment; } @Override public void setEnvironment(Map<String, String> env, IBuildConfiguration config, boolean resolveMacros) { for (IEnvironmentVariable var : getVariables(config, resolveMacros)) { switch (var.getOperation()) { case IEnvironmentVariable.ENVVAR_REPLACE: env.put(var.getName(), var.getValue()); break; case IEnvironmentVariable.ENVVAR_APPEND: env.put(var.getName(), env.get(var.getName()) + var.getDelimiter() + var.getValue()); break; case IEnvironmentVariable.ENVVAR_PREPEND: env.put(var.getName(), var.getValue() + var.getDelimiter() + env.get(var.getName())); break; case IEnvironmentVariable.ENVVAR_REMOVE: env.remove(var.getName()); break; } } } }