aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/db/MeasureMapper.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml15
-rw-r--r--sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java6
-rw-r--r--sonar-server/src/main/java/org/sonar/server/measure/persistence/MeasureDao.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/source/SourceService.java25
-rw-r--r--sonar-server/src/main/resources/org/sonar/server/component/ws/components-app-example-show.json1
-rw-r--r--sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java7
-rw-r--r--sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java4
-rw-r--r--sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java17
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_periods.json1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_rules.json1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_severities.json1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_without_sub_project.json1
16 files changed, 83 insertions, 12 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/db/MeasureMapper.java b/sonar-core/src/main/java/org/sonar/core/measure/db/MeasureMapper.java
index fc3db6097b4..4fcb4ac938d 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/db/MeasureMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/db/MeasureMapper.java
@@ -30,4 +30,6 @@ public interface MeasureMapper {
List<MeasureDto> selectByComponentAndMetrics(@Param("componentKey") String componentKey, @Param("metricKeys") List<String> metricKeys);
+ long count(@Param("key") MeasureKey key);
+
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml b/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
index e7553613f56..d1adf669fdc 100644
--- a/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/measure/db/MeasureMapper.xml
@@ -45,4 +45,19 @@
</where>
</select>
+ <select id="count" parameterType="map" resultType="long">
+ SELECT count(pm.id)
+ FROM project_measures pm
+ INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true}
+ INNER JOIN metrics metric ON metric.id=pm.metric_id
+ INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true}
+ <where>
+ AND p.kee = #{key.componentKey}
+ AND metric.name = #{key.metricKey}
+ AND pm.rule_id IS NULL
+ AND pm.characteristic_id IS NULL
+ AND pm.person_id IS NULL
+ </where>
+ </select>
+
</mapper>
diff --git a/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java b/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java
index 4dd47f6880d..47ddd61e687 100644
--- a/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java
+++ b/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentAppAction.java
@@ -52,6 +52,7 @@ import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueService;
import org.sonar.server.issue.RulesAggregation;
import org.sonar.server.measure.persistence.MeasureDao;
+import org.sonar.server.source.SourceService;
import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
@@ -69,13 +70,15 @@ public class ComponentAppAction implements RequestHandler {
private final DbClient dbClient;
private final IssueService issueService;
+ private final SourceService sourceService;
private final Periods periods;
private final Durations durations;
private final I18n i18n;
- public ComponentAppAction(DbClient dbClient, IssueService issueService, Periods periods, Durations durations, I18n i18n) {
+ public ComponentAppAction(DbClient dbClient, IssueService issueService, SourceService sourceService, Periods periods, Durations durations, I18n i18n) {
this.dbClient = dbClient;
this.issueService = issueService;
+ this.sourceService = sourceService;
this.periods = periods;
this.durations = durations;
this.i18n = i18n;
@@ -146,6 +149,7 @@ public class ComponentAppAction implements RequestHandler {
json.prop("projectName", project.longName());
json.prop("fav", isFavourite);
+ json.prop("scmAvailable", sourceService.hasScmData(component.key(), session));
}
private void appendPermissions(JsonWriter json, ComponentDto component, UserSession userSession) {
diff --git a/sonar-server/src/main/java/org/sonar/server/measure/persistence/MeasureDao.java b/sonar-server/src/main/java/org/sonar/server/measure/persistence/MeasureDao.java
index 9303d974145..8446ba71cb5 100644
--- a/sonar-server/src/main/java/org/sonar/server/measure/persistence/MeasureDao.java
+++ b/sonar-server/src/main/java/org/sonar/server/measure/persistence/MeasureDao.java
@@ -52,6 +52,10 @@ public class MeasureDao extends BaseDao<MeasureMapper, MeasureDto, MeasureKey> i
return session.getMapper(MeasureMapper.class).selectByKey(key);
}
+ public boolean exists(MeasureKey key, DbSession session) {
+ return session.getMapper(MeasureMapper.class).count(key) > 0;
+ }
+
public List<MeasureDto> findByComponentKeyAndMetricKeys(String componentKey, List<String> metricKeys, DbSession session){
if (metricKeys.isEmpty()) {
return Collections.emptyList();
diff --git a/sonar-server/src/main/java/org/sonar/server/source/SourceService.java b/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
index ad3ead6d929..d2c09186e06 100644
--- a/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
+++ b/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
@@ -27,6 +27,7 @@ import org.sonar.core.measure.db.MeasureDto;
import org.sonar.core.measure.db.MeasureKey;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.user.UserSession;
@@ -37,7 +38,7 @@ import java.util.List;
public class SourceService implements ServerComponent {
- private final MyBatis myBatis;
+ private final DbClient dbClient;
private final HtmlSourceDecorator sourceDecorator;
@@ -48,11 +49,11 @@ public class SourceService implements ServerComponent {
private final MeasureDao measureDao;
- public SourceService(MyBatis myBatis, HtmlSourceDecorator sourceDecorator, DeprecatedSourceDecorator deprecatedSourceDecorator, MeasureDao measureDao) {
- this.myBatis = myBatis;
+ public SourceService(DbClient dbClient, HtmlSourceDecorator sourceDecorator, DeprecatedSourceDecorator deprecatedSourceDecorator) {
+ this.dbClient = dbClient;
this.sourceDecorator = sourceDecorator;
this.deprecatedSourceDecorator = deprecatedSourceDecorator;
- this.measureDao = measureDao;
+ this.measureDao = dbClient.getDao(MeasureDao.class);
}
public List<String> getLinesAsHtml(String fileKey) {
@@ -81,13 +82,27 @@ public class SourceService implements ServerComponent {
return findDataFromComponent(fileKey, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
}
+ public boolean hasScmData(String fileKey, DbSession session) {
+ return measureDao.exists(MeasureKey.of(fileKey, CoreMetrics.SCM_AUTHORS_BY_LINE_KEY), session);
+ }
+
+ public boolean hasScmData(String fileKey) {
+ checkPermission(fileKey);
+ DbSession session = dbClient.openSession(false);
+ try {
+ return hasScmData(fileKey, session);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
private void checkPermission(String fileKey) {
UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
}
@CheckForNull
private String findDataFromComponent(String fileKey, String metricKey) {
- DbSession session = myBatis.openSession(false);
+ DbSession session = dbClient.openSession(false);
try {
MeasureDto data = measureDao.getByKey(MeasureKey.of(fileKey, metricKey), session);
if (data != null) {
diff --git a/sonar-server/src/main/resources/org/sonar/server/component/ws/components-app-example-show.json b/sonar-server/src/main/resources/org/sonar/server/component/ws/components-app-example-show.json
index 7c2670fa21f..5798fdac578 100644
--- a/sonar-server/src/main/resources/org/sonar/server/component/ws/components-app-example-show.json
+++ b/sonar-server/src/main/resources/org/sonar/server/component/ws/components-app-example-show.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": true,
+ "scmAvailable": true,
"canMarkAsFavourite": true,
"canBulkChange": false,
"periods": [
diff --git a/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java b/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
index fd2900c0bba..510d648a572 100644
--- a/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
@@ -49,6 +49,7 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.issue.IssueService;
import org.sonar.server.issue.RulesAggregation;
import org.sonar.server.measure.persistence.MeasureDao;
+import org.sonar.server.source.SourceService;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
@@ -86,6 +87,9 @@ public class ComponentAppActionTest {
IssueService issueService;
@Mock
+ SourceService sourceService;
+
+ @Mock
Periods periods;
@Mock
@@ -111,7 +115,7 @@ public class ComponentAppActionTest {
when(issueService.findRulesByComponent(anyString(), eq(session))).thenReturn(mock(RulesAggregation.class));
when(measureDao.findByComponentKeyAndMetricKeys(anyString(), anyListOf(String.class), eq(session))).thenReturn(measures);
- tester = new WsTester(new ComponentsWs(new ComponentAppAction(dbClient, issueService, periods, durations, i18n)));
+ tester = new WsTester(new ComponentsWs(new ComponentAppAction(dbClient, issueService, sourceService, periods, durations, i18n)));
}
@Test
@@ -124,6 +128,7 @@ public class ComponentAppActionTest {
when(componentDao.getById(5L, session)).thenReturn(new ComponentDto().setId(5L).setLongName("SonarQube :: Plugin API"));
when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setLongName("SonarQube"));
when(propertiesDao.selectByQuery(any(PropertyQuery.class), eq(session))).thenReturn(newArrayList(new PropertyDto()));
+ when(sourceService.hasScmData(eq(COMPONENT_KEY), eq(session))).thenReturn(true);
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
request.execute().assertJson(getClass(), "app.json");
diff --git a/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java b/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
index c6358a587b1..dc952770f8a 100644
--- a/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
@@ -29,6 +29,7 @@ import org.sonar.api.utils.Durations;
import org.sonar.core.timemachine.Periods;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.IssueService;
+import org.sonar.server.source.SourceService;
import org.sonar.server.ws.WsTester;
import static org.fest.assertions.Assertions.assertThat;
@@ -40,7 +41,8 @@ public class ComponentsWsTest {
@Before
public void setUp() throws Exception {
- WsTester tester = new WsTester(new ComponentsWs(new ComponentAppAction(mock(DbClient.class), mock(IssueService.class), mock(Periods.class), mock(Durations.class), mock(I18n.class))));
+ WsTester tester = new WsTester(new ComponentsWs(new ComponentAppAction(mock(DbClient.class), mock(IssueService.class), mock(SourceService.class),
+ mock(Periods.class), mock(Durations.class), mock(I18n.class))));
controller = tester.controller("api/components");
}
diff --git a/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java b/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
index 27755289041..f3ac394599f 100644
--- a/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
@@ -93,4 +93,12 @@ public class MeasureDaoTest extends AbstractDaoTestCase {
assertThat(result.getValue()).isEqualTo(10d);
assertThat(result.getKey()).isNotNull();
}
+
+ @Test
+ public void exists() throws Exception {
+ setupData("shared");
+
+ assertThat(dao.exists(MeasureKey.of("org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc"), session)).isTrue();
+ assertThat(dao.exists(MeasureKey.of("org.struts:struts-core:src/org/struts/RequestContext.java", "unknown"), session)).isFalse();
+ }
}
diff --git a/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java b/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
index feae50a14dc..2370356e815 100644
--- a/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
@@ -29,7 +29,7 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.web.UserRole;
import org.sonar.core.measure.db.MeasureKey;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.user.MockUserSession;
@@ -62,9 +62,10 @@ public class SourceServiceTest {
@Before
public void setUp() throws Exception {
- MyBatis myBatis = mock(MyBatis.class);
- when(myBatis.openSession(false)).thenReturn(session);
- service = new SourceService(myBatis, sourceDecorator, deprecatedSourceDecorator, measureDao);
+ DbClient dbClient = mock(DbClient.class);
+ when(dbClient.openSession(false)).thenReturn(session);
+ when(dbClient.getDao(MeasureDao.class)).thenReturn(measureDao);
+ service = new SourceService(dbClient, sourceDecorator, deprecatedSourceDecorator);
}
@Test
@@ -133,4 +134,12 @@ public class SourceServiceTest {
when(measureDao.getByKey(any(MeasureKey.class), eq(session))).thenReturn(null);
assertThat(service.getScmDateData(COMPONENT_KEY)).isNull();
}
+
+ @Test
+ public void has_scm_data() throws Exception {
+ MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, PROJECT_KEY, COMPONENT_KEY);
+
+ when(measureDao.exists(any(MeasureKey.class), eq(session))).thenReturn(true);
+ assertThat(service.hasScmData(COMPONENT_KEY)).isTrue();
+ }
}
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json
index 9d71aad91ca..466fa162d50 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": true,
+ "scmAvailable": true,
"canMarkAsFavourite": true,
"canBulkChange": true,
"periods": [],
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json
index 34c784044b3..0a888c70c9d 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_measures.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": false,
+ "scmAvailable": false,
"canMarkAsFavourite": false,
"canBulkChange": false,
"periods": [],
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_periods.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_periods.json
index 646cc2464e3..bed31c83110 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_periods.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_periods.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": false,
+ "scmAvailable": false,
"canMarkAsFavourite": false,
"canBulkChange": false,
"periods": [
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_rules.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_rules.json
index 78afaae5404..eec5ca7c609 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_rules.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_rules.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": false,
+ "scmAvailable": false,
"canMarkAsFavourite": false,
"canBulkChange": false,
"periods": [],
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_severities.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_severities.json
index 1dcbac620c7..a479050f9e1 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_severities.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_with_severities.json
@@ -6,6 +6,7 @@
"subProjectName": "SonarQube :: Plugin API",
"projectName": "SonarQube",
"fav": false,
+ "scmAvailable": false,
"canMarkAsFavourite": false,
"canBulkChange": false,
"periods": [],
diff --git a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_without_sub_project.json b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_without_sub_project.json
index 9d6f9806489..d0bbe41275e 100644
--- a/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_without_sub_project.json
+++ b/sonar-server/src/test/resources/org/sonar/server/component/ws/ComponentAppActionTest/app_without_sub_project.json
@@ -4,6 +4,7 @@
"q": "TRK",
"projectName": "SonarQube",
"fav": true,
+ "scmAvailable": false,
"canMarkAsFavourite": true,
"canBulkChange": true,
"periods": [],