/*******************************************************************************
* 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;
}
}
}
}