aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-07-17 10:05:49 +0200
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-07-24 13:14:57 +0200
commit8566436b507addd3b891cbe84a04e3e0225358ba (patch)
tree3d820452d1ba481673c6aac8830495135c1e8965
parent26bd5e1700d2d0a89706c61c7404ffb4f80fec3e (diff)
downloadsonarqube-8566436b507addd3b891cbe84a04e3e0225358ba.tar.gz
sonarqube-8566436b507addd3b891cbe84a04e3e0225358ba.zip
SONAR-6577 Offline mode in preview mode
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisProperties.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java15
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java8
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalMode.java51
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalSettings.java20
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/PersistentCacheProvider.java17
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java125
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java182
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderGlobalProvider.java46
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java20
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java25
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java36
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectAnalysisMode.java (renamed from sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultAnalysisMode.java)27
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/WSLoaderProjectProvider.java57
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReports.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/util/BatchUtils.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java17
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java3
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalModeTest.java67
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalSettingsTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java118
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/PersistentCacheProviderTest.java15
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java208
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderGlobalProviderTest.java76
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java214
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTestWithServer.java112
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java8
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java21
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java8
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java26
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java18
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java17
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/DefaultAnalysisModeTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultAnalysisModeTest.java)39
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java5
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/WSLoaderProjectProviderTest.java81
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java5
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java72
-rw-r--r--sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java21
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java55
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheBuilder.java8
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheLoader.java26
-rw-r--r--sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java36
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java5
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/AnalysisMode.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java10
62 files changed, 1512 insertions, 589 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisProperties.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisProperties.java
index d8b53410f60..8a514c6db45 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisProperties.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/AnalysisProperties.java
@@ -28,7 +28,10 @@ import java.util.Map;
* coming from sonar-project.properties).
*/
public class AnalysisProperties extends UserProperties {
-
+ public AnalysisProperties(Map<String, String> properties) {
+ this(properties, null);
+ }
+
public AnalysisProperties(Map<String, String> properties, @Nullable String pathToSecretKey) {
super(properties, pathToSecretKey);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
index 1704d303520..cb6f40dafc1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
@@ -42,7 +42,7 @@ public class BatchComponents {
// only static stuff
}
- public static Collection all(DefaultAnalysisMode analysisMode) {
+ public static Collection all(GlobalMode analysisMode) {
List components = Lists.newArrayList(
DefaultResourceTypes.get(),
// SCM
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
index 3310365a856..b6744b5ff4a 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
@@ -19,14 +19,18 @@
*/
package org.sonar.batch.bootstrap;
+import com.google.common.io.Files;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
+
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.Plugin;
@@ -47,12 +51,12 @@ public class BatchPluginInstaller implements PluginInstaller {
private static final Logger LOG = Loggers.get(BatchPluginInstaller.class);
private static final String PLUGINS_INDEX_URL = "/deploy/plugins/index.txt";
- private final ServerClient server;
+ private final WSLoader wsLoader;
private final FileCache fileCache;
private final BatchPluginPredicate pluginPredicate;
- public BatchPluginInstaller(ServerClient server, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
- this.server = server;
+ public BatchPluginInstaller(WSLoader wsLoader, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
+ this.wsLoader = wsLoader;
this.fileCache = fileCache;
this.pluginPredicate = pluginPredicate;
}
@@ -95,7 +99,8 @@ public class BatchPluginInstaller implements PluginInstaller {
} else {
LOG.info("Download {}", file.getFilename());
}
- server.download(url, toFile);
+
+ Files.write(wsLoader.load(url), toFile);
}
});
@@ -111,7 +116,7 @@ public class BatchPluginInstaller implements PluginInstaller {
List<RemotePlugin> listRemotePlugins() {
try {
Profiler profiler = Profiler.create(LOG).startInfo("Load plugins index");
- String indexContent = server.request(PLUGINS_INDEX_URL);
+ String indexContent = wsLoader.loadString(PLUGINS_INDEX_URL);
profiler.stopInfo();
String[] rows = StringUtils.split(indexContent, CharUtils.LF);
List<RemotePlugin> result = Lists.newArrayList();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java
index 435b53d10db..dd55c277587 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java
@@ -23,17 +23,19 @@ import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
+
import java.text.MessageFormat;
import java.util.List;
import java.util.Set;
+
import javax.annotation.Nonnull;
+
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-
import static com.google.common.collect.Sets.newHashSet;
/**
@@ -50,9 +52,9 @@ public class BatchPluginPredicate implements Predicate<String> {
private final Set<String> whites = newHashSet();
private final Set<String> blacks = newHashSet();
- private final DefaultAnalysisMode mode;
+ private final GlobalMode mode;
- public BatchPluginPredicate(Settings settings, DefaultAnalysisMode mode) {
+ public BatchPluginPredicate(Settings settings, GlobalMode mode) {
this.mode = mode;
if (mode.isPreview()) {
// These default values are not supported by Settings because the class CorePlugin
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
index 2899ede562b..aa4f22e4e1e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
@@ -20,7 +20,9 @@
package org.sonar.batch.bootstrap;
import java.util.List;
+
import javax.annotation.Nullable;
+
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
@@ -32,18 +34,18 @@ public class ExtensionInstaller {
private final PluginRepository pluginRepository;
private final EnvironmentInformation env;
- private final DefaultAnalysisMode analysisMode;
+ private final GlobalMode globalMode;
- public ExtensionInstaller(PluginRepository pluginRepository, EnvironmentInformation env, DefaultAnalysisMode analysisMode) {
+ public ExtensionInstaller(PluginRepository pluginRepository, EnvironmentInformation env, GlobalMode globalMode) {
this.pluginRepository = pluginRepository;
this.env = env;
- this.analysisMode = analysisMode;
+ this.globalMode = globalMode;
}
public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) {
// core components
- for (Object o : BatchComponents.all(analysisMode)) {
+ for (Object o : BatchComponents.all(globalMode)) {
doInstall(container, matcher, null, o);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
index dd8660a3795..b61fae76904 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
@@ -21,6 +21,7 @@ package org.sonar.batch.bootstrap;
import java.util.List;
import java.util.Map;
+
import org.sonar.api.CoreProperties;
import org.sonar.api.Plugin;
import org.sonar.api.utils.Durations;
@@ -52,7 +53,6 @@ import org.sonar.core.util.DefaultHttpDownloader;
public class GlobalContainer extends ComponentContainer {
private final Map<String, String> bootstrapProperties;
- private PersistentCacheProvider persistentCacheProvider;
private GlobalContainer(Map<String, String> bootstrapProperties) {
super();
@@ -68,14 +68,11 @@ public class GlobalContainer extends ComponentContainer {
@Override
protected void doBeforeStart() {
BootstrapProperties bootstrapProps = new BootstrapProperties(bootstrapProperties);
- DefaultAnalysisMode analysisMode = new DefaultAnalysisMode(bootstrapProps.properties());
- add(bootstrapProps, analysisMode);
+ add(bootstrapProps);
addBootstrapComponents();
}
private void addBootstrapComponents() {
- persistentCacheProvider = new PersistentCacheProvider();
-
add(
// plugins
BatchPluginRepository.class,
@@ -86,6 +83,7 @@ public class GlobalContainer extends ComponentContainer {
ExtensionInstaller.class,
CachesManager.class,
+ GlobalMode.class,
GlobalSettings.class,
ServerClient.class,
Logback.class,
@@ -94,7 +92,8 @@ public class GlobalContainer extends ComponentContainer {
DefaultHttpDownloader.class,
UriReader.class,
new FileCacheProvider(),
- persistentCacheProvider,
+ new PersistentCacheProvider(),
+ new WSLoaderGlobalProvider(),
System2.INSTANCE,
DefaultI18n.class,
Durations.class,
@@ -129,7 +128,6 @@ public class GlobalContainer extends ComponentContainer {
public void executeAnalysis(Map<String, String> analysisProperties, Object... components) {
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(BootstrapProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
- persistentCacheProvider.reconfigure(props);
new ProjectScanContainer(this, props, components).execute();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalMode.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalMode.java
new file mode 100644
index 00000000000..83c2249ad65
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalMode.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.sonar.api.CoreProperties;
+
+import java.text.MessageFormat;
+
+public class GlobalMode {
+ private static final Logger LOG = LoggerFactory.getLogger(GlobalMode.class);
+ private boolean preview;
+
+ public boolean isPreview() {
+ return preview;
+ }
+
+ public GlobalMode(BootstrapProperties props) {
+ if (props.property(CoreProperties.DRY_RUN) != null) {
+ LOG.warn(MessageFormat.format("Property {0} is deprecated. Please use {1} instead.", CoreProperties.DRY_RUN, CoreProperties.ANALYSIS_MODE));
+ preview = "true".equals(props.property(CoreProperties.DRY_RUN));
+ } else {
+ String mode = props.property(CoreProperties.ANALYSIS_MODE);
+ preview = CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode) || CoreProperties.ANALYSIS_MODE_INCREMENTAL.equals(mode) ||
+ CoreProperties.ANALYSIS_MODE_QUICK.equals(mode);
+ }
+
+ if (preview) {
+ LOG.info("Preview global mode");
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalSettings.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalSettings.java
index 718dfd6acb4..db7f0c730fb 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalSettings.java
@@ -20,7 +20,9 @@
package org.sonar.batch.bootstrap;
import com.google.common.collect.ImmutableMap;
+
import java.util.Map;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
@@ -39,17 +41,17 @@ public class GlobalSettings extends Settings {
* (what will happen, what should the user do, ...) as a value
*/
private static final Map<String, String> DROPPED_PROPERTIES = ImmutableMap.of(
- "sonar.jdbc.url", JDBC_SPECIFIC_MESSAGE,
- "sonar.jdbc.username", JDBC_SPECIFIC_MESSAGE,
- "sonar.jdbc.password", JDBC_SPECIFIC_MESSAGE
- );
+ "sonar.jdbc.url", JDBC_SPECIFIC_MESSAGE,
+ "sonar.jdbc.username", JDBC_SPECIFIC_MESSAGE,
+ "sonar.jdbc.password", JDBC_SPECIFIC_MESSAGE
+ );
private final BootstrapProperties bootstrapProps;
private final GlobalRepositories globalReferentials;
- private final DefaultAnalysisMode mode;
+ private final GlobalMode mode;
public GlobalSettings(BootstrapProperties bootstrapProps, PropertyDefinitions propertyDefinitions,
- GlobalRepositories globalReferentials, DefaultAnalysisMode mode) {
+ GlobalRepositories globalReferentials, GlobalMode mode) {
super(propertyDefinitions);
this.mode = mode;
@@ -63,6 +65,12 @@ public class GlobalSettings extends Settings {
private void init() {
addProperties(globalReferentials.globalSettings());
addProperties(bootstrapProps.properties());
+
+ // To stay compatible with plugins that use the old property to check mode
+ if (mode.isPreview()) {
+ setProperty(CoreProperties.DRY_RUN, "true");
+ }
+
LOG.info("Server id: " + getString(CoreProperties.SERVER_ID));
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PersistentCacheProvider.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PersistentCacheProvider.java
index be8cce1a11e..323b5aa0a0e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PersistentCacheProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PersistentCacheProvider.java
@@ -20,7 +20,6 @@
package org.sonar.batch.bootstrap;
import java.nio.file.Paths;
-import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.home.cache.PersistentCache;
import org.sonar.home.cache.PersistentCacheBuilder;
@@ -32,26 +31,14 @@ public class PersistentCacheProvider extends ProviderAdapter {
if (cache == null) {
PersistentCacheBuilder builder = new PersistentCacheBuilder(new Slf4jLogger());
- builder.forceUpdate(isForceUpdate(props.properties()));
-
String home = props.property("sonar.userHome");
if (home != null) {
builder.setSonarHome(Paths.get(home));
}
cache = builder.build();
- }
+ }
+
return cache;
}
-
- public void reconfigure(UserProperties props) {
- if (cache != null) {
- cache.reconfigure(isForceUpdate(props.properties()));
- }
- }
-
- private static boolean isForceUpdate(Map<String, String> props) {
- String enableCache = props.get("sonar.enableHttpCache");
- return !"true".equals(enableCache);
- }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
index 4f40634966f..66e2677691f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
@@ -19,26 +19,27 @@
*/
package org.sonar.batch.bootstrap;
+import org.sonar.api.utils.HttpDownloader.HttpException;
+
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
-import com.google.common.io.Files;
-import com.google.common.io.InputSupplier;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import java.io.ByteArrayInputStream;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
-import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Callable;
+
import javax.annotation.Nullable;
+
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
@@ -47,7 +48,6 @@ import org.sonar.api.batch.BatchSide;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.core.util.DefaultHttpDownloader;
-import org.sonar.home.cache.PersistentCache;
/**
* Replace the deprecated org.sonar.batch.ServerMetadata
@@ -60,29 +60,31 @@ public class ServerClient {
private static final String GET = "GET";
private BootstrapProperties props;
- private PersistentCache cache;
private DefaultHttpDownloader.BaseHttpDownloader downloader;
- private DefaultAnalysisMode mode;
- public ServerClient(BootstrapProperties settings, EnvironmentInformation env, PersistentCache cache, DefaultAnalysisMode mode) {
+ public ServerClient(BootstrapProperties settings, EnvironmentInformation env) {
this.props = settings;
this.downloader = new DefaultHttpDownloader.BaseHttpDownloader(settings.properties(), env.toString());
- this.cache = cache;
- this.mode = mode;
}
public String getURL() {
return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/");
}
+ public URI getURI(String pathStartingWithSlash) {
+ Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /");
+ String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash);
+ return URI.create(getURL() + path);
+ }
+
public void download(String pathStartingWithSlash, File toFile) {
- download(pathStartingWithSlash, toFile, null);
+ download(pathStartingWithSlash, toFile, null, null);
}
- public void download(String pathStartingWithSlash, File toFile, @Nullable Integer readTimeoutMillis) {
+ public void download(String pathStartingWithSlash, File toFile, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
try {
- InputSupplier<InputStream> inputSupplier = doRequest(pathStartingWithSlash, GET, readTimeoutMillis);
- Files.copy(inputSupplier, toFile);
+ InputStream is = load(pathStartingWithSlash, GET, false, connectTimeoutMillis, readTimeoutMillis);
+ Files.copy(is, toFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (HttpDownloader.HttpException he) {
throw handleHttpException(he);
} catch (IOException e) {
@@ -90,80 +92,41 @@ public class ServerClient {
}
}
- public String request(String pathStartingWithSlash) {
- return request(pathStartingWithSlash, GET, true);
- }
-
- public String request(String pathStartingWithSlash, String requestMethod) {
- return request(pathStartingWithSlash, requestMethod, true);
+ public String downloadString(String pathStartingWithSlash) {
+ return downloadString(pathStartingWithSlash, GET, true, null);
}
- public String request(String pathStartingWithSlash, boolean wrapHttpException) {
- return request(pathStartingWithSlash, GET, wrapHttpException, null);
- }
-
- public String request(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException) {
- return request(pathStartingWithSlash, requestMethod, wrapHttpException, null);
- }
-
- public String request(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer timeoutMillis) {
- final byte[] buf = load(pathStartingWithSlash, requestMethod, wrapHttpException, timeoutMillis);
+ public String downloadString(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer timeoutMillis) {
+ InputStream is = load(pathStartingWithSlash, requestMethod, wrapHttpException, null, timeoutMillis);
try {
- return new String(buf, "UTF-8");
- } catch (UnsupportedEncodingException e) {
+ return new String(IOUtils.toByteArray(is), "UTF-8");
+ } catch (IOException e) {
throw new IllegalStateException(String.format("Unable to request: %s", pathStartingWithSlash), e);
}
}
- public InputSupplier<InputStream> doRequest(String pathStartingWithSlash, String requestMethod, @Nullable Integer timeoutMillis) {
- final byte[] buf = load(pathStartingWithSlash, requestMethod, false, timeoutMillis);
-
- return new InputSupplier<InputStream>() {
- @Override
- public InputStream getInput() throws IOException {
- return new ByteArrayInputStream(buf);
- }
- };
- }
-
- private byte[] load(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer timeoutMillis) {
- Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /");
- String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash);
- URI uri = URI.create(getURL() + path);
+ /**
+ * @throws IllegalStateException on I/O error, not limited to the network connection and if HTTP response code > 400 and wrapHttpException is true
+ * @throws HttpException if HTTP response code > 400 and wrapHttpException is false
+ */
+ public InputStream load(String pathStartingWithSlash, String requestMethod, boolean wrapHttpException, @Nullable Integer connectTimeoutMs,
+ @Nullable Integer readTimeoutMs) {
+ URI uri = getURI(pathStartingWithSlash);
try {
- if (GET.equals(requestMethod) && mode.isPreview()) {
- return cache.get(uri.toString(), new HttpValueLoader(uri, requestMethod, timeoutMillis));
+ if (Strings.isNullOrEmpty(getLogin())) {
+ return downloader.newInputSupplier(uri, requestMethod, connectTimeoutMs, readTimeoutMs).getInput();
} else {
- return new HttpValueLoader(uri, requestMethod, timeoutMillis).call();
+ return downloader.newInputSupplier(uri, requestMethod, getLogin(), getPassword(), connectTimeoutMs, readTimeoutMs).getInput();
}
} catch (HttpDownloader.HttpException e) {
- throw wrapHttpException ? handleHttpException(e) : e;
- } catch (Exception e) {
- throw new IllegalStateException(String.format("Unable to request: %s", uri), e);
- }
- }
-
- private class HttpValueLoader implements Callable<byte[]> {
- private URI uri;
- private String requestMethod;
- private Integer timeoutMillis;
-
- public HttpValueLoader(URI uri, String requestMethod, Integer timeoutMillis) {
- this.uri = uri;
- this.requestMethod = requestMethod;
- this.timeoutMillis = timeoutMillis;
- }
-
- @Override
- public byte[] call() throws Exception {
- InputSupplier<InputStream> inputSupplier;
- if (Strings.isNullOrEmpty(getLogin())) {
- inputSupplier = downloader.newInputSupplier(uri, requestMethod, timeoutMillis);
+ if (wrapHttpException) {
+ throw handleHttpException(e);
} else {
- inputSupplier = downloader.newInputSupplier(uri, requestMethod, getLogin(), getPassword(), timeoutMillis);
+ throw e;
}
- return IOUtils.toByteArray(inputSupplier.getInput());
+ } catch (IOException e) {
+ throw new IllegalStateException(String.format("Unable to request: %s", uri), e);
}
}
@@ -207,14 +170,4 @@ public class ServerClient {
public String getPassword() {
return props.property(CoreProperties.PASSWORD);
}
-
- public static String encodeForUrl(String url) {
- try {
- return URLEncoder.encode(url, "UTF-8");
-
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("Encoding not supported", e);
- }
- }
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java
new file mode 100644
index 00000000000..d475e68c360
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoader.java
@@ -0,0 +1,182 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import javax.annotation.Nonnull;
+
+import org.sonar.api.utils.HttpDownloader;
+import com.google.common.io.ByteSource;
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.sonar.batch.bootstrap.WSLoader.ServerStatus.*;
+import static org.sonar.batch.bootstrap.WSLoader.LoadStrategy.*;
+import org.sonar.home.cache.PersistentCache;
+
+public class WSLoader {
+ private static final String FAIL_MSG = "Server is not accessible and data is not cached";
+ private static final int CONNECT_TIMEOUT = 5000;
+ private static final int READ_TIMEOUT = 10000;
+ private static final String REQUEST_METHOD = "GET";
+
+ public enum ServerStatus {
+ UNKNOWN, ACCESSIBLE, NOT_ACCESSIBLE;
+ }
+
+ public enum LoadStrategy {
+ SERVER_FIRST, CACHE_FIRST;
+ }
+
+ private LoadStrategy loadStrategy;
+ private boolean cacheEnabled;
+ private ServerStatus serverStatus;
+ private ServerClient client;
+ private PersistentCache cache;
+
+ public WSLoader(boolean cacheEnabled, PersistentCache cache, ServerClient client) {
+ this.cacheEnabled = cacheEnabled;
+ this.loadStrategy = CACHE_FIRST;
+ this.serverStatus = UNKNOWN;
+ this.cache = cache;
+ this.client = client;
+ }
+
+ public WSLoader(PersistentCache cache, ServerClient client) {
+ this(false, cache, client);
+ }
+
+ public ByteSource loadSource(String id) {
+ return ByteSource.wrap(load(id));
+ }
+
+ public String loadString(String id) {
+ return new String(load(id), StandardCharsets.UTF_8);
+ }
+
+ @Nonnull
+ public byte[] load(String id) {
+ if (loadStrategy == CACHE_FIRST) {
+ return loadFromCacheFirst(id);
+ } else {
+ return loadFromServerFirst(id);
+ }
+ }
+
+ public void setStrategy(LoadStrategy strategy) {
+ this.loadStrategy = strategy;
+ }
+
+ public LoadStrategy getStrategy() {
+ return this.loadStrategy;
+ }
+
+ public void setCacheEnabled(boolean enabled) {
+ this.cacheEnabled = enabled;
+ }
+
+ public boolean isCacheEnabled() {
+ return this.cacheEnabled;
+ }
+
+ private void switchToOffline() {
+ serverStatus = NOT_ACCESSIBLE;
+ }
+
+ private void switchToOnline() {
+ serverStatus = ACCESSIBLE;
+ }
+
+ private boolean isOffline() {
+ return serverStatus == NOT_ACCESSIBLE;
+ }
+
+ @Nonnull
+ private byte[] loadFromCacheFirst(String id) {
+ byte[] cached = loadFromCache(id);
+ if (cached != null) {
+ return cached;
+ }
+
+ try {
+ return loadFromServer(id);
+ } catch (Exception e) {
+ if (e.getCause() instanceof HttpDownloader.HttpException) {
+ throw e;
+ }
+ }
+
+ throw new IllegalStateException(FAIL_MSG);
+ }
+
+ @Nonnull
+ private byte[] loadFromServerFirst(String id) {
+ try {
+ return loadFromServer(id);
+ } catch (Exception serverException) {
+ if (serverException.getCause() instanceof HttpDownloader.HttpException) {
+ // http exceptions should always be thrown (no fallback)
+ throw serverException;
+ }
+ byte[] cached = loadFromCache(id);
+ if (cached != null) {
+ return cached;
+ }
+ }
+
+ throw new IllegalStateException(FAIL_MSG);
+ }
+
+ private byte[] loadFromCache(String id) {
+ if (!cacheEnabled) {
+ return null;
+ }
+
+ try {
+ return cache.get(client.getURI(id).toString(), null);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private byte[] loadFromServer(String id) {
+ if (isOffline()) {
+ throw new IllegalStateException("Server is not accessible");
+ }
+
+ try {
+ InputStream is = client.load(id, REQUEST_METHOD, true, CONNECT_TIMEOUT, READ_TIMEOUT);
+ switchToOnline();
+ byte[] value = IOUtils.toByteArray(is);
+ if (cacheEnabled) {
+ cache.put(client.getURI(id).toString(), value);
+ }
+ return value;
+ } catch (IllegalStateException e) {
+ switchToOffline();
+ throw e;
+ } catch (Exception e) {
+ switchToOffline();
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderGlobalProvider.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderGlobalProvider.java
new file mode 100644
index 00000000000..2d9a76252a8
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/WSLoaderGlobalProvider.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import org.picocontainer.injectors.ProviderAdapter;
+
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+
+import java.util.Map;
+
+import org.sonar.home.cache.PersistentCache;
+
+public class WSLoaderGlobalProvider extends ProviderAdapter {
+ private static final LoadStrategy DEFAULT_STRATEGY = LoadStrategy.SERVER_FIRST;
+ private WSLoader wsLoader;
+
+ public WSLoader provide(BootstrapProperties props, GlobalMode mode, PersistentCache cache, ServerClient client) {
+ if (wsLoader == null) {
+ wsLoader = new WSLoader(isCacheEnabled(props.properties(), mode.isPreview()), cache, client);
+ wsLoader.setStrategy(DEFAULT_STRATEGY);
+ }
+ return wsLoader;
+ }
+
+ private static boolean isCacheEnabled(Map<String, String> props, boolean isPreview) {
+ String enableOffline = props.get("sonar.enableOffline");
+ return isPreview && "true".equals(enableOffline);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java
index 26fa317b8bb..d9d6a444080 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java
@@ -19,23 +19,26 @@
*/
package org.sonar.batch.cpd.index;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import com.google.common.annotations.VisibleForTesting;
+
import javax.annotation.Nullable;
+
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@BatchSide
public class IndexFactory {
private final Settings settings;
- private final DefaultAnalysisMode mode;
+ private final ProjectAnalysisMode mode;
- public IndexFactory(DefaultAnalysisMode mode, Settings settings) {
+ public IndexFactory(ProjectAnalysisMode mode, Settings settings) {
this.mode = mode;
this.settings = settings;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
index f7fced2829d..121783e1da5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
@@ -19,18 +19,20 @@
*/
package org.sonar.batch.issue.tracking;
+import org.sonar.batch.util.BatchUtils;
+
+import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterators;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.batch.bootstrap.ServerClient;
public class DefaultServerLineHashesLoader implements ServerLineHashesLoader {
- private final ServerClient server;
+ private final WSLoader wsLoader;
- public DefaultServerLineHashesLoader(ServerClient server) {
- this.server = server;
+ public DefaultServerLineHashesLoader(WSLoader wsLoader) {
+ this.wsLoader = wsLoader;
}
@Override
@@ -44,7 +46,7 @@ public class DefaultServerLineHashesLoader implements ServerLineHashesLoader {
.addContext("file", fileKey)
.startDebug("Load line hashes");
try {
- return server.request("/api/sources/hash?key=" + ServerClient.encodeForUrl(fileKey));
+ return wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey));
} finally {
profiler.stopDebug();
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index c553aeb349a..370c3f32ca9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -190,7 +190,7 @@ public class BatchMediumTester {
}
TaskBuilder builder = new TaskBuilder(this);
builder.property("sonar.projectBaseDir", sonarProps.getParentFile().getAbsolutePath());
- for (Map.Entry entry : prop.entrySet()) {
+ for (Map.Entry<Object, Object> entry : prop.entrySet()) {
builder.property(entry.getKey().toString(), entry.getValue().toString());
}
return builder;
@@ -238,7 +238,7 @@ public class BatchMediumTester {
return ref.globalSettings();
}
- public FakeGlobalRepositoriesLoader add(Metric metric) {
+ public FakeGlobalRepositoriesLoader add(Metric<?> metric) {
Boolean optimizedBestValue = metric.isOptimizedBestValue();
ref.metrics().add(new org.sonar.batch.protocol.input.Metric(metricId,
metric.key(),
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
index 6acf8f31cb2..b49448be10c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
@@ -19,9 +19,10 @@
*/
package org.sonar.batch.phases;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.events.BatchStepEvent;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
@@ -48,7 +49,7 @@ public final class PhaseExecutor {
private final QProfileVerifier profileVerifier;
private final IssueExclusionsLoader issueExclusionsLoader;
private final IssuesReports issuesReport;
- private final DefaultAnalysisMode analysisMode;
+ private final ProjectAnalysisMode analysisMode;
private final LocalIssueTracking localIssueTracking;
public PhaseExecutor(InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
index fb6075057dd..2435330b613 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
@@ -19,8 +19,12 @@
*/
package org.sonar.batch.report;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
+import org.sonar.batch.util.BatchUtils;
import com.github.kevinsawicki.http.HttpRequest;
import com.google.common.annotations.VisibleForTesting;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -28,6 +32,7 @@ import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;
+
import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
import org.slf4j.Logger;
@@ -39,11 +44,9 @@ import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.scan.ImmutableProjectReactor;
-
import static java.lang.String.format;
@BatchSide
@@ -57,7 +60,7 @@ public class ReportPublisher implements Startable {
private final Server server;
private final Settings settings;
private final ImmutableProjectReactor projectReactor;
- private final DefaultAnalysisMode analysisMode;
+ private final ProjectAnalysisMode analysisMode;
private final TempFolder temp;
private ReportPublisherStep[] publishers;
@@ -66,7 +69,7 @@ public class ReportPublisher implements Startable {
private BatchReportWriter writer;
public ReportPublisher(Settings settings, ServerClient serverClient, Server server,
- ImmutableProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) {
+ ImmutableProjectReactor projectReactor, ProjectAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) {
this.serverClient = serverClient;
this.server = server;
this.projectReactor = projectReactor;
@@ -134,7 +137,7 @@ public class ReportPublisher implements Startable {
void sendOrDumpReport(File report) {
ProjectDefinition projectDefinition = projectReactor.getRoot();
String effectiveKey = projectDefinition.getKeyWithBranch();
- String relativeUrl = "/api/computation/submit_report?projectKey=" + effectiveKey + "&projectName=" + ServerClient.encodeForUrl(projectDefinition.getName());
+ String relativeUrl = "/api/computation/submit_report?projectKey=" + effectiveKey + "&projectName=" + BatchUtils.encodeForUrl(projectDefinition.getName());
String dumpDirLocation = settings.getString(DUMP_REPORT_PROP_KEY);
if (dumpDirLocation == null) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java
index 428e9bccab5..beb47749d6f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalRepositoriesLoader.java
@@ -19,22 +19,23 @@
*/
package org.sonar.batch.repository;
-import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.bootstrap.WSLoader;
+
import org.sonar.batch.protocol.input.GlobalRepositories;
public class DefaultGlobalRepositoriesLoader implements GlobalRepositoriesLoader {
private static final String BATCH_GLOBAL_URL = "/batch/global";
- private final ServerClient serverClient;
+ private final WSLoader wsLoader;
- public DefaultGlobalRepositoriesLoader(ServerClient serverClient) {
- this.serverClient = serverClient;
+ public DefaultGlobalRepositoriesLoader(WSLoader wsLoader) {
+ this.wsLoader = wsLoader;
}
@Override
public GlobalRepositories load() {
- return GlobalRepositories.fromJson(serverClient.request(BATCH_GLOBAL_URL));
+ return GlobalRepositories.fromJson(wsLoader.loadString(BATCH_GLOBAL_URL));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
index 71f4953769e..da008967662 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
@@ -19,11 +19,13 @@
*/
package org.sonar.batch.repository;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
+import org.sonar.batch.util.BatchUtils;
+import org.sonar.batch.bootstrap.WSLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.bootstrap.AnalysisProperties;
import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.rule.ModuleQProfiles;
@@ -34,25 +36,25 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
private static final String BATCH_PROJECT_URL = "/batch/project";
- private final ServerClient serverClient;
- private final DefaultAnalysisMode analysisMode;
+ private final WSLoader wsLoader;
+ private final ProjectAnalysisMode analysisMode;
- public DefaultProjectRepositoriesLoader(ServerClient serverClient, DefaultAnalysisMode analysisMode) {
- this.serverClient = serverClient;
+ public DefaultProjectRepositoriesLoader(WSLoader wsLoader, ProjectAnalysisMode analysisMode) {
+ this.wsLoader = wsLoader;
this.analysisMode = analysisMode;
}
@Override
public ProjectRepositories load(ProjectReactor reactor, AnalysisProperties taskProperties) {
String projectKey = reactor.getRoot().getKeyWithBranch();
- String url = BATCH_PROJECT_URL + "?key=" + ServerClient.encodeForUrl(projectKey);
+ String url = BATCH_PROJECT_URL + "?key=" + BatchUtils.encodeForUrl(projectKey);
if (taskProperties.properties().containsKey(ModuleQProfiles.SONAR_PROFILE_PROP)) {
LOG.warn("Ability to set quality profile from command line using '" + ModuleQProfiles.SONAR_PROFILE_PROP
+ "' is deprecated and will be dropped in a future SonarQube version. Please configure quality profile used by your project on SonarQube server.");
- url += "&profile=" + ServerClient.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP));
+ url += "&profile=" + BatchUtils.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP));
}
url += "&preview=" + analysisMode.isPreview();
- return ProjectRepositories.fromJson(serverClient.request(url));
+ return ProjectRepositories.fromJson(wsLoader.loadString(url));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java
index e71e9eb54cb..b6d9723bb55 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultServerIssuesLoader.java
@@ -19,35 +19,32 @@
*/
package org.sonar.batch.repository;
+import org.sonar.batch.util.BatchUtils;
+
+import com.google.common.io.ByteSource;
+import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Function;
-import com.google.common.io.InputSupplier;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
-import org.sonar.api.utils.HttpDownloader;
import java.io.IOException;
import java.io.InputStream;
public class DefaultServerIssuesLoader implements ServerIssuesLoader {
- private final ServerClient serverClient;
+ private final WSLoader wsLoader;
- public DefaultServerIssuesLoader(ServerClient serverClient) {
- this.serverClient = serverClient;
+ public DefaultServerIssuesLoader(WSLoader wsLoader) {
+ this.wsLoader = wsLoader;
}
@Override
public void load(String componentKey, Function<ServerIssue, Void> consumer, boolean incremental) {
- try {
- InputSupplier<InputStream> request = serverClient.doRequest("/batch/issues?key=" + ServerClient.encodeForUrl(componentKey), "GET", null);
- parseIssues(request, consumer);
- } catch (HttpDownloader.HttpException e) {
- throw serverClient.handleHttpException(e);
- }
+ ByteSource request = wsLoader.loadSource("/batch/issues?key=" + BatchUtils.encodeForUrl(componentKey));
+ parseIssues(request, consumer);
}
- private static void parseIssues(InputSupplier<InputStream> input, Function<ServerIssue, Void> consumer) {
- try (InputStream is = input.getInput()) {
+ private static void parseIssues(ByteSource input, Function<ServerIssue, Void> consumer) {
+ try (InputStream is = input.openStream()) {
ServerIssue previousIssue = ServerIssue.parseDelimitedFrom(is);
while (previousIssue != null) {
consumer.apply(previousIssue);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java b/sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java
index 7208086c308..c6f1d8ae58c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/user/UserRepository.java
@@ -19,12 +19,13 @@
*/
package org.sonar.batch.repository.user;
+import org.sonar.batch.util.BatchUtils;
+
+import org.sonar.batch.bootstrap.WSLoader;
+import com.google.common.io.ByteSource;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
-import com.google.common.io.InputSupplier;
-import org.sonar.api.utils.HttpDownloader;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.input.BatchInput;
import java.io.IOException;
@@ -36,10 +37,10 @@ import java.util.List;
public class UserRepository {
- private ServerClient serverClient;
+ private WSLoader wsLoader;
- public UserRepository(ServerClient serverClient) {
- this.serverClient = serverClient;
+ public UserRepository(WSLoader wsLoader) {
+ this.wsLoader = wsLoader;
}
public Collection<BatchInput.User> loadFromWs(List<String> userLogins) {
@@ -47,25 +48,20 @@ public class UserRepository {
return Collections.emptyList();
}
- try {
- InputSupplier<InputStream> request = serverClient.doRequest("/batch/users?logins=" + Joiner.on(',').join(Lists.transform(userLogins, new Function<String, String>() {
- @Override
- public String apply(String input) {
- return ServerClient.encodeForUrl(input);
- }
- })), "GET", null);
-
- return parseUsers(request);
+ ByteSource source = wsLoader.loadSource("/batch/users?logins=" + Joiner.on(',').join(Lists.transform(userLogins, new Function<String, String>() {
+ @Override
+ public String apply(String input) {
+ return BatchUtils.encodeForUrl(input);
+ }
+ })));
- } catch (HttpDownloader.HttpException e) {
- throw serverClient.handleHttpException(e);
- }
+ return parseUsers(source);
}
- private static Collection<BatchInput.User> parseUsers(InputSupplier<InputStream> input) {
+ private static Collection<BatchInput.User> parseUsers(ByteSource input) {
List<BatchInput.User> users = new ArrayList<>();
- try (InputStream is = input.getInput()) {
+ try (InputStream is = input.openStream()) {
BatchInput.User user = BatchInput.User.parseDelimitedFrom(is);
while (user != null) {
users.add(user);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
index bf1d0815ede..cf5a3c44fd9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
@@ -20,12 +20,13 @@
package org.sonar.batch.scan;
import com.google.common.collect.Lists;
+
import java.util.List;
+
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.GlobalSettings;
import org.sonar.batch.protocol.input.ProjectRepositories;
@@ -35,10 +36,10 @@ import org.sonar.batch.protocol.input.ProjectRepositories;
public class ModuleSettings extends Settings {
private final ProjectRepositories projectReferentials;
- private DefaultAnalysisMode analysisMode;
+ private ProjectAnalysisMode analysisMode;
public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition moduleDefinition, ProjectRepositories projectReferentials,
- DefaultAnalysisMode analysisMode) {
+ ProjectAnalysisMode analysisMode) {
super(batchSettings.getDefinitions());
this.projectReferentials = projectReferentials;
this.analysisMode = analysisMode;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultAnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectAnalysisMode.java
index c6b70402b95..1f544864cbe 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultAnalysisMode.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectAnalysisMode.java
@@ -17,7 +17,9 @@
* 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.sonar.batch.bootstrap;
+package org.sonar.batch.scan;
+
+import org.sonar.batch.bootstrap.AnalysisProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,21 +33,27 @@ import java.util.Map;
/**
* @since 4.0
*/
-public class DefaultAnalysisMode implements AnalysisMode {
+public class ProjectAnalysisMode implements AnalysisMode {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class);
+ private static final Logger LOG = LoggerFactory.getLogger(ProjectAnalysisMode.class);
private boolean preview;
private boolean incremental;
+ private boolean quick;
private boolean mediumTestMode;
- public DefaultAnalysisMode(Map<String, String> props) {
- init(props);
+ public ProjectAnalysisMode(AnalysisProperties props) {
+ init(props.properties());
}
@Override
public boolean isPreview() {
- return preview || incremental;
+ return preview || incremental || quick;
+ }
+
+ @Override
+ public boolean isQuick() {
+ return quick;
}
@Override
@@ -66,20 +74,19 @@ public class DefaultAnalysisMode implements AnalysisMode {
String mode = props.get(CoreProperties.ANALYSIS_MODE);
preview = CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
incremental = CoreProperties.ANALYSIS_MODE_INCREMENTAL.equals(mode);
+ quick = CoreProperties.ANALYSIS_MODE_QUICK.equals(mode);
}
mediumTestMode = "true".equals(props.get(BatchMediumTester.MEDIUM_TEST_ENABLED));
if (incremental) {
LOG.info("Incremental mode");
} else if (preview) {
LOG.info("Preview mode");
+ } else if (quick) {
+ LOG.info("Quick mode");
}
if (mediumTestMode) {
LOG.info("Medium test mode");
}
- // To stay compatible with plugins that use the old property to check mode
- if (incremental || preview) {
- props.put(CoreProperties.DRY_RUN, "true");
- }
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index 06d0a4423a2..1e0b5d4571b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -34,7 +34,6 @@ import org.sonar.batch.DefaultFileLinesContextFactory;
import org.sonar.batch.DefaultProjectTree;
import org.sonar.batch.ProjectConfigurator;
import org.sonar.batch.bootstrap.AnalysisProperties;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
@@ -83,7 +82,6 @@ public class ProjectScanContainer extends ComponentContainer {
private static final Logger LOG = Loggers.get(ProjectScanContainer.class);
- private final DefaultAnalysisMode analysisMode;
private final Object[] components;
private final AnalysisProperties props;
@@ -91,7 +89,6 @@ public class ProjectScanContainer extends ComponentContainer {
super(globalContainer);
this.props = props;
this.components = components;
- analysisMode = globalContainer.getComponentByType(DefaultAnalysisMode.class);
}
@Override
@@ -123,6 +120,7 @@ public class ProjectScanContainer extends ComponentContainer {
private void addBatchComponents() {
add(
props,
+ ProjectAnalysisMode.class,
projectReactorBuilder(),
new MutableProjectReactorProvider(getComponentByType(ProjectBootstrapper.class)),
new ImmutableProjectReactorProvider(),
@@ -134,6 +132,7 @@ public class ProjectScanContainer extends ComponentContainer {
ProjectExclusions.class,
ProjectReactorValidator.class,
new ProjectRepositoriesProvider(),
+ new WSLoaderProjectProvider(),
DefaultResourceCreationLock.class,
CodeColorizers.class,
MetricProvider.class,
@@ -206,7 +205,7 @@ public class ProjectScanContainer extends ComponentContainer {
LOG.debug("Start recursive analysis of project modules");
DefaultProjectTree tree = getComponentByType(DefaultProjectTree.class);
scanRecursively(tree.getRootProject());
- if (analysisMode.isMediumTest()) {
+ if (getComponentByType(ProjectAnalysisMode.class).isMediumTest()) {
getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
index 14720cbc944..5066ccfc524 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
@@ -20,13 +20,14 @@
package org.sonar.batch.scan;
import com.google.common.collect.ImmutableMap;
+
import java.util.Map;
+
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.DroppedPropertyChecker;
import org.sonar.batch.bootstrap.GlobalSettings;
import org.sonar.batch.protocol.input.ProjectRepositories;
@@ -43,10 +44,10 @@ public class ProjectSettings extends Settings {
private final GlobalSettings globalSettings;
private final ProjectRepositories projectRepositories;
- private final DefaultAnalysisMode mode;
+ private final ProjectAnalysisMode mode;
public ProjectSettings(ProjectReactor reactor, GlobalSettings globalSettings, PropertyDefinitions propertyDefinitions,
- ProjectRepositories projectRepositories, DefaultAnalysisMode mode) {
+ ProjectRepositories projectRepositories, ProjectAnalysisMode mode) {
super(propertyDefinitions);
this.mode = mode;
getEncryption().setPathToSecretKey(globalSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/WSLoaderProjectProvider.java b/sonar-batch/src/main/java/org/sonar/batch/scan/WSLoaderProjectProvider.java
new file mode 100644
index 00000000000..164354efb29
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/WSLoaderProjectProvider.java
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.scan;
+
+import org.picocontainer.injectors.ProviderAdapter;
+
+import java.util.Map;
+
+import org.sonar.batch.bootstrap.AnalysisProperties;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.bootstrap.WSLoader;
+import org.sonar.home.cache.PersistentCache;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+
+public class WSLoaderProjectProvider extends ProviderAdapter {
+ private WSLoader wsLoader;
+
+ public WSLoader provide(AnalysisProperties props, AnalysisMode mode, PersistentCache cache, ServerClient client) {
+ if (wsLoader == null) {
+ cache.reconfigure();
+ wsLoader = new WSLoader(isCacheEnabled(props.properties(), mode.isPreview()), cache, client);
+ wsLoader.setStrategy(getStrategy(mode));
+ }
+ return wsLoader;
+ }
+
+ private static LoadStrategy getStrategy(AnalysisMode mode) {
+ if (mode.isQuick()) {
+ return LoadStrategy.CACHE_FIRST;
+ }
+
+ return LoadStrategy.SERVER_FIRST;
+ }
+
+ private static boolean isCacheEnabled(Map<String, String> props, boolean isPreview) {
+ String enableOffline = props.get("sonar.enableOffline");
+ return isPreview && "true".equals(enableOffline);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
index 317612d9f69..f7296e97de5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
@@ -19,6 +19,8 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
@@ -28,7 +30,6 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import javax.annotation.CheckForNull;
@@ -43,12 +44,12 @@ class InputFileBuilder {
private final LanguageDetection langDetection;
private final StatusDetection statusDetection;
private final DefaultModuleFileSystem fs;
- private final DefaultAnalysisMode analysisMode;
+ private final ProjectAnalysisMode analysisMode;
private final Settings settings;
private final FileMetadata fileMetadata;
InputFileBuilder(String moduleKey, PathResolver pathResolver, LanguageDetection langDetection,
- StatusDetection statusDetection, DefaultModuleFileSystem fs, DefaultAnalysisMode analysisMode, Settings settings, FileMetadata fileMetadata) {
+ StatusDetection statusDetection, DefaultModuleFileSystem fs, ProjectAnalysisMode analysisMode, Settings settings, FileMetadata fileMetadata) {
this.moduleKey = moduleKey;
this.pathResolver = pathResolver;
this.langDetection = langDetection;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
index 304e330e7c1..3e9d31fbd89 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
@@ -19,12 +19,13 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@BatchSide
public class InputFileBuilderFactory {
@@ -33,12 +34,12 @@ public class InputFileBuilderFactory {
private final PathResolver pathResolver;
private final LanguageDetectionFactory langDetectionFactory;
private final StatusDetectionFactory statusDetectionFactory;
- private final DefaultAnalysisMode analysisMode;
+ private final ProjectAnalysisMode analysisMode;
private final Settings settings;
private final FileMetadata fileMetadata;
public InputFileBuilderFactory(ProjectDefinition def, PathResolver pathResolver, LanguageDetectionFactory langDetectionFactory,
- StatusDetectionFactory statusDetectionFactory, DefaultAnalysisMode analysisMode, Settings settings, FileMetadata fileMetadata) {
+ StatusDetectionFactory statusDetectionFactory, ProjectAnalysisMode analysisMode, Settings settings, FileMetadata fileMetadata) {
this.fileMetadata = fileMetadata;
this.moduleKey = def.getKeyWithBranch();
this.pathResolver = pathResolver;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReports.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReports.java
index eaa566bddfd..9aaf25528c6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReports.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReports.java
@@ -19,16 +19,17 @@
*/
package org.sonar.batch.scan.report;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.sonar.api.batch.BatchSide;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@BatchSide
public class IssuesReports {
- private final DefaultAnalysisMode analysisMode;
+ private final ProjectAnalysisMode analysisMode;
private final Reporter[] reporters;
- public IssuesReports(DefaultAnalysisMode analysisMode, Reporter... reporters) {
+ public IssuesReports(ProjectAnalysisMode analysisMode, Reporter... reporters) {
this.reporters = reporters;
this.analysisMode = analysisMode;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/util/BatchUtils.java b/sonar-batch/src/main/java/org/sonar/batch/util/BatchUtils.java
index e6321ac8b3b..b5460a6e2a1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/util/BatchUtils.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/util/BatchUtils.java
@@ -19,6 +19,9 @@
*/
package org.sonar.batch.util;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
import org.apache.commons.lang.StringUtils;
public class BatchUtils {
@@ -34,4 +37,13 @@ public class BatchUtils {
String cleanKey = StringUtils.deleteWhitespace(projectKey);
return StringUtils.replace(cleanKey, ":", "_");
}
+
+ public static String encodeForUrl(String url) {
+ try {
+ return URLEncoder.encode(url, "UTF-8");
+
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException("Encoding not supported", e);
+ }
+ }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
index c8d2e367475..78995ef7a74 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
@@ -50,9 +50,10 @@ public class BatchPluginInstallerTest {
@Test
public void listRemotePlugins() {
- ServerClient server = mock(ServerClient.class);
- when(server.request("/deploy/plugins/index.txt")).thenReturn("checkstyle\nsqale");
- BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate);
+ WSLoader wsLoader = mock(WSLoader.class);
+ when(wsLoader.load("/deploy/plugins/index.txt")).thenReturn("checkstyle\nsqale".getBytes());
+ when(wsLoader.loadString("/deploy/plugins/index.txt")).thenReturn("checkstyle\nsqale");
+ BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate);
List<RemotePlugin> remotePlugins = installer.listRemotePlugins();
assertThat(remotePlugins).extracting("key").containsOnly("checkstyle", "sqale");
@@ -63,8 +64,8 @@ public class BatchPluginInstallerTest {
File pluginJar = temp.newFile();
when(fileCache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar);
- ServerClient server = mock(ServerClient.class);
- BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate);
+ WSLoader wsLoader = mock(WSLoader.class);
+ BatchPluginInstaller installer = new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate);
RemotePlugin remote = new RemotePlugin("checkstyle").setFile("checkstyle-plugin.jar", "fakemd5_1");
File file = installer.download(remote);
@@ -76,9 +77,9 @@ public class BatchPluginInstallerTest {
public void should_fail_to_get_plugin_index() {
thrown.expect(IllegalStateException.class);
- ServerClient server = mock(ServerClient.class);
- doThrow(new IllegalStateException()).when(server).request("/deploy/plugins/index.txt");
+ WSLoader wsLoader = mock(WSLoader.class);
+ doThrow(new IllegalStateException()).when(wsLoader).load("/deploy/plugins/index.txt");
- new BatchPluginInstaller(server, fileCache, pluginPredicate).installRemotes();
+ new BatchPluginInstaller(wsLoader, fileCache, pluginPredicate).installRemotes();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java
index 511d29d9244..937281d2fba 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java
@@ -22,7 +22,6 @@ package org.sonar.batch.bootstrap;
import org.junit.Test;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -30,7 +29,7 @@ import static org.mockito.Mockito.when;
public class BatchPluginPredicateTest {
Settings settings = new Settings();
- DefaultAnalysisMode mode = mock(DefaultAnalysisMode.class);
+ GlobalMode mode = mock(GlobalMode.class);
@Test
public void accept_if_no_inclusions_nor_exclusions() {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
index b01040b29cd..aef314012ca 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
@@ -40,7 +40,7 @@ import static org.mockito.Mockito.when;
public class ExtensionInstallerTest {
- DefaultAnalysisMode mode;
+ GlobalMode mode;
BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
private static Plugin newPluginInstance(final Object... extensions) {
@@ -53,7 +53,7 @@ public class ExtensionInstallerTest {
@Before
public void setUp() {
- mode = mock(DefaultAnalysisMode.class);
+ mode = mock(GlobalMode.class);
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalModeTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalModeTest.java
new file mode 100644
index 00000000000..fb174d9d506
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalModeTest.java
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import org.sonar.api.CoreProperties;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GlobalModeTest {
+ @Test
+ public void testQuick() {
+ GlobalMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_QUICK);
+ assertThat(mode.isPreview()).isTrue();
+ }
+
+ @Test
+ public void testPreview() {
+ GlobalMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW);
+ assertThat(mode.isPreview()).isTrue();
+ }
+
+ @Test
+ public void testIncremental() {
+ GlobalMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_INCREMENTAL);
+ assertThat(mode.isPreview()).isTrue();
+ }
+
+ @Test
+ public void testOtherProperty() {
+ GlobalMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ANALYSIS);
+ assertThat(mode.isPreview()).isFalse();
+ }
+
+ @Test
+ public void testDeprecatedDryRun() {
+ GlobalMode mode = createMode(CoreProperties.DRY_RUN, "true");
+ assertThat(mode.isPreview()).isTrue();
+ }
+
+ private GlobalMode createMode(String key, String value) {
+ Map<String, String> map = new HashMap<>();
+ map.put(key, value);
+ BootstrapProperties props = new BootstrapProperties(map);
+ return new GlobalMode(props);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalSettingsTest.java
index 18f205ad772..b48ebc78db4 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalSettingsTest.java
@@ -19,7 +19,11 @@
*/
package org.sonar.batch.bootstrap;
+import org.sonar.api.CoreProperties;
+
import java.util.Collections;
+
+import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -28,7 +32,6 @@ import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.batch.protocol.input.GlobalRepositories;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -43,13 +46,13 @@ public class GlobalSettingsTest {
GlobalRepositories globalRef;
BootstrapProperties bootstrapProps;
- private DefaultAnalysisMode mode;
+ private GlobalMode mode;
@Before
public void prepare() {
globalRef = new GlobalRepositories();
bootstrapProps = new BootstrapProperties(Collections.<String, String>emptyMap());
- mode = mock(DefaultAnalysisMode.class);
+ mode = mock(GlobalMode.class);
}
@Test
@@ -60,6 +63,13 @@ public class GlobalSettingsTest {
assertThat(batchSettings.getBoolean("sonar.cpd.cross")).isTrue();
}
+
+ @Test
+ public void support_deprecated_dry_run() {
+ when(mode.isPreview()).thenReturn(true);
+ GlobalSettings batchSettings = new GlobalSettings(bootstrapProps, new PropertyDefinitions(), globalRef, mode);
+ assertThat(batchSettings.getString(CoreProperties.DRY_RUN)).isEqualTo("true");
+ }
@Test
public void should_log_warn_msg_for_each_jdbc_property_if_present() {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java
new file mode 100644
index 00000000000..757e3536717
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java
@@ -0,0 +1,118 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import org.apache.commons.io.IOUtils;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static org.apache.commons.io.IOUtils.write;
+
+public class MockHttpServer {
+ private Server server;
+ private String responseBody;
+ private String requestBody;
+ private String mockResponseData;
+ private int mockResponseStatus = SC_OK;
+ private int numRequests = 0;
+
+ public void start() throws Exception {
+ server = new Server(0);
+ server.setHandler(getMockHandler());
+ server.start();
+ }
+
+ public int getNumberRequests() {
+ return numRequests;
+ }
+
+ /**
+ * Creates an {@link org.mortbay.jetty.handler.AbstractHandler handler} returning an arbitrary String as a response.
+ *
+ * @return never <code>null</code>.
+ */
+ public Handler getMockHandler() {
+ Handler handler = new AbstractHandler() {
+
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
+ numRequests++;
+ setResponseBody(getMockResponseData());
+ setRequestBody(IOUtils.toString(baseRequest.getInputStream()));
+ response.setStatus(mockResponseStatus);
+ response.setContentType("text/xml;charset=utf-8");
+ write(getResponseBody(), response.getOutputStream());
+ baseRequest.setHandled(true);
+ }
+ };
+ return handler;
+ }
+
+ public void stop() {
+ try {
+ if (server != null) {
+ server.stop();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to stop HTTP server", e);
+ }
+ }
+
+ public String getResponseBody() {
+ return responseBody;
+ }
+
+ public void setResponseBody(String responseBody) {
+ this.responseBody = responseBody;
+ }
+
+ public String getRequestBody() {
+ return requestBody;
+ }
+
+ public void setRequestBody(String requestBody) {
+ this.requestBody = requestBody;
+ }
+
+ public void setMockResponseStatus(int status) {
+ this.mockResponseStatus = status;
+ }
+
+ public String getMockResponseData() {
+ return mockResponseData;
+ }
+
+ public void setMockResponseData(String mockResponseData) {
+ this.mockResponseData = mockResponseData;
+ }
+
+ public int getPort() {
+ return server.getConnectors()[0].getLocalPort();
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PersistentCacheProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PersistentCacheProviderTest.java
index 813c5efce70..4857621a910 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PersistentCacheProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PersistentCacheProviderTest.java
@@ -45,19 +45,4 @@ public class PersistentCacheProviderTest {
public void test_cache_dir() {
assertThat(provider.provide(props).getBaseDirectory().toFile()).exists().isDirectory();
}
-
- @Test
- public void test_enableCache() {
- // normally force update (cache disabled)
- assertThat(provider.provide(props).isForceUpdate()).isTrue();
-
- props.properties().put("sonar.enableHttpCache", "true");
- provider = new PersistentCacheProvider();
- assertThat(provider.provide(props).isForceUpdate()).isFalse();
- }
-
- @Test
- public void test_reconfigure() {
-
- }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java
index 75538ff5b73..56133fe40d0 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java
@@ -19,30 +19,18 @@
*/
package org.sonar.batch.bootstrap;
+import org.sonar.batch.util.BatchUtils;
+
import java.io.File;
-import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.io.IOUtils;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+
import org.junit.After;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
-import org.sonar.home.cache.PersistentCache;
-import org.sonar.home.cache.PersistentCacheBuilder;
-
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-import static org.apache.commons.io.IOUtils.write;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -53,19 +41,10 @@ public class ServerClientTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Rule
- public TemporaryFolder cacheTmp = new TemporaryFolder();
- @Rule
public ExpectedException thrown = ExpectedException.none();
private MockHttpServer server = null;
private BootstrapProperties bootstrapProps = mock(BootstrapProperties.class);
- private DefaultAnalysisMode mode = null;
-
- @Before
- public void setUp() {
- mode = mock(DefaultAnalysisMode.class);
- when(mode.isPreview()).thenReturn(true);
- }
@After
public void stopServer() {
@@ -75,77 +54,29 @@ public class ServerClientTest {
}
@Test
- public void dont_cache_post_request() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
- assertThat(newServerClient().request("/foo", "POST")).isEqualTo("this is the content");
-
- // cache never accessed, so not even the .lock should be there
- assertThat(getNumFilesInCache()).isEqualTo(0);
- }
-
- @Test
- public void dont_cache_non_preview_mode() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
- when(mode.isPreview()).thenReturn(false);
- assertThat(newServerClient().request("/foo")).isEqualTo("this is the content");
-
- // cache never accessed, so not even the .lock should be there
- assertThat(getNumFilesInCache()).isEqualTo(0);
- }
-
- @Test
- public void cache_preview_mode() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
- assertThat(newServerClient().request("/foo")).isEqualTo("this is the content");
-
- // should have the .lock and one request cached
- assertThat(getNumFilesInCache()).isEqualTo(2);
- }
-
- @Test
public void should_remove_url_ending_slash() {
BootstrapProperties settings = mock(BootstrapProperties.class);
when(settings.property("sonar.host.url")).thenReturn("http://localhost:8080/sonar/");
-
- PersistentCache ps = new PersistentCacheBuilder(new Slf4jLogger()).setSonarHome(cacheTmp.getRoot().toPath()).build();
- ServerClient client = new ServerClient(settings, new EnvironmentInformation("Junit", "4"), ps, mode);
+ ServerClient client = new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
assertThat(client.getURL()).isEqualTo("http://localhost:8080/sonar");
}
@Test
public void should_request_url() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
- assertThat(newServerClient().request("/foo")).isEqualTo("this is the content");
+ startServer(null, "this is the content");
+ assertThat(newServerClient().downloadString("/foo")).isEqualTo("this is the content");
}
@Test
public void should_escape_html_from_url() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
- assertThat(newServerClient().request("/<foo>")).isEqualTo("this is the content");
+ startServer(null, "this is the content");
+ assertThat(newServerClient().downloadString("/<foo>")).isEqualTo("this is the content");
}
@Test
public void should_download_file() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseData("this is the content");
-
+ startServer(null, "this is the content");
File file = temp.newFile();
newServerClient().download("/foo", file);
assertThat(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8)).isEqualTo("this is the content");
@@ -153,138 +84,55 @@ public class ServerClientTest {
@Test
public void should_fail_if_unauthorized_with_no_login_password() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseStatus(401);
-
+ startServer(401, null);
thrown.expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
- newServerClient().request("/foo");
+ newServerClient().downloadString("/foo");
}
@Test
public void should_fail_if_unauthorized_with_login_password_provided() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseStatus(401);
+ startServer(401, null);
when(bootstrapProps.property(eq("sonar.login"))).thenReturn("login");
when(bootstrapProps.property(eq("sonar.password"))).thenReturn("password");
thrown.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password");
- newServerClient().request("/foo");
+ newServerClient().downloadString("/foo");
}
@Test
public void should_display_json_error_when_403() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseStatus(403);
- server.setMockResponseData("{\"errors\":[{\"msg\":\"Insufficient privileges\"}]}");
-
+ startServer(403, "{\"errors\":[{\"msg\":\"Insufficient privileges\"}]}");
thrown.expectMessage("Insufficient privileges");
- newServerClient().request("/foo");
+ newServerClient().downloadString("/foo");
}
@Test
public void should_fail_if_error() throws Exception {
- server = new MockHttpServer();
- server.start();
- server.setMockResponseStatus(500);
-
+ startServer(500, null);
thrown.expectMessage("Fail to execute request [code=500, url=http://localhost:" + server.getPort() + "/foo]");
- newServerClient().request("/foo");
+ newServerClient().downloadString("/foo");
}
@Test
- public void testEncode() {
- assertThat(ServerClient.encodeForUrl("my value")).isEqualTo("my+value");
+ public void string_encode() {
+ assertThat(BatchUtils.encodeForUrl("my value")).isEqualTo("my+value");
}
private ServerClient newServerClient() {
when(bootstrapProps.property("sonar.host.url")).thenReturn("http://localhost:" + server.getPort());
- PersistentCache ps = new PersistentCacheBuilder(new Slf4jLogger()).setSonarHome(cacheTmp.getRoot().toPath()).build();
- return new ServerClient(bootstrapProps, new EnvironmentInformation("Junit", "4"), ps, mode);
+ return new ServerClient(bootstrapProps, new EnvironmentInformation("Junit", "4"));
}
- private int getNumFilesInCache() {
- return new File(cacheTmp.getRoot(), "ws_cache").listFiles().length;
- }
-
- static class MockHttpServer {
- private Server server;
- private String responseBody;
- private String requestBody;
- private String mockResponseData;
- private int mockResponseStatus = SC_OK;
-
- public void start() throws Exception {
- server = new Server(0);
- server.setHandler(getMockHandler());
- server.start();
- }
-
- /**
- * Creates an {@link org.mortbay.jetty.handler.AbstractHandler handler} returning an arbitrary String as a response.
- *
- * @return never <code>null</code>.
- */
- public Handler getMockHandler() {
- Handler handler = new AbstractHandler() {
-
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- setResponseBody(getMockResponseData());
- setRequestBody(IOUtils.toString(baseRequest.getInputStream()));
- response.setStatus(mockResponseStatus);
- response.setContentType("text/xml;charset=utf-8");
- write(getResponseBody(), response.getOutputStream());
- baseRequest.setHandled(true);
- }
- };
- return handler;
- }
-
- public void stop() {
- try {
- if (server != null) {
- server.stop();
- }
- } catch (Exception e) {
- throw new IllegalStateException("Fail to stop HTTP server", e);
- }
- }
-
- public String getResponseBody() {
- return responseBody;
- }
-
- public void setResponseBody(String responseBody) {
- this.responseBody = responseBody;
- }
-
- public String getRequestBody() {
- return requestBody;
- }
-
- public void setRequestBody(String requestBody) {
- this.requestBody = requestBody;
- }
-
- public void setMockResponseStatus(int status) {
- this.mockResponseStatus = status;
- }
-
- public String getMockResponseData() {
- return mockResponseData;
- }
-
- public void setMockResponseData(String mockResponseData) {
- this.mockResponseData = mockResponseData;
+ private void startServer(Integer responseStatus, String responseData) throws Exception {
+ server = new MockHttpServer();
+ server.start();
+
+ if (responseStatus != null) {
+ server.setMockResponseStatus(responseStatus);
}
-
- public int getPort() {
- return server.getConnectors()[0].getLocalPort();
+ if (responseData != null) {
+ server.setMockResponseData(responseData);
}
-
}
-
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderGlobalProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderGlobalProviderTest.java
new file mode 100644
index 00000000000..8cc8b118018
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderGlobalProviderTest.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Mockito.when;
+
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+import org.junit.Test;
+import org.junit.Before;
+import org.sonar.home.cache.PersistentCache;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class WSLoaderGlobalProviderTest {
+ @Mock
+ private PersistentCache cache;
+
+ @Mock
+ private ServerClient client;
+
+ @Mock
+ private GlobalMode mode;
+
+ private WSLoaderGlobalProvider loaderProvider;
+ private Map<String, String> propMap;
+ private BootstrapProperties props;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ loaderProvider = new WSLoaderGlobalProvider();
+ }
+
+ @Test
+ public void testDefault() {
+ propMap = new HashMap<>();
+ props = new BootstrapProperties(propMap);
+
+ WSLoader wsLoader = loaderProvider.provide(props, mode, cache, client);
+ assertThat(wsLoader.getStrategy()).isEqualTo(LoadStrategy.SERVER_FIRST);
+ assertThat(wsLoader.isCacheEnabled()).isEqualTo(false);
+ }
+
+ @Test
+ public void testOffline() {
+ propMap = new HashMap<>();
+ propMap.put("sonar.enableOffline", "true");
+ when(mode.isPreview()).thenReturn(true);
+ props = new BootstrapProperties(propMap);
+
+ WSLoader wsLoader = loaderProvider.provide(props, mode, cache, client);
+ assertThat(wsLoader.isCacheEnabled()).isEqualTo(true);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java
new file mode 100644
index 00000000000..c4571c9e8e6
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTest.java
@@ -0,0 +1,214 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import org.sonar.api.utils.HttpDownloader;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.apache.commons.io.IOUtils;
+import org.mockito.Mockito;
+import org.mockito.InOrder;
+
+import java.io.IOException;
+import java.net.URI;
+
+import static org.mockito.Mockito.mock;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.anyInt;
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.sonar.home.cache.PersistentCache;
+import org.mockito.Mock;
+
+public class WSLoaderTest {
+ private final static String ID = "/dummy";
+ private final static String cacheValue = "cache";
+ private final static String serverValue = "server";
+
+ @Mock
+ private ServerClient client;
+ @Mock
+ private PersistentCache cache;
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenReturn(IOUtils.toInputStream(serverValue));
+ when(cache.get(ID, null)).thenReturn(cacheValue.getBytes());
+ when(client.getURI(anyString())).thenAnswer(new Answer<URI>() {
+ @Override
+ public URI answer(InvocationOnMock invocation) throws Throwable {
+ return new URI((String) invocation.getArguments()[0]);
+ }
+ });
+ }
+
+ @Test
+ public void dont_retry_server() throws IOException {
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.setCacheEnabled(true);
+
+ assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
+ assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
+
+ // only try once the server
+ verify(client, times(1)).load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt());
+ verify(cache, times(2)).get(ID, null);
+ }
+
+ @Test
+ public void test_cache_strategy_fallback() throws IOException {
+ when(cache.get(ID, null)).thenReturn(null);
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ loader.setCacheEnabled(true);
+
+ loader.load(ID);
+
+ InOrder inOrder = Mockito.inOrder(client, cache);
+ inOrder.verify(cache).get(ID, null);
+ inOrder.verify(client).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
+ }
+
+ @Test
+ public void test_server_strategy_fallback() throws IOException {
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.setCacheEnabled(true);
+ assertThat(loader.loadString(ID)).isEqualTo(cacheValue);
+
+ InOrder inOrder = Mockito.inOrder(client, cache);
+ inOrder.verify(client).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
+ inOrder.verify(cache).get(ID, null);
+ }
+
+ @Test
+ public void test_put_cache() throws IOException {
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.load(ID);
+ verify(cache).put(ID, serverValue.getBytes());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void test_throw_cache_exception_fallback() throws IOException {
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
+ when(cache.get(ID, null)).thenThrow(new NullPointerException());
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.setCacheEnabled(true);
+
+ loader.load(ID);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_throw_cache_exception() throws IOException {
+ when(cache.get(ID, null)).thenThrow(new IllegalStateException());
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ loader.setCacheEnabled(true);
+
+ loader.load(ID);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void test_throw_http_exceptions() {
+ HttpDownloader.HttpException httpException = mock(HttpDownloader.HttpException.class);
+ IllegalStateException wrapperException = new IllegalStateException(httpException);
+
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(wrapperException);
+
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+
+ try {
+ loader.load(ID);
+ } catch(IllegalStateException e) {
+ // cache should not be used
+ verifyNoMoreInteractions(cache);
+ throw e;
+ }
+ }
+
+ @Test
+ public void test_server_not_accessible() throws IOException {
+ when(client.load(anyString(), anyString(), anyBoolean(), anyInt(), anyInt())).thenThrow(new IllegalStateException());
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.load(ID);
+ loader.load(ID);
+
+ // only try once from server
+ verify(client, times(1)).load(eq(ID), anyString(), anyBoolean(), anyInt(), anyInt());
+ verify(cache, times(2)).get(ID, null);
+ }
+
+ @Test
+ public void test_change_strategy() throws IOException {
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ test_cache_strategy_fallback();
+ }
+
+ @Test
+ public void test_enable_cache() throws IOException {
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setCacheEnabled(false);
+ test_cache_disabled();
+ }
+
+ @Test
+ public void test_server_strategy() throws IOException {
+ WSLoader loader = new WSLoader(true, cache, client);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ loader.load(ID);
+
+ // should not fetch from cache
+ verify(cache).put(ID, serverValue.getBytes());
+ verifyNoMoreInteractions(cache);
+ }
+
+ @Test
+ public void test_cache_disabled() throws IOException {
+ WSLoader loader = new WSLoader(cache, client);
+ loader.load(ID);
+
+ // should not even put
+ verifyNoMoreInteractions(cache);
+ }
+
+ @Test
+ public void test_string() {
+ WSLoader loader = new WSLoader(cache, client);
+ assertThat(loader.loadString(ID)).isEqualTo(serverValue);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTestWithServer.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTestWithServer.java
new file mode 100644
index 00000000000..5b5f2c7efee
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/WSLoaderTestWithServer.java
@@ -0,0 +1,112 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.bootstrap;
+
+import static org.mockito.Mockito.mock;
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+import static org.mockito.Mockito.when;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.home.cache.PersistentCache;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class WSLoaderTestWithServer {
+ private static final String RESPONSE_STRING = "this is the content";
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private MockHttpServer server;
+ private PersistentCache cache;
+ private ServerClient client;
+ private WSLoader loader;
+
+ @Before
+ public void setUp() throws Exception {
+ server = new MockHttpServer();
+ server.start();
+
+ BootstrapProperties bootstrapProps = mock(BootstrapProperties.class);
+ when(bootstrapProps.property("sonar.host.url")).thenReturn("http://localhost:" + server.getPort());
+
+ client = new ServerClient(bootstrapProps, new EnvironmentInformation("Junit", "4"));
+ cache = new PersistentCache(temp.getRoot().toPath(), 1000 * 60, new Slf4jLogger());
+ loader = new WSLoader(cache, client);
+ }
+
+ @After
+ public void tearDown() {
+ if (server != null) {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testServer() {
+ loader.setCacheEnabled(false);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ server.setMockResponseData(RESPONSE_STRING);
+ assertThat(loader.loadString("/foo")).isEqualTo(RESPONSE_STRING);
+ }
+
+ @Test
+ public void testCacheDisabled() {
+ loader.setCacheEnabled(false);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ makeRequests();
+ assertThat(server.getNumberRequests()).isEqualTo(3);
+ }
+
+ @Test
+ public void testCacheEnabled() {
+ loader.setCacheEnabled(true);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ makeRequests();
+ assertThat(server.getNumberRequests()).isEqualTo(1);
+ }
+
+ @Test
+ public void testServerStrategy() {
+ loader.setCacheEnabled(true);
+ loader.setStrategy(LoadStrategy.SERVER_FIRST);
+ makeRequests();
+ assertThat(server.getNumberRequests()).isEqualTo(3);
+ }
+
+ @Test
+ public void testCacheStrategyDisabled() {
+ loader.setCacheEnabled(false);
+ loader.setStrategy(LoadStrategy.CACHE_FIRST);
+ makeRequests();
+ assertThat(server.getNumberRequests()).isEqualTo(3);
+ }
+
+ private void makeRequests() {
+ server.setMockResponseData(RESPONSE_STRING);
+ assertThat(loader.loadString("/foo")).isEqualTo(RESPONSE_STRING);
+ assertThat(loader.loadString("/foo")).isEqualTo(RESPONSE_STRING);
+ assertThat(loader.loadString("/foo")).isEqualTo(RESPONSE_STRING);
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java
index 07279e5396b..af5a763c26d 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/cpd/index/IndexFactoryTest.java
@@ -19,14 +19,14 @@
*/
package org.sonar.batch.cpd.index;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -38,13 +38,13 @@ public class IndexFactoryTest {
Settings settings;
IndexFactory factory;
Logger logger;
- private DefaultAnalysisMode analysisMode;
+ private ProjectAnalysisMode analysisMode;
@Before
public void setUp() {
project = new Project("foo");
settings = new Settings();
- analysisMode = mock(DefaultAnalysisMode.class);
+ analysisMode = mock(ProjectAnalysisMode.class);
factory = new IndexFactory(analysisMode, settings);
logger = mock(Logger.class);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
index 28d9b251ec9..991e61dc463 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
@@ -19,12 +19,13 @@
*/
package org.sonar.batch.issue.tracking;
+import org.sonar.batch.bootstrap.WSLoader;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.HttpDownloader;
-import org.sonar.batch.bootstrap.ServerClient;
import java.net.URI;
import java.net.URISyntaxException;
@@ -46,32 +47,32 @@ public class DefaultServerLineHashesLoaderTest {
@Test
public void should_download_source_from_ws_if_preview_mode() {
- ServerClient server = mock(ServerClient.class);
- when(server.request(anyString())).thenReturn("ae12\n\n43fb");
+ WSLoader wsLoader = mock(WSLoader.class);
+ when(wsLoader.loadString(anyString())).thenReturn("ae12\n\n43fb");
- ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
+ ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(wsLoader);
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Bar.c");
assertThat(hashes).containsOnly("ae12", "", "43fb");
- verify(server).request("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c");
+ verify(wsLoader).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c");
}
@Test
public void should_download_source_with_space_from_ws_if_preview_mode() {
- ServerClient server = mock(ServerClient.class);
- when(server.request(anyString())).thenReturn("ae12\n\n43fb");
+ WSLoader server = mock(WSLoader.class);
+ when(server.loadString(anyString())).thenReturn("ae12\n\n43fb");
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Foo Bar.c");
assertThat(hashes).containsOnly("ae12", "", "43fb");
- verify(server).request("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c");
+ verify(server).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c");
}
@Test
public void should_fail_to_download_source_from_ws() throws URISyntaxException {
- ServerClient server = mock(ServerClient.class);
- when(server.request(anyString())).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
+ WSLoader server = mock(WSLoader.class);
+ when(server.loadString(anyString())).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java
index ea301e425b0..df097d68457 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java
@@ -19,6 +19,8 @@
*/
package org.sonar.batch.report;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
@@ -27,23 +29,21 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.TempFolder;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.scan.ImmutableProjectReactor;
-
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ReportPublisherTest {
- private DefaultAnalysisMode mode;
+ private ProjectAnalysisMode mode;
private ImmutableProjectReactor reactor;
@Before
public void setUp() {
- mode = mock(DefaultAnalysisMode.class);
+ mode = mock(ProjectAnalysisMode.class);
reactor = mock(ImmutableProjectReactor.class);
when(reactor.getRoot()).thenReturn(ProjectDefinition.create().setKey("struts"));
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
index 9458bc31c35..c9cadbe05ee 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
@@ -19,16 +19,16 @@
*/
package org.sonar.batch.repository;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
+import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.batch.bootstrap.AnalysisProperties;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.rule.ModuleQProfiles;
-
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -38,18 +38,18 @@ import static org.mockito.Mockito.when;
public class DefaultProjectRepositoriesLoaderTest {
private DefaultProjectRepositoriesLoader loader;
- private ServerClient serverClient;
- private DefaultAnalysisMode analysisMode;
+ private WSLoader wsLoader;
+ private ProjectAnalysisMode analysisMode;
private ProjectReactor reactor;
private AnalysisProperties taskProperties;
@Before
public void prepare() {
- serverClient = mock(ServerClient.class);
- analysisMode = mock(DefaultAnalysisMode.class);
- loader = new DefaultProjectRepositoriesLoader(serverClient, analysisMode);
+ wsLoader = mock(WSLoader.class);
+ analysisMode = mock(ProjectAnalysisMode.class);
+ loader = new DefaultProjectRepositoriesLoader(wsLoader, analysisMode);
loader = spy(loader);
- when(serverClient.request(anyString())).thenReturn("{}");
+ when(wsLoader.loadString(anyString())).thenReturn("{}");
taskProperties = new AnalysisProperties(Maps.<String, String>newHashMap(), "");
}
@@ -58,18 +58,18 @@ public class DefaultProjectRepositoriesLoaderTest {
reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
when(analysisMode.isPreview()).thenReturn(false);
loader.load(reactor, taskProperties);
- verify(serverClient).request("/batch/project?key=foo&preview=false");
+ verify(wsLoader).loadString("/batch/project?key=foo&preview=false");
when(analysisMode.isPreview()).thenReturn(true);
loader.load(reactor, taskProperties);
- verify(serverClient).request("/batch/project?key=foo&preview=true");
+ verify(wsLoader).loadString("/batch/project?key=foo&preview=true");
}
@Test
public void passAndEncodeProjectKeyParameter() {
reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo bàr"));
loader.load(reactor, taskProperties);
- verify(serverClient).request("/batch/project?key=foo+b%C3%A0r&preview=false");
+ verify(wsLoader).loadString("/batch/project?key=foo+b%C3%A0r&preview=false");
}
@Test
@@ -77,7 +77,7 @@ public class DefaultProjectRepositoriesLoaderTest {
reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
taskProperties.properties().put(ModuleQProfiles.SONAR_PROFILE_PROP, "my-profile#2");
loader.load(reactor, taskProperties);
- verify(serverClient).request("/batch/project?key=foo&profile=my-profile%232&preview=false");
+ verify(wsLoader).loadString("/batch/project?key=foo&profile=my-profile%232&preview=false");
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java
index 4cc756ff1ce..d1686d63372 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultServerIssuesLoaderTest.java
@@ -19,17 +19,17 @@
*/
package org.sonar.batch.repository;
+import com.google.common.io.ByteSource;
+
+import org.sonar.batch.bootstrap.WSLoader;
import com.google.common.base.Function;
-import com.google.common.io.InputSupplier;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.input.BatchInput;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -39,18 +39,18 @@ import static org.mockito.Mockito.when;
public class DefaultServerIssuesLoaderTest {
private DefaultServerIssuesLoader loader;
- private ServerClient serverClient;
+ private WSLoader wsLoader;
@Before
public void prepare() {
- serverClient = mock(ServerClient.class);
- loader = new DefaultServerIssuesLoader(serverClient);
+ wsLoader = mock(WSLoader.class);
+ loader = new DefaultServerIssuesLoader(wsLoader);
}
@Test
public void loadFromWs() throws Exception {
- InputSupplier<InputStream> is = mock(InputSupplier.class);
- when(serverClient.doRequest("/batch/issues?key=foo", "GET", null)).thenReturn(is);
+ ByteSource bs = mock(ByteSource.class);
+ when(wsLoader.loadSource("/batch/issues?key=foo")).thenReturn(bs);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -59,7 +59,7 @@ public class DefaultServerIssuesLoaderTest {
ServerIssue.newBuilder().setKey("ab2").build()
.writeDelimitedTo(bos);
- when(is.getInput()).thenReturn(new ByteArrayInputStream(bos.toByteArray()));
+ when(bs.openStream()).thenReturn(new ByteArrayInputStream(bos.toByteArray()));
final List<ServerIssue> result = new ArrayList<>();
loader.load("foo", new Function<BatchInput.ServerIssue, Void>() {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java
index 54d62bce5f8..6910f2dc462 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/user/UserRepositoryTest.java
@@ -19,15 +19,15 @@
*/
package org.sonar.batch.repository.user;
-import com.google.common.io.InputSupplier;
+import com.google.common.io.ByteSource;
+
+import org.sonar.batch.bootstrap.WSLoader;
import org.junit.Test;
-import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.input.BatchInput;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,18 +39,17 @@ public class UserRepositoryTest {
@Test
public void testLoad() throws IOException {
- ServerClient serverClient = mock(ServerClient.class);
- UserRepository userRepo = new UserRepository(serverClient);
+ WSLoader wsLoader = mock(WSLoader.class);
+ UserRepository userRepo = new UserRepository(wsLoader);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BatchInput.User.Builder builder = BatchInput.User.newBuilder();
builder.setLogin("fmallet").setName("Freddy Mallet").build().writeDelimitedTo(out);
builder.setLogin("sbrandhof").setName("Simon").build().writeDelimitedTo(out);
- InputSupplier<InputStream> is = mock(InputSupplier.class);
- when(serverClient.doRequest("/batch/users?logins=fmallet,sbrandhof", "GET", null))
- .thenReturn(is);
- when(is.getInput()).thenReturn(new ByteArrayInputStream(out.toByteArray()));
+ ByteSource source = mock(ByteSource.class);
+ when(wsLoader.loadSource("/batch/users?logins=fmallet,sbrandhof")).thenReturn(source);
+ when(source.openStream()).thenReturn(new ByteArrayInputStream(out.toByteArray()));
assertThat(userRepo.loadFromWs(Arrays.asList("fmallet", "sbrandhof"))).extracting("login", "name").containsOnly(tuple("fmallet", "Freddy Mallet"), tuple("sbrandhof", "Simon"));
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultAnalysisModeTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultAnalysisModeTest.java
index 65c7d548b9a..a2b20592b68 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultAnalysisModeTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultAnalysisModeTest.java
@@ -17,14 +17,15 @@
* 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.sonar.batch.bootstrap;
+package org.sonar.batch.scan;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
+import org.sonar.batch.bootstrap.AnalysisProperties;
+import org.sonar.batch.scan.ProjectAnalysisMode;
import org.junit.Test;
import org.sonar.api.CoreProperties;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,12 +34,12 @@ public class DefaultAnalysisModeTest {
@Test
public void regular_analysis_by_default() {
- DefaultAnalysisMode mode = new DefaultAnalysisMode(Collections.<String, String>emptyMap());
+ ProjectAnalysisMode mode = new ProjectAnalysisMode(new AnalysisProperties(Collections.<String, String>emptyMap()));
assertThat(mode.isPreview()).isFalse();
assertThat(mode.isIncremental()).isFalse();
- mode = new DefaultAnalysisMode(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, "pouet"));
+ mode = createMode(CoreProperties.ANALYSIS_MODE, "pouet");
assertThat(mode.isPreview()).isFalse();
assertThat(mode.isIncremental()).isFalse();
@@ -46,7 +47,7 @@ public class DefaultAnalysisModeTest {
@Test
public void support_analysis_mode() {
- DefaultAnalysisMode mode = new DefaultAnalysisMode(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ANALYSIS));
+ ProjectAnalysisMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ANALYSIS);
assertThat(mode.isPreview()).isFalse();
assertThat(mode.isIncremental()).isFalse();
@@ -54,31 +55,41 @@ public class DefaultAnalysisModeTest {
@Test
public void support_preview_mode() {
- Map<String, String> props = Maps.newHashMap(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW));
- DefaultAnalysisMode mode = new DefaultAnalysisMode(props);
+ ProjectAnalysisMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW);
assertThat(mode.isPreview()).isTrue();
assertThat(mode.isIncremental()).isFalse();
+ }
+
+ @Test
+ public void support_quick_mode() {
+ ProjectAnalysisMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_QUICK);
- assertThat(props.get(CoreProperties.DRY_RUN)).isEqualTo("true");
+ assertThat(mode.isPreview()).isTrue();
+ assertThat(mode.isIncremental()).isFalse();
+ assertThat(mode.isQuick()).isTrue();
}
@Test
public void support_incremental_mode() {
- Map<String, String> props = Maps.newHashMap(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_INCREMENTAL));
- DefaultAnalysisMode mode = new DefaultAnalysisMode(props);
+ ProjectAnalysisMode mode = createMode(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_INCREMENTAL);
assertThat(mode.isPreview()).isTrue();
assertThat(mode.isIncremental()).isTrue();
-
- assertThat(props.get(CoreProperties.DRY_RUN)).isEqualTo("true");
}
@Test
public void support_deprecated_dryrun_property() {
- DefaultAnalysisMode mode = new DefaultAnalysisMode(Maps.newHashMap(ImmutableMap.of(CoreProperties.DRY_RUN, "true")));
+ ProjectAnalysisMode mode = createMode(CoreProperties.DRY_RUN, "true");
assertThat(mode.isPreview()).isTrue();
assertThat(mode.isIncremental()).isFalse();
}
+
+ private ProjectAnalysisMode createMode(String key, String value) {
+ Map<String, String> map = new HashMap<>();
+ map.put(key, value);
+
+ return new ProjectAnalysisMode(new AnalysisProperties(map));
+ }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
index abf12abc034..4edec303f85 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
@@ -27,7 +27,6 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.MessageException;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.GlobalSettings;
import org.sonar.batch.protocol.input.ProjectRepositories;
@@ -43,12 +42,12 @@ public class ModuleSettingsTest {
public ExpectedException thrown = ExpectedException.none();
ProjectRepositories projectRef;
- private DefaultAnalysisMode mode;
+ private ProjectAnalysisMode mode;
@Before
public void before() {
projectRef = new ProjectRepositories();
- mode = mock(DefaultAnalysisMode.class);
+ mode = mock(ProjectAnalysisMode.class);
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
index 0970ede0908..5b4e60f4bc0 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
@@ -19,8 +19,12 @@
*/
package org.sonar.batch.scan;
+import org.sonar.batch.bootstrap.GlobalMode;
+
import com.google.common.collect.ImmutableMap;
+
import java.util.Collections;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -33,11 +37,9 @@ import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.batch.bootstrap.BootstrapProperties;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.GlobalSettings;
import org.sonar.batch.protocol.input.GlobalRepositories;
import org.sonar.batch.protocol.input.ProjectRepositories;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -53,13 +55,15 @@ public class ProjectSettingsTest {
ProjectDefinition project = ProjectDefinition.create().setKey("struts");
GlobalSettings bootstrapProps;
- private DefaultAnalysisMode mode;
+ private GlobalMode globalMode;
+ private ProjectAnalysisMode mode;
@Before
public void prepare() {
projectRef = new ProjectRepositories();
- mode = mock(DefaultAnalysisMode.class);
- bootstrapProps = new GlobalSettings(new BootstrapProperties(Collections.<String, String>emptyMap()), new PropertyDefinitions(), new GlobalRepositories(), mode);
+ globalMode = mock(GlobalMode.class);
+ mode = mock(ProjectAnalysisMode.class);
+ bootstrapProps = new GlobalSettings(new BootstrapProperties(Collections.<String, String>emptyMap()), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
}
@Test
@@ -118,7 +122,7 @@ public class ProjectSettingsTest {
@Test
public void should_log_a_warning_when_a_dropper_property_is_present() {
- GlobalSettings settings = new GlobalSettings(new BootstrapProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(), mode);
+ GlobalSettings settings = new GlobalSettings(new BootstrapProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
new ProjectSettings(new ProjectReactor(project), settings, new PropertyDefinitions(), projectRef, mode);
assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly("Property 'sonar.qualitygate' is not supported any more. It will be ignored.");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/WSLoaderProjectProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/WSLoaderProjectProviderTest.java
new file mode 100644
index 00000000000..f3a4aa62216
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/WSLoaderProjectProviderTest.java
@@ -0,0 +1,81 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.batch.scan;
+
+import org.sonar.api.batch.AnalysisMode;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.batch.bootstrap.AnalysisProperties;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.bootstrap.WSLoader;
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+import org.sonar.home.cache.PersistentCache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Mockito.when;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class WSLoaderProjectProviderTest {
+ @Mock
+ private PersistentCache cache;
+
+ @Mock
+ private ServerClient client;
+
+ @Mock
+ private AnalysisMode mode;
+
+ private WSLoaderProjectProvider loaderProvider;
+ private Map<String, String> propMap;
+ private AnalysisProperties props;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ loaderProvider = new WSLoaderProjectProvider();
+ propMap = new HashMap<>();
+ }
+
+ @Test
+ public void testDefault() {
+ props = new AnalysisProperties(propMap, null);
+
+ WSLoader loader = loaderProvider.provide(props, mode, cache, client);
+ assertThat(loader.getStrategy()).isEqualTo(LoadStrategy.SERVER_FIRST);
+ assertThat(loader.isCacheEnabled()).isEqualTo(false);
+ }
+
+ @Test
+ public void testSingleMode() {
+ when(mode.isQuick()).thenReturn(true);
+ when(mode.isPreview()).thenReturn(true);
+ propMap.put("sonar.enableOffline", "true");
+ props = new AnalysisProperties(propMap, null);
+
+ WSLoader loader = loaderProvider.provide(props, mode, cache, client);
+ assertThat(loader.getStrategy()).isEqualTo(LoadStrategy.CACHE_FIRST);
+ assertThat(loader.isCacheEnabled()).isEqualTo(true);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
index 60f85a52e17..2f5141d676e 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
@@ -19,14 +19,14 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -37,7 +37,7 @@ public class InputFileBuilderFactoryTest {
LanguageDetectionFactory langDetectionFactory = mock(LanguageDetectionFactory.class, Mockito.RETURNS_MOCKS);
StatusDetectionFactory statusDetectionFactory = mock(StatusDetectionFactory.class, Mockito.RETURNS_MOCKS);
DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class);
- DefaultAnalysisMode analysisMode = mock(DefaultAnalysisMode.class);
+ ProjectAnalysisMode analysisMode = mock(ProjectAnalysisMode.class);
InputFileBuilderFactory factory = new InputFileBuilderFactory(ProjectDefinition.create().setKey("struts"), pathResolver, langDetectionFactory,
statusDetectionFactory, analysisMode, new Settings(), new FileMetadata());
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
index ff304db2e22..5b14b2bc9be 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
@@ -19,6 +19,8 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.scan.ProjectAnalysisMode;
+
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
@@ -29,7 +31,6 @@ import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.PathUtils;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import java.io.File;
import java.nio.charset.StandardCharsets;
@@ -47,7 +48,7 @@ public class InputFileBuilderTest {
LanguageDetection langDetection = mock(LanguageDetection.class);
StatusDetection statusDetection = mock(StatusDetection.class);
DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class);
- DefaultAnalysisMode analysisMode = mock(DefaultAnalysisMode.class);
+ ProjectAnalysisMode analysisMode = mock(ProjectAnalysisMode.class);
@Test
public void complete_input_file() throws Exception {
diff --git a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java b/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
index a1bcbee4601..b8b74d6afab 100644
--- a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
+++ b/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
@@ -19,6 +19,7 @@
*/
package org.sonar.core.util;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
@@ -28,6 +29,7 @@ import com.google.common.io.ByteStreams;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -42,7 +44,9 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
+
import javax.annotation.Nullable;
+
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
@@ -60,13 +64,19 @@ import org.sonar.api.utils.log.Loggers;
public class DefaultHttpDownloader extends HttpDownloader {
private final BaseHttpDownloader downloader;
private final Integer readTimeout;
+ private final Integer connectTimeout;
public DefaultHttpDownloader(Server server, Settings settings) {
this(server, settings, null);
}
public DefaultHttpDownloader(Server server, Settings settings, @Nullable Integer readTimeout) {
+ this(server, settings, null, readTimeout);
+ }
+
+ public DefaultHttpDownloader(Server server, Settings settings, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
this.readTimeout = readTimeout;
+ this.connectTimeout = connectTimeout;
downloader = new BaseHttpDownloader(settings.getProperties(), server.getVersion());
}
@@ -75,7 +85,12 @@ public class DefaultHttpDownloader extends HttpDownloader {
}
public DefaultHttpDownloader(Settings settings, @Nullable Integer readTimeout) {
+ this(settings, null, readTimeout);
+ }
+
+ public DefaultHttpDownloader(Settings settings, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
this.readTimeout = readTimeout;
+ this.connectTimeout = connectTimeout;
downloader = new BaseHttpDownloader(settings.getProperties(), null);
}
@@ -97,7 +112,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
@Override
protected String readString(URI uri, Charset charset) {
try {
- return CharStreams.toString(CharStreams.newReaderSupplier(downloader.newInputSupplier(uri, this.readTimeout), charset));
+ return CharStreams.toString(CharStreams.newReaderSupplier(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout), charset));
} catch (IOException e) {
throw failToDownload(uri, e);
}
@@ -111,7 +126,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
@Override
public byte[] download(URI uri) {
try {
- return ByteStreams.toByteArray(downloader.newInputSupplier(uri, this.readTimeout));
+ return ByteStreams.toByteArray(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout));
} catch (IOException e) {
throw failToDownload(uri, e);
}
@@ -124,7 +139,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
@Override
public InputStream openStream(URI uri) {
try {
- return downloader.newInputSupplier(uri, this.readTimeout).getInput();
+ return downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout).getInput();
} catch (IOException e) {
throw failToDownload(uri, e);
}
@@ -133,7 +148,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
@Override
public void download(URI uri, File toFile) {
try {
- Files.copy(downloader.newInputSupplier(uri, this.readTimeout), toFile);
+ Files.copy(downloader.newInputSupplier(uri, this.connectTimeout, this.readTimeout), toFile);
} catch (IOException e) {
FileUtils.deleteQuietly(toFile);
throw failToDownload(uri, e);
@@ -213,18 +228,29 @@ public class DefaultHttpDownloader extends HttpDownloader {
}
public InputSupplier<InputStream> newInputSupplier(URI uri) {
- return new HttpInputSupplier(uri, GET, userAgent, null, null, TIMEOUT_MILLISECONDS);
+ return newInputSupplier(uri, GET, null, null, null, null);
}
public InputSupplier<InputStream> newInputSupplier(URI uri, @Nullable Integer readTimeoutMillis) {
return newInputSupplier(uri, GET, readTimeoutMillis);
}
+ /**
+ * @since 5.2
+ */
+ public InputSupplier<InputStream> newInputSupplier(URI uri, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
+ return newInputSupplier(uri, GET, connectTimeoutMillis, readTimeoutMillis);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public InputSupplier<InputStream> newInputSupplier(URI uri, String requestMethod, @Nullable Integer connectTimeoutMillis, @Nullable Integer readTimeoutMillis) {
+ return newInputSupplier(uri, requestMethod, null, null, connectTimeoutMillis, readTimeoutMillis);
+ }
+
public InputSupplier<InputStream> newInputSupplier(URI uri, String requestMethod, @Nullable Integer readTimeoutMillis) {
- if (readTimeoutMillis != null) {
- return new HttpInputSupplier(uri, requestMethod, userAgent, null, null, readTimeoutMillis);
- }
- return new HttpInputSupplier(uri, requestMethod, userAgent, null, null, TIMEOUT_MILLISECONDS);
+ return newInputSupplier(uri, requestMethod, null, null, null, readTimeoutMillis);
}
public InputSupplier<InputStream> newInputSupplier(URI uri, String login, String password) {
@@ -235,7 +261,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
* @since 5.0
*/
public InputSupplier<InputStream> newInputSupplier(URI uri, String requestMethod, String login, String password) {
- return new HttpInputSupplier(uri, requestMethod, userAgent, login, password, TIMEOUT_MILLISECONDS);
+ return newInputSupplier(uri, requestMethod, login, password, null, null);
}
public InputSupplier<InputStream> newInputSupplier(URI uri, String login, String password, @Nullable Integer readTimeoutMillis) {
@@ -246,10 +272,17 @@ public class DefaultHttpDownloader extends HttpDownloader {
* @since 5.0
*/
public InputSupplier<InputStream> newInputSupplier(URI uri, String requestMethod, String login, String password, @Nullable Integer readTimeoutMillis) {
- if (readTimeoutMillis != null) {
- return new HttpInputSupplier(uri, requestMethod, userAgent, login, password, readTimeoutMillis);
- }
- return new HttpInputSupplier(uri, requestMethod, userAgent, login, password, TIMEOUT_MILLISECONDS);
+ return newInputSupplier(uri, requestMethod, login, password, null, readTimeoutMillis);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public InputSupplier<InputStream> newInputSupplier(URI uri, String requestMethod, String login, String password, @Nullable Integer connectTimeoutMillis,
+ @Nullable Integer readTimeoutMillis) {
+ int read = readTimeoutMillis != null ? readTimeoutMillis : TIMEOUT_MILLISECONDS;
+ int connect = connectTimeoutMillis != null ? connectTimeoutMillis : TIMEOUT_MILLISECONDS;
+ return new HttpInputSupplier(uri, requestMethod, userAgent, login, password, connect, read);
}
private static class HttpInputSupplier implements InputSupplier<InputStream> {
@@ -257,22 +290,27 @@ public class DefaultHttpDownloader extends HttpDownloader {
private final String password;
private final URI uri;
private final String userAgent;
+ private final int connectTimeoutMillis;
private final int readTimeoutMillis;
private final String requestMethod;
- HttpInputSupplier(URI uri, String requestMethod, String userAgent, String login, String password, int readTimeoutMillis) {
+ HttpInputSupplier(URI uri, String requestMethod, String userAgent, String login, String password, int connectTimeoutMillis, int readTimeoutMillis) {
this.uri = uri;
this.requestMethod = requestMethod;
this.userAgent = userAgent;
this.login = login;
this.password = password;
this.readTimeoutMillis = readTimeoutMillis;
+ this.connectTimeoutMillis = connectTimeoutMillis;
}
+ /**
+ * @throws IOException any I/O error, not limited to the network connection
+ * @throws HttpException if HTTP response code > 400
+ */
@Override
public InputStream getInput() throws IOException {
Loggers.get(getClass()).debug("Download: " + uri + " (" + getProxySynthesis(uri, ProxySelector.getDefault()) + ")");
-
HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
connection.setRequestMethod(requestMethod);
HttpsTrust.INSTANCE.trust(connection);
@@ -283,7 +321,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
String encoded = Base64.encodeBase64String((login + ":" + password).getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization", "Basic " + encoded);
}
- connection.setConnectTimeout(TIMEOUT_MILLISECONDS);
+ connection.setConnectTimeout(connectTimeoutMillis);
connection.setReadTimeout(readTimeoutMillis);
connection.setUseCaches(true);
connection.setInstanceFollowRedirects(true);
diff --git a/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java b/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java
index 8ca54546371..f19f42c5345 100644
--- a/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java
@@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Properties;
import java.util.zip.GZIPOutputStream;
+
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.AfterClass;
@@ -51,7 +52,6 @@ import org.simpleframework.transport.connect.SocketConnection;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.SonarException;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
@@ -123,6 +123,25 @@ public class DefaultHttpDownloaderTest {
}
}
+ @Test(timeout = 10000)
+ public void readStringConnectTimeout() throws IOException, URISyntaxException {
+ // non routable address
+ String url = "http://10.255.255.1";
+
+ thrown.expect(new BaseMatcher<Exception>() {
+ @Override
+ public boolean matches(Object ex) {
+ return ex instanceof SonarException && ((SonarException) ex).getCause() instanceof SocketTimeoutException;
+ }
+
+ @Override
+ public void describeTo(Description arg0) {
+ }
+ });
+ DefaultHttpDownloader downloader = new DefaultHttpDownloader(new Settings(), 10, 50000);
+ downloader.openStream(new URI(url));
+ }
+
@Test
public void downloadBytes() throws URISyntaxException {
byte[] bytes = new DefaultHttpDownloader(new Settings()).readBytes(new URI(baseUrl));
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
index 95b93e6ed27..e4c8bd02912 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
@@ -32,7 +32,6 @@ import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.concurrent.Callable;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -51,25 +50,18 @@ public class PersistentCache {
// eviction strategy is to expire entries after modification once a time duration has elapsed
private final long defaultDurationToExpireMs;
- private boolean forceUpdate;
private final Logger logger;
- public PersistentCache(Path baseDir, long defaultDurationToExpireMs, boolean forceUpdate, Logger logger) {
+ public PersistentCache(Path baseDir, long defaultDurationToExpireMs, Logger logger) {
this.baseDir = baseDir;
this.defaultDurationToExpireMs = defaultDurationToExpireMs;
this.logger = logger;
- reconfigure(forceUpdate);
+ reconfigure();
logger.debug("cache: " + baseDir + ", default expiration time (ms): " + defaultDurationToExpireMs);
}
- public void reconfigure(boolean forceUpdate) {
- this.forceUpdate = forceUpdate;
-
- if (forceUpdate) {
- logger.debug("cache: forcing update");
- }
-
+ public void reconfigure() {
try {
Files.createDirectories(baseDir);
} catch (IOException e) {
@@ -81,16 +73,12 @@ public class PersistentCache {
return baseDir;
}
- public boolean isForceUpdate() {
- return forceUpdate;
- }
-
@CheckForNull
- public synchronized String getString(@Nonnull String obj, @Nullable final Callable<String> valueLoader) throws Exception {
- byte[] cached = get(obj, new Callable<byte[]>() {
+ public synchronized String getString(@Nonnull String obj, @Nullable final PersistentCacheLoader<String> valueLoader) throws IOException {
+ byte[] cached = get(obj, new PersistentCacheLoader<byte[]>() {
@Override
- public byte[] call() throws Exception {
- String s = valueLoader.call();
+ public byte[] get() throws IOException {
+ String s = valueLoader.get();
if (s != null) {
return s.getBytes(ENCODING);
}
@@ -106,26 +94,23 @@ public class PersistentCache {
}
@CheckForNull
- public synchronized byte[] get(@Nonnull String obj, @Nullable Callable<byte[]> valueLoader) throws Exception {
+ public synchronized byte[] get(@Nonnull String obj, @Nullable PersistentCacheLoader<byte[]> valueLoader) throws IOException {
String key = getKey(obj);
try {
lock();
- if (!forceUpdate) {
- byte[] cached = getCache(key);
- if (cached != null) {
- logger.debug("cache hit for " + obj + " -> " + key);
- return cached;
- }
+ byte[] cached = getCache(key);
- logger.debug("cache miss for " + obj + " -> " + key);
- } else {
- logger.debug("cache force update for " + obj + " -> " + key);
+ if (cached != null) {
+ logger.debug("cache hit for " + obj + " -> " + key);
+ return cached;
}
+ logger.debug("cache miss for " + obj + " -> " + key);
+
if (valueLoader != null) {
- byte[] value = valueLoader.call();
+ byte[] value = valueLoader.get();
if (value != null) {
putCache(key, value);
}
@@ -138,6 +123,16 @@ public class PersistentCache {
return null;
}
+ public synchronized void put(@Nonnull String obj, @Nonnull byte[] value) throws IOException {
+ String key = getKey(obj);
+ try {
+ lock();
+ putCache(key, value);
+ } finally {
+ unlock();
+ }
+ }
+
/**
* Deletes all cache entries
*/
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheBuilder.java b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheBuilder.java
index e115f1cab64..f0fa1596917 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheBuilder.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheBuilder.java
@@ -28,7 +28,6 @@ public class PersistentCacheBuilder {
private static final long DEFAULT_EXPIRE_DURATION = TimeUnit.MILLISECONDS.convert(1L, TimeUnit.DAYS);
private static final String DIR_NAME = "ws_cache";
- private boolean forceUpdate = false;
private Path cachePath;
private final Logger logger;
@@ -41,7 +40,7 @@ public class PersistentCacheBuilder {
setSonarHome(findHome());
}
- return new PersistentCache(cachePath, DEFAULT_EXPIRE_DURATION, forceUpdate, logger);
+ return new PersistentCache(cachePath, DEFAULT_EXPIRE_DURATION, logger);
}
public PersistentCacheBuilder setSonarHome(@Nullable Path p) {
@@ -51,11 +50,6 @@ public class PersistentCacheBuilder {
return this;
}
- public PersistentCacheBuilder forceUpdate(boolean update) {
- this.forceUpdate = update;
- return this;
- }
-
private static Path findHome() {
String home = System.getenv("SONAR_USER_HOME");
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheLoader.java b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheLoader.java
new file mode 100644
index 00000000000..ee906b4b67d
--- /dev/null
+++ b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCacheLoader.java
@@ -0,0 +1,26 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.sonar.home.cache;
+
+import java.io.IOException;
+
+public interface PersistentCacheLoader<T> {
+ T get() throws IOException;
+}
diff --git a/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java b/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
index 09335dffc3b..62e105bf861 100644
--- a/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
+++ b/sonar-home/src/test/java/org/sonar/home/cache/PersistentCacheTest.java
@@ -20,7 +20,6 @@
package org.sonar.home.cache;
import java.io.File;
-import java.util.concurrent.Callable;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
@@ -42,7 +41,7 @@ public class PersistentCacheTest {
@Before
public void setUp() {
- cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, false, mock(Logger.class));
+ cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, mock(Logger.class));
}
@Test
@@ -59,9 +58,9 @@ public class PersistentCacheTest {
@Test
public void testNullValue() throws Exception {
// mocks have their methods returning null by default
- Callable<byte[]> c = mock(Callable.class);
+ PersistentCacheLoader<byte[]> c = mock(PersistentCacheLoader.class);
assertThat(cache.get(URI, c)).isNull();
- verify(c).call();
+ verify(c).get();
assertCacheHit(false);
}
@@ -79,29 +78,16 @@ public class PersistentCacheTest {
}
@Test
- public void testForceUpdate() throws Exception {
- cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, true, mock(Logger.class));
-
- assertCacheHit(false);
- assertCacheHit(false);
- assertCacheHit(false);
-
- // with forceUpdate, it should still have cached the last call
- cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, false, mock(Logger.class));
- assertCacheHit(true);
- }
-
- @Test
public void testReconfigure() throws Exception {
- cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, true, mock(Logger.class));
- assertCacheHit(false);
+ cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, mock(Logger.class));
assertCacheHit(false);
+ assertCacheHit(true);
File root = tmp.getRoot();
FileUtils.deleteQuietly(root);
// should re-create cache directory and start using the cache
- cache.reconfigure(false);
+ cache.reconfigure();
assertThat(root).exists();
assertCacheHit(false);
@@ -111,7 +97,7 @@ public class PersistentCacheTest {
@Test
public void testExpiration() throws Exception {
// negative time to make sure it is expired on the second call
- cache = new PersistentCache(tmp.getRoot().toPath(), -100, false, mock(Logger.class));
+ cache = new PersistentCache(tmp.getRoot().toPath(), -100, mock(Logger.class));
assertCacheHit(false);
assertCacheHit(false);
}
@@ -122,11 +108,11 @@ public class PersistentCacheTest {
assertThat(c.wasCalled).isEqualTo(!hit);
}
- private class CacheFillerString implements Callable<String> {
+ private class CacheFillerString implements PersistentCacheLoader<String> {
public boolean wasCalled = false;
@Override
- public String call() throws Exception {
+ public String get() {
wasCalled = true;
return VALUE;
}
@@ -139,8 +125,8 @@ public class PersistentCacheTest {
*/
@Test(expected = ArithmeticException.class)
public void testExceptions() throws Exception {
- Callable<byte[]> c = mock(Callable.class);
- when(c.call()).thenThrow(ArithmeticException.class);
+ PersistentCacheLoader<byte[]> c = mock(PersistentCacheLoader.class);
+ when(c.get()).thenThrow(ArithmeticException.class);
cache.get(URI, c);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
index 13c47e7ce0d..247b9097e5e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
@@ -446,6 +446,11 @@ public interface CoreProperties {
* @since 4.0
*/
String ANALYSIS_MODE_PREVIEW = "preview";
+
+ /**
+ * @since 5.2
+ */
+ String ANALYSIS_MODE_QUICK = "quick";
/**
* @since 4.0
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/AnalysisMode.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/AnalysisMode.java
index 2fad14d30c3..37734df0917 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/AnalysisMode.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/AnalysisMode.java
@@ -29,5 +29,7 @@ public interface AnalysisMode {
boolean isPreview();
boolean isIncremental();
+
+ boolean isQuick();
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
index 9d574bb86bd..8bec2b65ea4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
@@ -230,6 +230,7 @@ public class SensorContextTester implements SensorContext {
public static class MockAnalysisMode implements AnalysisMode {
private boolean isIncremental = false;
private boolean isPreview = false;
+ private boolean isSingle = false;
@Override
public boolean isIncremental() {
@@ -248,6 +249,15 @@ public class SensorContextTester implements SensorContext {
public void setPreview(boolean value) {
this.isPreview = value;
}
+
+ @Override
+ public boolean isQuick() {
+ return this.isSingle;
+ }
+
+ public void setSingle(boolean single) {
+ this.isSingle = single;
+ }
}
private static class InMemorySensorStorage implements SensorStorage {