Browse Source

SQSCANNER-9 Allow to use variables in the configuration file

tags/2.9.0.670
Duarte Meneses 7 years ago
parent
commit
df0aa9bad9

+ 7
- 0
src/main/java/org/sonarsource/scanner/cli/Conf.java View File

@@ -62,12 +62,19 @@ class Conf {
result.putAll(System.getProperties());
result.putAll(loadEnvironmentProperties());
result.putAll(cli.properties());
result = resolve(result);
// root project base directory must be present and be absolute
result.setProperty(PROPERTY_PROJECT_BASEDIR, getRootProjectBaseDir(result).toString());
result.remove(PROJECT_HOME);
return result;
}

private Properties resolve(Properties props) {
PropertyResolver resolver = new PropertyResolver(props, env);
return resolver.resolve();
}

private Properties loadEnvironmentProperties() {
return Utils.loadEnvironmentProperties(env);
}

+ 104
- 0
src/main/java/org/sonarsource/scanner/cli/PropertyResolver.java View File

@@ -0,0 +1,104 @@
/*
* SonarQube Scanner
* Copyright (C) 2011-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonarsource.scanner.cli;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PropertyResolver {
private static final Pattern placeholderPattern = Pattern.compile("\\$\\{([\\w\\.]+)\\}|\\$([\\w\\.]+)");
private final Properties props;
private final Properties resolved;
private final List<String> queue;
private Map<String, String> env;

public PropertyResolver(Properties props, Map<String, String> env) {
this.props = props;
this.env = env;
this.resolved = new Properties();
this.queue = new LinkedList<>();
}

public Properties resolve() {
for (Map.Entry<Object, Object> e : props.entrySet()) {
if (resolved.containsKey(e.getKey())) {
continue;
}
resolveProperty((String) e.getKey());
}

return resolved;
}

private String getValue(String key) {
String propValue;

if (key.startsWith("env.")) {
String envKey = key.substring(4);
propValue = env.get(envKey);
} else {
propValue = props.getProperty(key);
}

return propValue != null ? propValue : "";
}

private String resolveProperty(String propKey) {
String propValue = getValue(propKey);
if (propValue.isEmpty()) {
return propValue;
}

Matcher m = placeholderPattern.matcher(propValue);
StringBuffer sb = new StringBuffer();

while (m.find()) {
String varName = (null == m.group(1)) ? m.group(2) : m.group(1);
if (queue.contains(varName)) {
throw new IllegalArgumentException("Found a loop resolving place holders in properties, for variable: " + varName);
}

String placeholderValue = resolveVar(varName);
m.appendReplacement(sb, Matcher.quoteReplacement(placeholderValue));
}
m.appendTail(sb);

String resolvedPropValue = sb.toString();
resolved.setProperty(propKey, resolvedPropValue);
return resolvedPropValue;
}

private String resolveVar(String varName) {
String placeholderValue;
if (resolved.containsKey(varName)) {
placeholderValue = resolved.getProperty(varName);
} else {
queue.add(varName);
placeholderValue = resolveProperty(varName);
queue.remove(varName);
}
return placeholderValue;

}
}

+ 1
- 1
src/test/java/org/sonarsource/scanner/cli/MainTest.java View File

@@ -64,7 +64,7 @@ public class MainTest {
when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
when(conf.properties()).thenReturn(properties);
}
@Test
public void should_execute_runner() {
Main main = new Main(exit, cli, conf, runnerFactory, logs);

+ 123
- 0
src/test/java/org/sonarsource/scanner/cli/PropertyResolverTest.java View File

@@ -0,0 +1,123 @@
/*
* SonarQube Scanner
* Copyright (C) 2011-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonarsource.scanner.cli;

import static org.fest.assertions.Assertions.assertThat;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class PropertyResolverTest {
@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void resolve_properties() {
Properties map = new Properties();
Map<String, String> env = new HashMap<>();

// resolve
map.put("A", "value a");
map.put("B", "value b");
map.put("C", "${A} ${B} ${nonexisting}");

PropertyResolver resolver = new PropertyResolver(map, env);
Properties resolved = resolver.resolve();
assertThat(resolved.get("A")).isEqualTo("value a");
assertThat(resolved.get("B")).isEqualTo("value b");
assertThat(resolved.get("C")).isEqualTo("value a value b ");

map.clear();
map.put("sonar.login", "admin");
map.put("sonar.password", "${sonar.login}");

resolver = new PropertyResolver(map, env);
resolved = resolver.resolve();
assertThat(resolved.get("sonar.password")).isEqualTo("admin");
}

@Test
public void use_env() {
Properties map = new Properties();
Map<String, String> env = new HashMap<>();

// resolve
map.put("A", "invalid");
map.put("B", "value b");
map.put("C", "${env.A} ${B} ${nonexisting}");
env.put("A", "value a");

PropertyResolver resolver = new PropertyResolver(map, env);
Properties resolved = resolver.resolve();
assertThat(resolved.get("A")).isEqualTo("invalid");
assertThat(resolved.get("B")).isEqualTo("value b");
assertThat(resolved.get("C")).isEqualTo("value a value b ");
}

@Test
public void resolve_recursively() {
Properties map = new Properties();
Map<String, String> env = new HashMap<>();
map.put("A", "value a");
map.put("B", "${A}");
map.put("C", "${A} ${B}");

PropertyResolver resolver = new PropertyResolver(map, env);
Properties resolved = resolver.resolve();
assertThat(resolved.get("A")).isEqualTo("value a");
assertThat(resolved.get("B")).isEqualTo("value a");
assertThat(resolved.get("C")).isEqualTo("value a value a");
}

@Test
public void dont_resolve_nested() {
Properties map = new Properties();
Map<String, String> env = new HashMap<>();
map.put("A", "value a");
map.put("B", "value b");
map.put("C", "${A ${B}}");

PropertyResolver resolver = new PropertyResolver(map, env);
Properties resolved = resolver.resolve();
assertThat(resolved.get("A")).isEqualTo("value a");
assertThat(resolved.get("B")).isEqualTo("value b");
assertThat(resolved.get("C")).isEqualTo("${A value b}");
}

@Test
public void fail_loop_properties_resolution() {
Properties map = new Properties();
Map<String, String> env = new HashMap<>();

// resolve
map.put("A", "${B}");
map.put("B", "${A}");

exception.expect(IllegalArgumentException.class);
exception.expectMessage("variable: B");
PropertyResolver resolver = new PropertyResolver(map, env);
resolver.resolve();
}
}

Loading…
Cancel
Save