/*******************************************************************************
* Copyright (c) 2005, 2008 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 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;
/**
* This class implements the IEnvironmentVariableProvider interface and provides all
* build environment funvtionality 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();
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();
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;
}
/*
* returns a variable of a given name or null
* the context information is taken from the contextInfo passed
* @see org.eclipse.cdt.managedbuilder.internal.envvar.IContextInfo
*/
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;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider#getVariable()
*/
public IEnvironmentVariable getVariable(String variableName,
ICConfigurationDescription cfg, boolean resolveMacros) {
if(variableName == null || "".equals(variableName)) //$NON-NLS-1$
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;
}
IEnvironmentContextInfo getDefaultContextInfo(Object level){
DefaultEnvironmentContextInfo info = new DefaultEnvironmentContextInfo(level);
if(info.getSuppliers() == null)
return null;
return info;
}
/*
* returns 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);
return getDefaultContextInfo(level);
}
/*
* returns a list of defined variables.
* the context information is taken from the contextInfo passed
* @see org.eclipse.cdt.managedbuilder.internal.envvar.IContextInfo
*/
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;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider#getVariables()
*/
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];
}
/*
* returns 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;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider#getDefaultDelimiter()
*/
public String getDefaultDelimiter() {
return isWin32() ? DELIMITER_WIN32 : DELIMITER_UNIX;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider#isVariableCaseSensitive()
*/
public boolean isVariableCaseSensitive() {
return !isWin32();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider#getSuppliers()
*/
public ICoreEnvironmentVariableSupplier[] getSuppliers(Object level) {
IEnvironmentContextInfo info = getContextInfo(level);
if(info != null)
return info.getSuppliers();
return null;
}
/*
* returns 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;
}
public IContributedEnvironment getContributedEnvironment() {
return fContributedEnvironment;
}
}