/*******************************************************************************
* 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.managedbuilder.internal.envvar;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
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.envvar.EnvVarCollector;
import org.eclipse.cdt.managedbuilder.core.IBuildPathResolver;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IEnvVarBuildPath;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentBuildPathsChangeListener;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableSupplier;
import org.eclipse.cdt.utils.envvar.EnvVarOperationProcessor;
/**
* This class implements the IEnvironmentVariableProvider interface and provides all
* build environment functionality to the MBS
*
* @since 3.0
*/
public class EnvironmentVariableProvider implements IEnvironmentVariableProvider {
// private static final QualifiedName fBuildPathVarProperty = new QualifiedName(ManagedBuilderCorePlugin.getUniqueIdentifier(), "buildPathVar"); //$NON-NLS-1$
// private static final String DELIMITER_WIN32 = ";"; //$NON-NLS-1$
// private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
private static EnvironmentVariableProvider fInstance = null;
private List<IEnvironmentBuildPathsChangeListener> fListeners = null;
private IEnvironmentVariableManager fMngr;
private boolean fBuildPathVarCheckAllowed;
private StoredBuildPathEnvironmentContainer fIncludeStoredBuildPathVariables;
private StoredBuildPathEnvironmentContainer fLibraryStoredBuildPathVariables;
/**
* This class is used by the EnvironmentVariableProvider to calculate the build paths
* in case a tool-integrator did not provide the special logic for obtaining the build
* paths from environment variable values
*
* @since 3.0
*/
static public class DefaultBuildPathResolver implements IBuildPathResolver {
private String fDelimiter;
public DefaultBuildPathResolver(String delimiter) {
fDelimiter = delimiter;
}
@Override
public String[] resolveBuildPaths(int pathType, String variableName, String variableValue, IConfiguration configuration) {
if (fDelimiter == null || fDelimiter.isEmpty())
return new String[]{variableValue};
List<String> list = EnvVarOperationProcessor.convertToList(variableValue,fDelimiter);
return list.toArray(new String[list.size()]);
}
}
protected EnvironmentVariableProvider(IEnvironmentVariableManager mngr) {
fMngr = mngr;
}
public static EnvironmentVariableProvider getDefault() {
if (fInstance == null) {
fInstance = new EnvironmentVariableProvider(CCorePlugin.getDefault().getBuildEnvironmentManager());
fInstance.fBuildPathVarCheckAllowed = true;
}
return fInstance;
}
@Override
public IBuildEnvironmentVariable getVariable(String variableName, Object level, boolean includeParentLevels, boolean resolveMacros) {
if (variableName == null || variableName.isEmpty())
return null;
if (level instanceof IConfiguration) {
return wrap(getVariable(variableName, (IConfiguration)level, resolveMacros));
}
return null;
}
@Override
public IEnvironmentVariable getVariable(String variableName, IConfiguration cfg, boolean resolveMacros) {
return getVariable(variableName, cfg, resolveMacros, true);
}
public IEnvironmentVariable getVariable(String variableName, IConfiguration cfg, boolean resolveMacros, boolean checkBuildPaths) {
ICConfigurationDescription des = ManagedBuildManager.getDescriptionForConfiguration(cfg);
if (des != null) {
IEnvironmentVariable variable = fMngr.getVariable(variableName, des, resolveMacros);
if (checkBuildPaths && resolveMacros && fBuildPathVarCheckAllowed)
checkBuildPathVariable(cfg, variableName, variable);
return variable;
}
return null;
}
@Override
public IEnvironmentVariable[] getVariables(IConfiguration cfg, boolean resolveMacros) {
return getVariables(cfg, resolveMacros, true);
}
public IEnvironmentVariable[] getVariables(IConfiguration cfg, boolean resolveMacros, boolean checkBuildPaths) {
ICConfigurationDescription des = ManagedBuildManager.getDescriptionForConfiguration(cfg);
if (des != null) {
IEnvironmentVariable vars[] = fMngr.getVariables(des, resolveMacros);
if (checkBuildPaths && resolveMacros && fBuildPathVarCheckAllowed)
checkBuildPathVariables(cfg,vars);
return vars;
}
return new IBuildEnvironmentVariable[0];
}
public static IBuildEnvironmentVariable wrap(IEnvironmentVariable var) {
if (var == null)
return null;
if (var instanceof IBuildEnvironmentVariable)
return (IBuildEnvironmentVariable)var;
return new BuildEnvVar(var);
}
public static IBuildEnvironmentVariable[] wrap(IEnvironmentVariable vars[]) {
if (vars == null)
return null;
if (vars instanceof IBuildEnvironmentVariable[])
return (IBuildEnvironmentVariable[])vars;
IBuildEnvironmentVariable[] buildVars = new IBuildEnvironmentVariable[vars.length];
for(int i = 0; i < vars.length; i++) {
buildVars[i] = wrap(vars[i]);
}
return buildVars;
}
/* protected ICConfigurationDescription getDescription(IConfiguration cfg) {
IProject project = cfg.getOwner().getProject();
ICProjectDescription des = CoreModel.getDefault().getProjectDescription(project, false);
if (des != null) {
return des.getConfigurationById(cfg.getId());
}
return null;
}
*/
@Override
public IBuildEnvironmentVariable[] getVariables(Object level, boolean includeParentLevels, boolean resolveMacros) {
if (level instanceof IConfiguration) {
return wrap(getVariables((IConfiguration)level, resolveMacros));
}
return new IBuildEnvironmentVariable[0];
}
@Override
public String getDefaultDelimiter() {
return fMngr.getDefaultDelimiter();
}
@Override
public boolean isVariableCaseSensitive() {
return fMngr.isVariableCaseSensitive();
}
@Override
public IEnvironmentVariableSupplier[] getSuppliers(Object level) {
return null;
}
@Override
public String[] getBuildPaths(IConfiguration configuration, int buildPathType) {
ITool tools[] = configuration.getFilteredTools();
List<String> list = new ArrayList<String>();
for (ITool tool : tools) {
IEnvVarBuildPath pathDescriptors[] = tool.getEnvVarBuildPaths();
if (pathDescriptors == null || pathDescriptors.length == 0)
continue;
for (IEnvVarBuildPath curPathDes : pathDescriptors) {
if (curPathDes.getType() != buildPathType)
continue;
String vars[] = curPathDes.getVariableNames();
if (vars == null || vars.length == 0)
continue;
IBuildPathResolver pathResolver = curPathDes.getBuildPathResolver();
if (pathResolver == null) {
String delimiter = curPathDes.getPathDelimiter();
if (delimiter == null)
delimiter = getDefaultDelimiter();
pathResolver = new DefaultBuildPathResolver(delimiter);
}
for (String varName : vars) {
IEnvironmentVariable var = getVariable(varName,configuration,true, false);
if (var == null)
continue;
String varValue = var.getValue();
String paths[] = pathResolver.resolveBuildPaths(buildPathType,varName,varValue,configuration);
if (paths != null && paths.length != 0)
list.addAll(Arrays.asList(paths));
}
}
}
return list.toArray(new String[list.size()]);
}
/**
* @return a list of registered listeners
*/
private List<IEnvironmentBuildPathsChangeListener> getListeners() {
if (fListeners == null)
fListeners = new ArrayList<IEnvironmentBuildPathsChangeListener>();
return fListeners;
}
/**
* notifies registered listeners
*/
private void notifyListeners(IConfiguration configuration, int buildPathType) {
List<IEnvironmentBuildPathsChangeListener> listeners = getListeners();
for (IEnvironmentBuildPathsChangeListener listener : listeners) {
listener.buildPathsChanged(configuration,buildPathType);
}
}
@Override
public synchronized void subscribe(IEnvironmentBuildPathsChangeListener listener) {
if (listener == null)
return;
List<IEnvironmentBuildPathsChangeListener> listeners = getListeners();
if (!listeners.contains(listener))
listeners.add(listener);
}
@Override
public synchronized void unsubscribe(IEnvironmentBuildPathsChangeListener listener) {
if (listener == null)
return;
List<IEnvironmentBuildPathsChangeListener> listeners = getListeners();
listeners.remove(listener);
}
/**
* performs a check of the build path variables for the given configuration
* If the build variables are changed, the notification is sent
*/
public void checkBuildPathVariables(IConfiguration configuration) {
checkBuildPathVariables(configuration, getVariables(configuration ,true, false));
}
/**
* performs a check of the build path variables of the specified type
* for the given configuration
* If the build variables are changed, the notification is sent
*/
public void checkBuildPathVariables(IConfiguration configuration,int buildPathType) {
EnvVarCollector cr = new EnvVarCollector();
cr.add(getVariables(configuration, true, false));
checkBuildPathVariables(configuration,buildPathType,cr);
}
/**
* performs a check of the build path variables
* for the given configuration given the set of the variables
* defined for this configuration
* If the build variables are changed, the notification is sent
*/
protected void checkBuildPathVariables(IConfiguration configuration, IEnvironmentVariable vars[]) {
EnvVarCollector cr = new EnvVarCollector();
cr.add(vars);
checkBuildPathVariables(configuration,IEnvVarBuildPath.BUILDPATH_INCLUDE,cr);
checkBuildPathVariables(configuration,IEnvVarBuildPath.BUILDPATH_LIBRARY,cr);
}
/**
* performs a check of whether the given variable is the build path variable
* and if true checks whether it is changed.
* In the case of it is changed all other build path variables are checked
* and notification is sent.
* If it is not changed, other build path variables are not checked
* In the case of the given variable is not the build path one, this method does nothing
*/
protected void checkBuildPathVariable(IConfiguration configuration, String varName, IEnvironmentVariable var) {
checkBuildPathVariable(configuration, IEnvVarBuildPath.BUILDPATH_INCLUDE, varName, var);
checkBuildPathVariable(configuration, IEnvVarBuildPath.BUILDPATH_LIBRARY, varName, var);
}
/**
* performs a check of whether the given variable is the build path variable
* of the specified type and if true checks whether it is changed.
* In the case of it is changed all other build path variables of that type are checked
* and notification is sent.
* If it is not changed, other build path variables are not checked
* In the case of the given variable is not the build path one, this method does nothing
*/
protected void checkBuildPathVariable(IConfiguration configuration, int buildPathType, String varName, IEnvironmentVariable var) {
StoredBuildPathEnvironmentContainer buildPathVars = getStoredBuildPathVariables(buildPathType);
if (buildPathVars == null)
return;
if (buildPathVars.isVariableChanged(varName,var,configuration)) {
EnvVarCollector cr = new EnvVarCollector();
cr.add(getVariables(configuration, true, false));
buildPathVars.synchronize(cr,configuration);
notifyListeners(configuration, buildPathType);
}
}
/**
* performs a check of the build path variables of the specified type
* for the given configuration given the set of the variables
* defined for this configuration.
* If the build variables are changed, the notification is sent
*/
protected void checkBuildPathVariables(IConfiguration configuration, int buildPathType, EnvVarCollector varSet) {
StoredBuildPathEnvironmentContainer buildPathVars = getStoredBuildPathVariables(buildPathType);
if (buildPathVars == null)
return;
if (buildPathVars.checkBuildPathChange(varSet,configuration)) {
notifyListeners(configuration, buildPathType);
}
}
/**
* returns the container of the build variables of the specified type
*/
protected StoredBuildPathEnvironmentContainer getStoredBuildPathVariables(int buildPathType) {
return buildPathType == IEnvVarBuildPath.BUILDPATH_LIBRARY ?
getStoredLibraryBuildPathVariables() :
getStoredIncludeBuildPathVariables();
}
/**
* returns the container of the Include path variables
*/
protected StoredBuildPathEnvironmentContainer getStoredIncludeBuildPathVariables() {
if (fIncludeStoredBuildPathVariables == null)
fIncludeStoredBuildPathVariables = new StoredBuildPathEnvironmentContainer(IEnvVarBuildPath.BUILDPATH_INCLUDE);
return fIncludeStoredBuildPathVariables;
}
/**
* returns the container of the Library path variables
*/
protected StoredBuildPathEnvironmentContainer getStoredLibraryBuildPathVariables() {
if (fLibraryStoredBuildPathVariables == null)
fLibraryStoredBuildPathVariables = new StoredBuildPathEnvironmentContainer(IEnvVarBuildPath.BUILDPATH_LIBRARY);
return fLibraryStoredBuildPathVariables;
}
}