aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2013-02-19 00:04:01 +0100
committerSimon Brandhof <simon.brandhof@gmail.com>2013-02-19 00:09:44 +0100
commit91cfedbfd44100916f813231c72d0b4202bef4ef (patch)
tree9535836350d4427e2b5439cc083767420f1ecd1c /sonar-batch/src
parent16fcb63b9884486db7b97f0aa0e9d0d00cb29266 (diff)
downloadsonarqube-91cfedbfd44100916f813231c72d0b4202bef4ef.tar.gz
sonarqube-91cfedbfd44100916f813231c72d0b4202bef4ef.zip
SONAR-3317 download last analysis on dry run
Diffstat (limited to 'sonar-batch/src')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java106
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ScanContainer.java1
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java126
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/last_snapshot.xml11
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/no_last_snapshot.xml3
6 files changed, 261 insertions, 9 deletions
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 181f7703ab3..fda39f6c801 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
@@ -33,6 +33,7 @@ import org.sonar.api.utils.SonarException;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@@ -59,19 +60,23 @@ public class ServerClient implements BatchComponent {
InputSupplier<InputStream> inputSupplier = doRequest(pathStartingWithSlash);
Files.copy(inputSupplier, toFile);
} catch (HttpDownloader.HttpException he) {
- throw handleHttpException(he);
- } catch (Exception e) {
+ throw handleHttpException(pathStartingWithSlash, he);
+ } catch (IOException e) {
throw new SonarException(String.format("Unable to download '%s' to: %s", pathStartingWithSlash, toFile), e);
}
}
public String request(String pathStartingWithSlash) {
+ return request(pathStartingWithSlash, true);
+ }
+
+ public String request(String pathStartingWithSlash, boolean wrapHttpException) {
InputSupplier<InputStream> inputSupplier = doRequest(pathStartingWithSlash);
try {
return IOUtils.toString(inputSupplier.getInput(), "UTF-8");
- } catch (HttpDownloader.HttpException he) {
- throw handleHttpException(he);
- } catch (Exception e) {
+ } catch (HttpDownloader.HttpException e) {
+ throw (wrapHttpException ? handleHttpException(pathStartingWithSlash, e) : e);
+ } catch (IOException e) {
throw new SonarException(String.format("Unable to request: %s", pathStartingWithSlash), e);
}
}
@@ -96,14 +101,14 @@ public class ServerClient implements BatchComponent {
}
}
- private SonarException handleHttpException(HttpDownloader.HttpException he) {
+ private RuntimeException handleHttpException(String uri, HttpDownloader.HttpException he) {
if (he.getResponseCode() == 401) {
- throw new SonarException(String.format(getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
+ return new SonarException(String.format(getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
}
- throw new SonarException(String.format("Fail to execute request [code=%s, url=%s]", he.getResponseCode(), he.getUri()), he);
+ return new SonarException(String.format("Fail to execute request [code=%s, url=%s]", he.getResponseCode(), he.getUri()), he);
}
- private String getMessageWhenNotAuthorized(){
+ private String getMessageWhenNotAuthorized() {
String login = settings.getProperty(CoreProperties.LOGIN);
String password = settings.getProperty(CoreProperties.PASSWORD);
if (StringUtils.isEmpty(login) && StringUtils.isEmpty(password)) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java b/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java
new file mode 100644
index 00000000000..490ce77ffea
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/LastSnapshots.java
@@ -0,0 +1,106 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.scan;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.database.model.SnapshotSource;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.utils.HttpDownloader;
+import org.sonar.batch.bootstrap.ServerClient;
+
+import javax.annotation.CheckForNull;
+import javax.persistence.Query;
+
+import java.util.Collections;
+import java.util.List;
+
+public class LastSnapshots implements BatchComponent {
+
+ private final Settings settings;
+ private final DatabaseSession session;
+ private final ServerClient server;
+
+ public LastSnapshots(Settings settings, DatabaseSession session, ServerClient server) {
+ this.settings = settings;
+ this.session = session;
+ this.server = server;
+ }
+
+ /**
+ * Return null if this is the first scan (no last scan).
+ */
+ @CheckForNull
+ public List<RuleFailureModel> getViolations(Resource resource) {
+ Snapshot snapshot = getSnapshot(resource);
+ if (snapshot != null) {
+ return session.getResults(RuleFailureModel.class, "snapshotId", snapshot.getId());
+ }
+ return null;
+ }
+
+ public String getSource(Resource resource) {
+ String source = "";
+ if (ResourceUtils.isFile(resource)) {
+ if (settings.getBoolean(CoreProperties.DRY_RUN)) {
+ source = loadSourceFromWs(resource);
+ } else {
+ source = loadSourceFromDb(resource);
+ }
+ }
+ return source;
+ }
+
+ private String loadSourceFromWs(Resource resource) {
+ try {
+ return server.request("/api/sources?resource=" + resource.getEffectiveKey() + "&format=txt", false);
+ } catch (HttpDownloader.HttpException he) {
+ if (he.getResponseCode() == 404) {
+ return "";
+ }
+ throw he;
+ }
+ }
+
+ private String loadSourceFromDb(Resource resource) {
+ Snapshot snapshot = getSnapshot(resource);
+ if (snapshot != null) {
+ SnapshotSource source = session.getSingleResult(SnapshotSource.class, "snapshotId", snapshot.getId());
+ if (source != null) {
+ return source.getData();
+ }
+ }
+ return "";
+ }
+
+ private Snapshot getSnapshot(Resource resource) {
+ Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + " s where s.last=:last and s.resourceId=(select r.id from "
+ + ResourceModel.class.getSimpleName() + " r where r.key=:key)");
+ query.setParameter("key", resource.getEffectiveKey());
+ query.setParameter("last", Boolean.TRUE);
+ return session.getSingleResult(query, null);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanContainer.java
index dcb25cbdeaa..e898e87d53f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanContainer.java
@@ -94,6 +94,7 @@ public class ScanContainer extends Container {
}
container.addSingleton(Languages.class);
container.addSingleton(RulesDao.class);
+ container.addSingleton(LastSnapshots.class);
// file system
container.addSingleton(PathResolver.class);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java
new file mode 100644
index 00000000000..62e756b8c7d
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/LastSnapshotsTest.java
@@ -0,0 +1,126 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.scan;
+
+import org.junit.Test;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.model.RuleFailureModel;
+import org.sonar.api.resources.File;
+import org.sonar.api.utils.HttpDownloader;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class LastSnapshotsTest extends AbstractDbUnitTestCase {
+
+ @Test
+ public void should_return_null_violations_if_no_last_snapshot() {
+ setupData("no_last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+
+ LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server);
+
+ assertThat(lastSnapshots.getViolations(new File("org/foo", "Bar.c"))).isNull();
+ verifyZeroInteractions(server);
+ }
+
+ @Test
+ public void should_get_violations_of_last_snapshot() {
+ setupData("last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+
+ LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server);
+
+ List<RuleFailureModel> violations = lastSnapshots.getViolations(newFile());
+ assertThat(violations).hasSize(1);
+ assertThat(violations.get(0).getChecksum()).isEqualTo("ABCDE");
+ verifyZeroInteractions(server);
+ }
+
+ @Test
+ public void should_get_source_of_last_snapshot() {
+ setupData("last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+
+ LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server);
+
+ assertThat(lastSnapshots.getSource(newFile())).isEqualTo("this is bar");
+ verifyZeroInteractions(server);
+ }
+
+ @Test
+ public void should_return_empty_source_if_no_last_snapshot() {
+ setupData("no_last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+
+ LastSnapshots lastSnapshots = new LastSnapshots(new Settings(), getSession(), server);
+
+ assertThat(lastSnapshots.getSource(newFile())).isEqualTo("");
+ verifyZeroInteractions(server);
+ }
+
+ @Test
+ public void should_download_source_from_ws_if_dry_run() {
+ setupData("last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+ when(server.request(anyString(), eq(false))).thenReturn("downloaded source of Bar.c");
+
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.DRY_RUN, true);
+ LastSnapshots lastSnapshots = new LastSnapshots(settings, getSession(), server);
+
+ String source = lastSnapshots.getSource(newFile());
+ assertThat(source).isEqualTo("downloaded source of Bar.c");
+ verify(server).request("/api/sources?resource=myproject:org/foo/Bar.c&format=txt", false);
+ }
+
+ @Test
+ public void should_return_empty_source_if_dry_run_and_no_last_snapshot() throws URISyntaxException {
+ setupData("last_snapshot");
+ ServerClient server = mock(ServerClient.class);
+ when(server.request(anyString(), eq(false))).thenThrow(new HttpDownloader.HttpException(new URI(""), 404));
+
+ Settings settings = new Settings();
+ settings.setProperty(CoreProperties.DRY_RUN, true);
+ LastSnapshots lastSnapshots = new LastSnapshots(settings, getSession(), server);
+
+ String source = lastSnapshots.getSource(newFile());
+ assertThat(source).isEqualTo("");
+ verify(server).request("/api/sources?resource=myproject:org/foo/Bar.c&format=txt", false);
+ }
+
+ private File newFile() {
+ File file = new File("org/foo", "Bar.c");
+ file.setEffectiveKey("myproject:org/foo/Bar.c");
+ return file;
+ }
+}
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/last_snapshot.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/last_snapshot.xml
new file mode 100644
index 00000000000..6cc2ea5b8a5
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/last_snapshot.xml
@@ -0,0 +1,11 @@
+<dataset>
+ <projects id="100" kee="myproject:org/foo/Bar.c" enabled="[true]" scope="FIL" qualifier="FIL" language="c"/>
+ <snapshots id="1000" project_id="100" status="P" islast="[false]" purge_status="[null]"/>
+ <snapshots id="1100" project_id="100" status="P" islast="[true]" purge_status="[null]"/>
+ <snapshot_sources ID="10000" SNAPSHOT_ID="1100" DATA="this is bar"/>
+ <rule_failures ID="1000000" SNAPSHOT_ID="1100" RULE_ID="1"
+ switched_off="[null]" permanent_id="[null]" FAILURE_LEVEL="2"
+ MESSAGE="msg1" LINE="[null]" COST="[null]"
+ created_at="2008-12-02 13:58:00.00"
+ checksum="ABCDE" person_id="[null]"/>
+</dataset> \ No newline at end of file
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/no_last_snapshot.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/no_last_snapshot.xml
new file mode 100644
index 00000000000..84d67a04385
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/scan/LastSnapshotsTest/no_last_snapshot.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset> \ No newline at end of file