aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java39
-rw-r--r--sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java27
-rw-r--r--sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java14
-rw-r--r--sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java2
-rw-r--r--sonar-runner-impl/src/main/java/org/sonar/runner/impl/InternalProperties.java2
-rw-r--r--sonar-runner-impl/src/main/java/org/sonar/runner/impl/IsolatedClassloader.java12
-rw-r--r--sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java4
-rw-r--r--sonar-runner-impl/src/test/java/org/sonar/runner/impl/IsolatedClassloaderTest.java6
8 files changed, 79 insertions, 27 deletions
diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java
index e5ce102..f83218f 100644
--- a/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java
+++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java
@@ -36,6 +36,7 @@ public class EmbeddedRunner extends Runner<EmbeddedRunner> {
private final BatchLauncher batchLauncher;
private final List<Object> extensions = new ArrayList<Object>();
+ private final static String MASK_RULES_PROP = "sonarRunner.maskRules";
EmbeddedRunner(BatchLauncher bl) {
this.batchLauncher = bl;
@@ -49,12 +50,42 @@ public class EmbeddedRunner extends Runner<EmbeddedRunner> {
}
/**
- * Sonar is executed in an almost fully isolated classloader. The unmasked packages
- * define the classes of the client application that are visible from Sonar classloader. They
- * relate to the extensions provided by {@link #setUnmaskedPackages(String...)}.
+ * Sonar is executed in an almost fully isolated classloader (mask everything by default). his method allow to unmask some classes based on
+ * a prefix of their fully qualified name. They relate to the extensions provided by {@link #addExtensions(Object...)}.
+ * Complex mask/unmask rules can be defined by chaining several ordered calls to {@link #unmask(String)} and {@link #mask(String)}.
+ * Registered mask/unmask rules are considered in their registration order and as soon as a matching prefix is found
+ * the class is masked/unmasked accordingly.
+ * If no matching prefix can be found then by default class is masked.
*/
+ public EmbeddedRunner unmask(String fqcnPrefix) {
+ return addMaskRule("UNMASK", fqcnPrefix);
+ }
+
+ /**
+ * @see EmbeddedRunner#unmask(String)
+ */
+ public EmbeddedRunner mask(String fqcnPrefix) {
+ return addMaskRule("MASK", fqcnPrefix);
+ }
+
+ private EmbeddedRunner addMaskRule(String type, String fqcnPrefix) {
+ String existingRules = property(MASK_RULES_PROP, "");
+ if (!"".equals(existingRules)) {
+ existingRules += ",";
+ }
+ existingRules += type + "|" + fqcnPrefix;
+ return setProperty(MASK_RULES_PROP, existingRules);
+ }
+
+ /**
+ * @deprecated since 2.3 use {@link #setUnmaskedClassRegexp(String)}
+ */
+ @Deprecated
public EmbeddedRunner setUnmaskedPackages(String... packages) {
- return setProperty("sonarRunner.unmaskedPackages", Utils.join(packages, ","));
+ for (String packagePrefix : packages) {
+ unmask(packagePrefix + ".");
+ }
+ return this;
}
public EmbeddedRunner addExtensions(Object... objects) {
diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java
index 4b06069..ce41b57 100644
--- a/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java
+++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java
@@ -48,10 +48,23 @@ public class EmbeddedRunnerTest {
@Test
public void should_set_unmasked_packages() {
EmbeddedRunner runner = EmbeddedRunner.create();
- assertThat(runner.property(InternalProperties.RUNNER_UNMASKED_PACKAGES, null)).isNull();
+ assertThat(runner.property(InternalProperties.RUNNER_MASK_RULES, null)).isNull();
runner = EmbeddedRunner.create().setUnmaskedPackages("org.apache.ant", "org.ant");
- assertThat(runner.property(InternalProperties.RUNNER_UNMASKED_PACKAGES, null)).isEqualTo("org.apache.ant,org.ant");
+ assertThat(runner.property(InternalProperties.RUNNER_MASK_RULES, null)).isEqualTo("UNMASK|org.apache.ant.,UNMASK|org.ant.");
+ }
+
+ @Test
+ public void should_set_mask_rules() {
+ EmbeddedRunner runner = EmbeddedRunner.create();
+ assertThat(runner.property(InternalProperties.RUNNER_MASK_RULES, null)).isNull();
+
+ runner = EmbeddedRunner.create()
+ .unmask("org.slf4j.Logger")
+ .mask("org.slf4j.")
+ .mask("ch.qos.logback.")
+ .unmask("");
+ assertThat(runner.property(InternalProperties.RUNNER_MASK_RULES, null)).isEqualTo("UNMASK|org.slf4j.Logger,MASK|org.slf4j.,MASK|ch.qos.logback.,UNMASK|");
}
@Test
@@ -68,10 +81,12 @@ public class EmbeddedRunnerTest {
public void should_set_properties() {
EmbeddedRunner runner = EmbeddedRunner.create();
runner.setProperty("sonar.projectKey", "foo");
- runner.addProperties(new Properties() {{
- setProperty("sonar.login", "admin");
- setProperty("sonar.password", "gniark");
- }});
+ runner.addProperties(new Properties() {
+ {
+ setProperty("sonar.login", "admin");
+ setProperty("sonar.password", "gniark");
+ }
+ });
assertThat(runner.property("sonar.projectKey", null)).isEqualTo("foo");
assertThat(runner.property("sonar.login", null)).isEqualTo("admin");
diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java
index 51b917a..96c28db 100644
--- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java
+++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java
@@ -57,8 +57,15 @@ public class BatchLauncher {
Object launcher = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
List<File> jarFiles = jarDownloader.download();
- String unmaskedPackages = props.getProperty(InternalProperties.RUNNER_UNMASKED_PACKAGES, "");
- IsolatedClassloader classloader = new IsolatedClassloader(getClass().getClassLoader(), unmaskedPackages.split(":"));
+ String maskRulesProp = props.getProperty(InternalProperties.RUNNER_MASK_RULES, null);
+ String[] maskRulesConcat = maskRulesProp != null ? maskRulesProp.split(",") : new String[0];
+ String[][] maskRules = new String[maskRulesConcat.length][2];
+ for (int i = 0; i < maskRulesConcat.length; i++) {
+ String[] splitted = maskRulesConcat[i].split("\\|");
+ maskRules[i][0] = splitted[0];
+ maskRules[i][1] = splitted.length > 1 ? splitted[1] : "";
+ }
+ IsolatedClassloader classloader = new IsolatedClassloader(getClass().getClassLoader(), maskRules);
classloader.addFiles(jarFiles);
Object launcher = delegateExecution(classloader, props, extensions);
tempCleaning.clean();
@@ -88,5 +95,4 @@ public class BatchLauncher {
return launcher;
}
-
-} \ No newline at end of file
+}
diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java
index 0c8591a..67fd0e8 100644
--- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java
+++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java
@@ -47,7 +47,7 @@ public class BatchLauncherMain {
try {
props.load(input);
// just to be clean, do not forward properties that do not make sense in fork mode
- props.remove(InternalProperties.RUNNER_UNMASKED_PACKAGES);
+ props.remove(InternalProperties.RUNNER_MASK_RULES);
} finally {
IOUtils.closeQuietly(input);
diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/InternalProperties.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/InternalProperties.java
index 8f9956e..f0069a7 100644
--- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/InternalProperties.java
+++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/InternalProperties.java
@@ -22,5 +22,5 @@ package org.sonar.runner.impl;
public interface InternalProperties {
String RUNNER_APP = "sonarRunner.app";
String RUNNER_APP_VERSION = "sonarRunner.appVersion";
- String RUNNER_UNMASKED_PACKAGES = "sonarRunner.unmaskedPackages";
+ String RUNNER_MASK_RULES = "sonarRunner.maskRules";
}
diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/IsolatedClassloader.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/IsolatedClassloader.java
index 954b341..9054935 100644
--- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/IsolatedClassloader.java
+++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/IsolatedClassloader.java
@@ -33,14 +33,14 @@ import java.util.List;
*/
class IsolatedClassloader extends URLClassLoader {
- private final String[] unmaskedPackages;
+ private final String[][] maskRules;
/**
* The parent classloader is used only for loading classes and resources in unmasked packages
*/
- IsolatedClassloader(ClassLoader parent, String... unmaskedPackages) {
+ IsolatedClassloader(ClassLoader parent, String[][] maskRules) {
super(new URL[0], parent);
- this.unmaskedPackages = unmaskedPackages;
+ this.maskRules = maskRules;
}
void addFiles(List<File> files) {
@@ -57,9 +57,9 @@ class IsolatedClassloader extends URLClassLoader {
* @return true, if class can be loaded from parent ClassLoader
*/
boolean canLoadFromParent(String name) {
- for (String pkg : unmaskedPackages) {
- if (name.startsWith(pkg + ".")) {
- return true;
+ for (String[] maskRule : maskRules) {
+ if (name.startsWith(maskRule[1])) {
+ return "UNMASK".equals(maskRule[0]);
}
}
return false;
diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java
index b914a39..eceb8c9 100644
--- a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java
+++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java
@@ -48,7 +48,7 @@ public class BatchLauncherTest {
props.put("foo", "bar");
// Unmask the current classloader in order to access FakeIsolatedLauncher
- props.put(InternalProperties.RUNNER_UNMASKED_PACKAGES, "org.sonar.runner.impl");
+ props.put(InternalProperties.RUNNER_MASK_RULES, "UNMASK|org.sonar.runner.impl.");
List<Object> extensions = new ArrayList<Object>();
FakeIsolatedLauncher isolatedLauncher = (FakeIsolatedLauncher) launcher.doExecute(jarDownloader, props, extensions);
@@ -64,7 +64,7 @@ public class BatchLauncherTest {
Properties props = new Properties();
// The current classloader in not available -> fail to load FakeIsolatedLauncher
- props.put(InternalProperties.RUNNER_UNMASKED_PACKAGES, "");
+ props.put(InternalProperties.RUNNER_MASK_RULES, "");
try {
launcher.doExecute(jarDownloader, props, Collections.emptyList());
fail();
diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/IsolatedClassloaderTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/IsolatedClassloaderTest.java
index fb0d7f9..266208c 100644
--- a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/IsolatedClassloaderTest.java
+++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/IsolatedClassloaderTest.java
@@ -32,7 +32,7 @@ public class IsolatedClassloaderTest {
@Test
public void should_restrict_loading_from_parent() throws Exception {
ClassLoader parentClassloader = getClass().getClassLoader();
- IsolatedClassloader classLoader = new IsolatedClassloader(parentClassloader, "org.apache.ant");
+ IsolatedClassloader classLoader = new IsolatedClassloader(parentClassloader, new String[][] {new String[] {"UNMASK", "org.apache.ant."}});
assertThat(classLoader.canLoadFromParent("org.sonar.runner.Foo")).isFalse();
assertThat(classLoader.canLoadFromParent("org.objectweb.asm.ClassVisitor")).isFalse();
@@ -46,7 +46,7 @@ public class IsolatedClassloaderTest {
thrown.expect(ClassNotFoundException.class);
thrown.expectMessage("org.junit.Test");
ClassLoader parent = getClass().getClassLoader();
- IsolatedClassloader classLoader = new IsolatedClassloader(parent);
+ IsolatedClassloader classLoader = new IsolatedClassloader(parent, new String[0][]);
// JUnit is available in the parent classloader (classpath used to execute this test) but not in the core JVM
assertThat(classLoader.loadClass("java.lang.String", false)).isNotNull();
@@ -56,7 +56,7 @@ public class IsolatedClassloaderTest {
@Test
public void should_find_in_parent_when_matches_unmasked_packages() throws ClassNotFoundException {
ClassLoader parent = getClass().getClassLoader();
- IsolatedClassloader classLoader = new IsolatedClassloader(parent, "org.junit");
+ IsolatedClassloader classLoader = new IsolatedClassloader(parent, new String[][] {new String[] {"UNMASK", "org.junit."}});
// JUnit is available in the parent classloader (classpath used to execute this test) but not in the core JVM
assertThat(classLoader.loadClass("org.junit.Test", false)).isNotNull();