aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2014-12-05 16:26:39 +0100
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2014-12-05 17:06:08 +0100
commitf1b5ffc899b37f43b7c8f1503a747df978b3e2e4 (patch)
tree800ff16e8b063c04d4daf964a674abcfa5ec7f16 /server
parent2554b6c3be6fa31d60e5bffdc20d02629580312e (diff)
downloadsonarqube-f1b5ffc899b37f43b7c8f1503a747df978b3e2e4.tar.gz
sonarqube-f1b5ffc899b37f43b7c8f1503a747df978b3e2e4.zip
SONAR-5889 Implement api/sources/index on ES index
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/IndexAction.java95
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java5
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/source/ws/example-index.json17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java123
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java28
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/source/ws/IndexActionTest/index-result.json6
12 files changed, 273 insertions, 15 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 0abd8100276..b1f54a0cced 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -545,6 +545,7 @@ class ServerComponents {
pico.addSingleton(HashAction.class);
pico.addSingleton(ScmWriter.class);
pico.addSingleton(RawAction.class);
+ pico.addSingleton(IndexAction.class);
pico.addSingleton(ScmAction.class);
pico.addSingleton(SourceLineIndexDefinition.class);
pico.addSingleton(SourceLineIndex.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/IndexAction.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/IndexAction.java
new file mode 100644
index 00000000000..73373395eb9
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/ws/IndexAction.java
@@ -0,0 +1,95 @@
+/*
+ * 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.server.source.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.source.SourceService;
+import org.sonar.server.user.UserSession;
+
+import java.util.List;
+
+public class IndexAction implements RequestHandler {
+
+ private final DbClient dbClient;
+ private final SourceService sourceService;
+
+ public IndexAction(DbClient dbClient, SourceService sourceService) {
+ this.dbClient = dbClient;
+ this.sourceService = sourceService;
+ }
+
+ void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("index")
+ .setDescription("Get source code as line number / text pairs. Require See Source Code permission on file")
+ .setSince("5.0")
+ .setResponseExample(Resources.getResource(getClass(), "example-index.json"))
+ .setInternal(true)
+ .setHandler(this);
+
+ action
+ .createParam("resource")
+ .setRequired(true)
+ .setDescription("File key")
+ .setExampleValue("my_project:/src/foo/Bar.php");
+
+ action
+ .createParam("from")
+ .setRequired(true)
+ .setDefaultValue(1)
+ .setDescription("First line");
+
+ action
+ .createParam("to")
+ .setRequired(false)
+ .setDescription("Last line (excluded). If not specified, all lines are returned until end of file");
+ }
+
+ @Override
+ public void handle(Request request, Response response) {
+ String fileKey = request.mandatoryParam("resource");
+ UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
+ Integer from = request.mandatoryParamAsInt("from");
+ Integer to = request.paramAsInt("to");
+ DbSession session = dbClient.openSession(false);
+ try {
+ ComponentDto componentDto = dbClient.componentDao().getByKey(session, fileKey);
+ List<String> lines = sourceService.getLinesAsTxt(componentDto.uuid(), from, to == null ? null : to - 1);
+ JsonWriter json = response.newJsonWriter().beginArray().beginObject();
+ Integer lineCounter = from;
+ for (String line: lines) {
+ json.prop(lineCounter.toString(), line);
+ lineCounter ++;
+ }
+ json.endObject().endArray().close();;
+ } finally {
+ session.close();
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
index 75bc8580d19..259aef1ec66 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
@@ -29,13 +29,15 @@ public class SourcesWs implements WebService {
private final RawAction rawAction;
private final ScmAction scmAction;
private final HashAction hashAction;
+ private final IndexAction indexAction;
- public SourcesWs(ShowAction showAction, RawAction rawAction, ScmAction scmAction, LinesAction show2Action, HashAction hashAction) {
+ public SourcesWs(ShowAction showAction, RawAction rawAction, ScmAction scmAction, LinesAction show2Action, HashAction hashAction, IndexAction indexAction) {
this.showAction = showAction;
this.show2Action = show2Action;
this.rawAction = rawAction;
this.scmAction = scmAction;
this.hashAction = hashAction;
+ this.indexAction = indexAction;
}
@Override
@@ -48,6 +50,7 @@ public class SourcesWs implements WebService {
rawAction.define(controller);
scmAction.define(controller);
hashAction.define(controller);
+ indexAction.define(controller);
controller.done();
}
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/source/ws/example-index.json b/server/sonar-server/src/main/resources/org/sonar/server/source/ws/example-index.json
new file mode 100644
index 00000000000..89745d72612
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/source/ws/example-index.json
@@ -0,0 +1,17 @@
+[
+ {
+ "48": " void define(WebService.NewController controller) {",
+ "49": " WebService.NewAction action = controller.createAction(\"raw\")",
+ "50": " .setDescription(\"Get source code as plain text. Require Code viewer permission on file\")",
+ "51": " .setSince(\"5.0\")",
+ "52": " .setResponseExample(Resources.getResource(getClass(), \"example-raw.txt\"))",
+ "53": " .setHandler(this);",
+ "54": "",
+ "55": " action",
+ "56": " .createParam(\"key\")",
+ "57": " .setRequired(true)",
+ "58": " .setDescription(\"File key\")",
+ "59": " .setExampleValue(\"my_project:/src/foo/Bar.php\");",
+ "60": " }"
+ }
+] \ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
index 1fb3ed23cfd..5ed6696facb 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
@@ -66,7 +66,8 @@ public class HashActionTest {
mock(RawAction.class),
mock(ScmAction.class),
mock(LinesAction.class),
- new HashAction(dbClient, fileSourceDao)
+ new HashAction(dbClient, fileSourceDao),
+ mock(IndexAction.class)
)
);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java
new file mode 100644
index 00000000000..079666645dd
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.server.source.ws;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.source.SourceService;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.ws.WsTester;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class IndexActionTest {
+
+ @Mock
+ DbClient dbClient;
+
+ @Mock
+ DbSession session;
+
+ @Mock
+ ComponentDao componentDao;
+
+ @Mock
+ SourceService sourceService;
+
+ WsTester tester;
+
+ ComponentDto project = ComponentTesting.newProjectDto();
+ ComponentDto file = ComponentTesting.newFileDto(project);
+
+ @Before
+ public void setUp() throws Exception {
+ when(dbClient.componentDao()).thenReturn(componentDao);
+ when(dbClient.openSession(false)).thenReturn(session);
+ tester = new WsTester(new SourcesWs(mock(ShowAction.class), mock(RawAction.class), mock(ScmAction.class), mock(LinesAction.class),
+ mock(HashAction.class), new IndexAction(dbClient, sourceService)));
+ }
+
+ @Test
+ public void get_json() throws Exception {
+ String fileKey = "src/Foo.java";
+ MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "polop", fileKey);
+ when(componentDao.getByKey(session, fileKey)).thenReturn(file);
+
+ when(sourceService.getLinesAsTxt(file.uuid(), 1, null)).thenReturn(newArrayList(
+ "public class HelloWorld {",
+ "}"
+ ));
+
+ WsTester.TestRequest request = tester.newGetRequest("api/sources", "index").setParam("resource", fileKey);
+ request.execute().assertJson(this.getClass(), "index-result.json");
+ }
+
+ @Test
+ public void limit_range() throws Exception {
+ String fileKey = "src/Foo.java";
+ MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "polop", fileKey);
+ when(componentDao.getByKey(session, fileKey)).thenReturn(file);
+
+ when(sourceService.getLinesAsTxt(file.uuid(), 1, 2)).thenReturn(newArrayList(
+ "public class HelloWorld {",
+ "}"
+ ));
+
+ WsTester.TestRequest request = tester.newGetRequest("api/sources", "index")
+ .setParam("resource", fileKey).setParam("from", "1").setParam("to", "3");
+ request.execute().assertJson(this.getClass(), "index-result.json");
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void requires_code_viewer_permission() throws Exception {
+ MockUserSession.set();
+ tester.newGetRequest("api/sources", "index").setParam("resource", "any").execute();
+ }
+
+ @Test
+ public void close_db_session() throws Exception {
+ String fileKey = "src/Foo.java";
+ MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "polop", fileKey);
+ when(componentDao.getByKey(session, fileKey)).thenThrow(new NotFoundException());
+
+ WsTester.TestRequest request = tester.newGetRequest("api/sources", "index").setParam("resource", fileKey);
+ try {
+ request.execute();
+ } catch(NotFoundException nfe) {
+ verify(session).close();
+ }
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
index 2039584edec..ddbb959010b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
@@ -78,7 +78,8 @@ public class LinesActionTest {
mock(RawAction.class),
mock(ScmAction.class),
new LinesAction(sourceLineIndex, htmlSourceDecorator, componentService),
- mock(HashAction.class)
+ mock(HashAction.class),
+ mock(IndexAction.class)
)
);
when(htmlSourceDecorator.getDecoratedSourceAsHtml(anyString(), anyString(), anyString())).thenAnswer(new Answer<String>() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
index a306752ce50..5b11c4fb8a1 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
@@ -66,7 +66,7 @@ public class RawActionTest {
when(dbClient.componentDao()).thenReturn(componentDao);
when(dbClient.openSession(false)).thenReturn(session);
tester = new WsTester(new SourcesWs(mock(ShowAction.class), new RawAction(dbClient, sourceService), mock(ScmAction.class), mock(LinesAction.class),
- mock(HashAction.class)));
+ mock(HashAction.class), mock(IndexAction.class)));
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java
index ba91095a920..97ccb21efa6 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java
@@ -35,7 +35,7 @@ public class ScmActionTest {
SourceService sourceService = mock(SourceService.class);
ScmWriter scmWriter = mock(ScmWriter.class);
WsTester tester = new WsTester(new SourcesWs(mock(ShowAction.class), mock(RawAction.class), new ScmAction(sourceService, scmWriter), mock(LinesAction.class),
- mock(HashAction.class)));
+ mock(HashAction.class), mock(IndexAction.class)));
@Test
public void get_scm() throws Exception {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
index 5c9df69e4ec..c3471efa0bb 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
@@ -67,7 +67,8 @@ public class ShowActionTest {
when(dbClient.openSession(false)).thenReturn(session);
tester = new WsTester(new SourcesWs(new ShowAction(sourceService, dbClient), mock(RawAction.class), new ScmAction(sourceService, mock(ScmWriter.class)),
mock(LinesAction.class),
- mock(HashAction.class)));
+ mock(HashAction.class),
+ mock(IndexAction.class)));
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
index 20aed4eee31..db22e8bb0a8 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
@@ -40,7 +40,8 @@ public class SourcesWsTest {
ScmAction scmAction = new ScmAction(mock(SourceService.class), new ScmWriter());
LinesAction linesAction = new LinesAction(mock(SourceLineIndex.class), mock(HtmlSourceDecorator.class), mock(ComponentService.class));
HashAction hashAction = new HashAction(mock(DbClient.class), mock(FileSourceDao.class));
- WsTester tester = new WsTester(new SourcesWs(showAction, rawAction, scmAction, linesAction, hashAction));
+ IndexAction indexAction = new IndexAction(mock(DbClient.class), mock(SourceService.class));
+ WsTester tester = new WsTester(new SourcesWs(showAction, rawAction, scmAction, linesAction, hashAction, indexAction));
@Test
public void define_ws() throws Exception {
@@ -48,7 +49,7 @@ public class SourcesWsTest {
assertThat(controller).isNotNull();
assertThat(controller.since()).isEqualTo("4.2");
assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(5);
+ assertThat(controller.actions()).hasSize(6);
WebService.Action show = controller.action("show");
assertThat(show).isNotNull();
@@ -74,13 +75,13 @@ public class SourcesWsTest {
assertThat(scm.responseExampleAsString()).isNotEmpty();
assertThat(scm.params()).hasSize(4);
- WebService.Action index = controller.action("lines");
- assertThat(index).isNotNull();
- assertThat(index.handler()).isSameAs(linesAction);
- assertThat(index.since()).isEqualTo("5.0");
- assertThat(index.isInternal()).isTrue();
- assertThat(index.responseExampleAsString()).isNotEmpty();
- assertThat(index.params()).hasSize(3);
+ WebService.Action lines = controller.action("lines");
+ assertThat(lines).isNotNull();
+ assertThat(lines.handler()).isSameAs(linesAction);
+ assertThat(lines.since()).isEqualTo("5.0");
+ assertThat(lines.isInternal()).isTrue();
+ assertThat(lines.responseExampleAsString()).isNotEmpty();
+ assertThat(lines.params()).hasSize(3);
WebService.Action hash = controller.action("hash");
assertThat(hash).isNotNull();
@@ -89,5 +90,14 @@ public class SourcesWsTest {
assertThat(hash.isInternal()).isTrue();
assertThat(hash.responseExampleAsString()).isNotEmpty();
assertThat(hash.params()).hasSize(1);
+
+ WebService.Action index = controller.action("index");
+ assertThat(index).isNotNull();
+ assertThat(index.handler()).isSameAs(indexAction);
+ assertThat(index.since()).isEqualTo("5.0");
+ assertThat(index.isInternal()).isTrue();
+ assertThat(index.responseExampleAsString()).isNotEmpty();
+ assertThat(index.params()).hasSize(3);
+
}
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/ws/IndexActionTest/index-result.json b/server/sonar-server/src/test/resources/org/sonar/server/source/ws/IndexActionTest/index-result.json
new file mode 100644
index 00000000000..fb991865f86
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/source/ws/IndexActionTest/index-result.json
@@ -0,0 +1,6 @@
+[
+ {
+ "1": "public class HelloWorld {",
+ "2": "}"
+ }
+] \ No newline at end of file