/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.configuration;
import com.google.common.collect.ImmutableMap;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Holds environment variables configuration:
* <ul>
* <li>list of user-defined environment variables</li>
* <li>boolean flag - whether to pass system environment</li>
* </ul>
* Instances of this class are immutable objects, so it can be safely passed across threads.
*/
public class EnvironmentVariablesData {
public static final EnvironmentVariablesData DEFAULT = new EnvironmentVariablesData(ImmutableMap.of(), true);
@NonNls private static final String ENVS = "envs";
@NonNls private static final String PASS_PARENT_ENVS = "pass-parent-envs";
@NonNls private static final String ENV = EnvironmentVariablesComponent.ENV;
@NonNls private static final String NAME = EnvironmentVariablesComponent.NAME;
@NonNls private static final String VALUE = EnvironmentVariablesComponent.VALUE;
private final ImmutableMap<String, String> myEnvs;
private final boolean myPassParentEnvs;
private EnvironmentVariablesData(@NotNull Map<String, String> envs, boolean passParentEnvs) {
myEnvs = ImmutableMap.copyOf(envs);
myPassParentEnvs = passParentEnvs;
}
/**
* @return immutable Map instance containing user-defined environment variables (iteration order is reliable user-specified)
*/
@NotNull
public Map<String, String> getEnvs() {
return myEnvs;
}
public boolean isPassParentEnvs() {
return myPassParentEnvs;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EnvironmentVariablesData data = (EnvironmentVariablesData)o;
return myPassParentEnvs == data.myPassParentEnvs && myEnvs.equals(data.myEnvs);
}
@Override
public int hashCode() {
int result = myEnvs.hashCode();
result = 31 * result + (myPassParentEnvs ? 1 : 0);
return result;
}
@Override
public String toString() {
return "envs=" + myEnvs + ", passParentEnvs=" + myPassParentEnvs;
}
@NotNull
public static EnvironmentVariablesData readExternal(@NotNull Element element) {
Element envsElement = element.getChild(ENVS);
if (envsElement == null) {
return DEFAULT;
}
Map<String, String> envs = ImmutableMap.of();
String passParentEnvsStr = envsElement.getAttributeValue(PASS_PARENT_ENVS);
boolean passParentEnvs = passParentEnvsStr == null || Boolean.parseBoolean(passParentEnvsStr);
for (Element envElement : envsElement.getChildren(ENV)) {
String envName = envElement.getAttributeValue(NAME);
String envValue = envElement.getAttributeValue(VALUE);
if (envName != null && envValue != null) {
if (envs.isEmpty()) {
envs = ContainerUtil.newLinkedHashMap();
}
envs.put(envName, envValue);
}
}
return create(envs, passParentEnvs);
}
public void writeExternal(@NotNull Element parent) {
Element envsElement = new Element(ENVS);
if (!myPassParentEnvs) {
// Avoid writing pass-parent-envs="true" to minimize changes in xml comparing it to xml written by
// com.intellij.execution.configuration.EnvironmentVariablesComponent.writeExternal
envsElement.setAttribute(PASS_PARENT_ENVS, Boolean.FALSE.toString());
}
for (Map.Entry<String, String> entry : myEnvs.entrySet()) {
Element envElement = new Element(ENV);
envElement.setAttribute(NAME, entry.getKey());
envElement.setAttribute(VALUE, entry.getValue());
envsElement.addContent(envElement);
}
parent.addContent(envsElement);
}
public void configureCommandLine(@NotNull GeneralCommandLine commandLine, boolean consoleParentEnvs) {
if (myPassParentEnvs) {
commandLine.withParentEnvironmentType(consoleParentEnvs ? GeneralCommandLine.ParentEnvironmentType.CONSOLE
: GeneralCommandLine.ParentEnvironmentType.SYSTEM);
}
else {
commandLine.withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.NONE);
}
commandLine.withEnvironment(myEnvs);
}
/**
* @param envs Map instance containing user-defined environment variables
* (iteration order should be reliable user-specified, like {@link LinkedHashMap} or {@link ImmutableMap})
* @param passParentEnvs true if system environment should be passed
*/
@NotNull
public static EnvironmentVariablesData create(@NotNull Map<String, String> envs, boolean passParentEnvs) {
if (passParentEnvs && envs.isEmpty()) {
return DEFAULT;
}
return new EnvironmentVariablesData(envs, passParentEnvs);
}
}