aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl12
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java10
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java6
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDao.java61
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDao.java69
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDto.java (renamed from server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDto.java)62
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkMapper.java (renamed from server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkMapper.java)14
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java2
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml57
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/component/ProjectLinkMapper.xml69
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml4
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java9
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java137
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDaoTest.java166
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDbTester.java59
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDtoTest.java (renamed from server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java)20
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkTesting.java52
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml5
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml3
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml5
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml7
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml5
-rw-r--r--server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml5
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java28
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java77
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java5
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java (renamed from server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkTesting.java)26
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java112
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java56
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java14
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java66
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java54
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java209
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java58
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql0
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql7
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql64
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql9
-rw-r--r--server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/ProjectLinksPage.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStep.java115
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java16
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/CreateAction.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java29
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/search-example.json (renamed from server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json)1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest.java141
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/CreateActionTest.java84
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/DeleteActionTest.java152
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java88
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java241
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/add_links_on_project_and_module-result.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/delete_link.xml5
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/empty.xml3
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/not_delete_custom_link.xml5
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/nothing_to_do_when_link_already_exists.xml5
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link-result.xml5
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link.xml5
-rw-r--r--tests/src/test/java/org/sonarqube/tests/project/ProjectLinksTest.java8
64 files changed, 1642 insertions, 978 deletions
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
index 5c287cea0ec..c63f060e839 100644
--- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
+++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
@@ -283,13 +283,17 @@ CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
CREATE TABLE "PROJECT_LINKS" (
- "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
- "COMPONENT_UUID" VARCHAR(50),
- "LINK_TYPE" VARCHAR(20),
+ "UUID" VARCHAR(40) NOT NULL,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "LINK_TYPE" VARCHAR(20) NOT NULL,
"NAME" VARCHAR(128),
- "HREF" VARCHAR(2048) NOT NULL
+ "HREF" VARCHAR(2048) NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
);
+CREATE INDEX "PROJECT_LINKS_PROJECT" ON "PROJECT_LINKS" ("PROJECT_UUID");
+
CREATE TABLE "DUPLICATIONS_INDEX" (
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
index 31a49c77346..ef1d147fe33 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
@@ -32,7 +32,7 @@ import org.sonar.db.component.AnalysisPropertiesDao;
import org.sonar.db.component.BranchDao;
import org.sonar.db.component.ComponentDao;
import org.sonar.db.component.ComponentKeyUpdaterDao;
-import org.sonar.db.component.ComponentLinkDao;
+import org.sonar.db.component.ProjectLinkDao;
import org.sonar.db.component.SnapshotDao;
import org.sonar.db.duplication.DuplicationDao;
import org.sonar.db.es.EsQueueDao;
@@ -92,7 +92,7 @@ public class DaoModule extends Module {
CeTaskInputDao.class,
ComponentDao.class,
ComponentKeyUpdaterDao.class,
- ComponentLinkDao.class,
+ ProjectLinkDao.class,
LiveMeasureDao.class,
CustomMeasureDao.class,
DefaultQProfileDao.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
index 3b671e1b682..ee6e3b82eb9 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
@@ -30,7 +30,7 @@ import org.sonar.db.component.AnalysisPropertiesDao;
import org.sonar.db.component.BranchDao;
import org.sonar.db.component.ComponentDao;
import org.sonar.db.component.ComponentKeyUpdaterDao;
-import org.sonar.db.component.ComponentLinkDao;
+import org.sonar.db.component.ProjectLinkDao;
import org.sonar.db.component.SnapshotDao;
import org.sonar.db.duplication.DuplicationDao;
import org.sonar.db.es.EsQueueDao;
@@ -107,7 +107,7 @@ public class DbClient {
private final CeTaskCharacteristicDao ceTaskCharacteristicsDao;
private final CeScannerContextDao ceScannerContextDao;
private final FileSourceDao fileSourceDao;
- private final ComponentLinkDao componentLinkDao;
+ private final ProjectLinkDao projectLinkDao;
private final EventDao eventDao;
private final PurgeDao purgeDao;
private final QualityGateDao qualityGateDao;
@@ -169,7 +169,7 @@ public class DbClient {
ceTaskCharacteristicsDao = getDao(map, CeTaskCharacteristicDao.class);
ceScannerContextDao = getDao(map, CeScannerContextDao.class);
fileSourceDao = getDao(map, FileSourceDao.class);
- componentLinkDao = getDao(map, ComponentLinkDao.class);
+ projectLinkDao = getDao(map, ProjectLinkDao.class);
eventDao = getDao(map, EventDao.class);
purgeDao = getDao(map, PurgeDao.class);
qualityGateDao = getDao(map, QualityGateDao.class);
@@ -316,8 +316,8 @@ public class DbClient {
return fileSourceDao;
}
- public ComponentLinkDao componentLinkDao() {
- return componentLinkDao;
+ public ProjectLinkDao projectLinkDao() {
+ return projectLinkDao;
}
public EventDao eventDao() {
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
index c14eba4110d..5559074c5c7 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
@@ -40,11 +40,10 @@ import org.sonar.db.component.BranchMapper;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentDtoWithSnapshotId;
import org.sonar.db.component.ComponentKeyUpdaterMapper;
-import org.sonar.db.component.ComponentLinkDto;
-import org.sonar.db.component.ComponentLinkMapper;
import org.sonar.db.component.ComponentMapper;
import org.sonar.db.component.FilePathWithHashDto;
import org.sonar.db.component.KeyWithUuidDto;
+import org.sonar.db.component.ProjectLinkMapper;
import org.sonar.db.component.ResourceDto;
import org.sonar.db.component.ScrapAnalysisPropertyDto;
import org.sonar.db.component.SnapshotDto;
@@ -149,7 +148,6 @@ public class MyBatis implements Startable {
confBuilder.loadAlias("ActiveRuleParam", ActiveRuleParamDto.class);
confBuilder.loadAlias("CeTaskCharacteristic", CeTaskCharacteristicDto.class);
confBuilder.loadAlias("Component", ComponentDto.class);
- confBuilder.loadAlias("ComponentLink", ComponentLinkDto.class);
confBuilder.loadAlias("ComponentWithSnapshot", ComponentDtoWithSnapshotId.class);
confBuilder.loadAlias("CustomMeasure", CustomMeasureDto.class);
confBuilder.loadAlias("DuplicationUnit", DuplicationUnitDto.class);
@@ -206,7 +204,7 @@ public class MyBatis implements Startable {
CeTaskInputMapper.class,
CeTaskCharacteristicMapper.class,
ComponentKeyUpdaterMapper.class,
- ComponentLinkMapper.class,
+ ProjectLinkMapper.class,
ComponentMapper.class,
LiveMeasureMapper.class,
CustomMeasureMapper.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDao.java
deleted file mode 100644
index 9a1b058112c..00000000000
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDao.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.db.component;
-
-import java.util.List;
-import javax.annotation.CheckForNull;
-import org.sonar.db.Dao;
-import org.sonar.db.DbSession;
-
-import static java.util.Collections.emptyList;
-
-public class ComponentLinkDao implements Dao {
-
- public List<ComponentLinkDto> selectByComponentUuid(DbSession session, String componentUuid) {
- return session.getMapper(ComponentLinkMapper.class).selectByComponentUuid(componentUuid);
- }
-
- public List<ComponentLinkDto> selectByComponentUuids(DbSession dbSession, List<String> componentUuids) {
- return componentUuids.isEmpty() ? emptyList() : mapper(dbSession).selectByComponentUuids(componentUuids);
- }
-
- @CheckForNull
- public ComponentLinkDto selectById(DbSession session, long id) {
- return session.getMapper(ComponentLinkMapper.class).selectById(id);
- }
-
- public ComponentLinkDto insert(DbSession session, ComponentLinkDto dto) {
- session.getMapper(ComponentLinkMapper.class).insert(dto);
- return dto;
- }
-
- public void update(DbSession session, ComponentLinkDto dto) {
- session.getMapper(ComponentLinkMapper.class).update(dto);
- }
-
- public void delete(DbSession session, long id) {
- session.getMapper(ComponentLinkMapper.class).delete(id);
- }
-
- private static ComponentLinkMapper mapper(DbSession dbSession) {
- return dbSession.getMapper(ComponentLinkMapper.class);
- }
-
-}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDao.java
new file mode 100644
index 00000000000..d375b1e5368
--- /dev/null
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDao.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.component;
+
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.sonar.api.utils.System2;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+import static org.sonar.db.DatabaseUtils.executeLargeInputs;
+
+public class ProjectLinkDao implements Dao {
+
+ private final System2 system2;
+
+ public ProjectLinkDao(System2 system2) {
+ this.system2 = system2;
+ }
+
+ public List<ProjectLinkDto> selectByProjectUuid(DbSession session, String projectUuid) {
+ return session.getMapper(ProjectLinkMapper.class).selectByProjectUuid(projectUuid);
+ }
+
+ public List<ProjectLinkDto> selectByProjectUuids(DbSession dbSession, List<String> projectUuids) {
+ return executeLargeInputs(projectUuids, mapper(dbSession)::selectByProjectUuids);
+ }
+
+ @CheckForNull
+ public ProjectLinkDto selectByUuid(DbSession session, String uuid) {
+ return session.getMapper(ProjectLinkMapper.class).selectByUuid(uuid);
+ }
+
+ public ProjectLinkDto insert(DbSession session, ProjectLinkDto dto) {
+ long now = system2.now();
+ session.getMapper(ProjectLinkMapper.class).insert(dto.setCreatedAt(now).setUpdatedAt(now));
+ return dto;
+ }
+
+ public void update(DbSession session, ProjectLinkDto dto) {
+ session.getMapper(ProjectLinkMapper.class).update(dto.setUpdatedAt(system2.now()));
+ }
+
+ public void delete(DbSession session, String uuid) {
+ session.getMapper(ProjectLinkMapper.class).delete(uuid);
+ }
+
+ private static ProjectLinkMapper mapper(DbSession dbSession) {
+ return dbSession.getMapper(ProjectLinkMapper.class);
+ }
+
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDto.java
index 8cd7d0a000b..9930ee9b9d7 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkDto.java
@@ -21,42 +21,53 @@ package org.sonar.db.component;
import com.google.common.collect.ImmutableList;
import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
-/**
- * Component links should be merge in a 'links' column (using protobuf for instance) of the projects table.
- * But to do this we'll have to wait for the measure filters page (where links are displayed) to be rewritten in JS/WS (because it's in Rails for the moment).
- */
-public class ComponentLinkDto {
+public class ProjectLinkDto {
public static final String TYPE_HOME_PAGE = "homepage";
public static final String TYPE_CI = "ci";
public static final String TYPE_ISSUE_TRACKER = "issue";
public static final String TYPE_SOURCES = "scm";
+
public static final String TYPE_SOURCES_DEV = "scm_dev";
public static final List<String> PROVIDED_TYPES = ImmutableList.of(TYPE_HOME_PAGE, TYPE_CI, TYPE_ISSUE_TRACKER, TYPE_SOURCES, TYPE_SOURCES_DEV);
- private Long id;
- private String componentUuid;
+ private String uuid;
+ private String projectUuid;
private String type;
private String name;
private String href;
+ private long createdAt;
+ private long updatedAt;
+
+ public String getUuid() {
+ return uuid;
+ }
+ public ProjectLinkDto setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ @CheckForNull
public String getName() {
return name;
}
- public ComponentLinkDto setName(String name) {
+ public ProjectLinkDto setName(@Nullable String name) {
this.name = name;
return this;
}
- public String getComponentUuid() {
- return componentUuid;
+ public String getProjectUuid() {
+ return projectUuid;
}
- public ComponentLinkDto setComponentUuid(String componentUuid) {
- this.componentUuid = componentUuid;
+ public ProjectLinkDto setProjectUuid(String projectUuid) {
+ this.projectUuid = projectUuid;
return this;
}
@@ -64,30 +75,35 @@ public class ComponentLinkDto {
return href;
}
- public ComponentLinkDto setHref(String href) {
+ public ProjectLinkDto setHref(String href) {
this.href = href;
return this;
}
- public Long getId() {
- return id;
+ public String getType() {
+ return type;
+ }
+
+ public ProjectLinkDto setType(String type) {
+ this.type = type;
+ return this;
}
- public String getIdAsString() {
- return String.valueOf(id);
+ public long getCreatedAt() {
+ return createdAt;
}
- public ComponentLinkDto setId(Long id) {
- this.id = id;
+ public ProjectLinkDto setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
return this;
}
- public String getType() {
- return type;
+ public long getUpdatedAt() {
+ return updatedAt;
}
- public ComponentLinkDto setType(String type) {
- this.type = type;
+ public ProjectLinkDto setUpdatedAt(long updatedAt) {
+ this.updatedAt = updatedAt;
return this;
}
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkMapper.java
index fe955f73275..9fc084f3e2c 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentLinkMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ProjectLinkMapper.java
@@ -22,17 +22,17 @@ package org.sonar.db.component;
import java.util.List;
import org.apache.ibatis.annotations.Param;
-public interface ComponentLinkMapper {
+public interface ProjectLinkMapper {
- List<ComponentLinkDto> selectByComponentUuid(String componentUuid);
+ List<ProjectLinkDto> selectByProjectUuid(String projectUuid);
- List<ComponentLinkDto> selectByComponentUuids(@Param("componentUuids") List<String> componentUuids);
+ List<ProjectLinkDto> selectByProjectUuids(@Param("projectUuids") List<String> projectUuids);
- ComponentLinkDto selectById(@Param("id") long id);
+ ProjectLinkDto selectByUuid(@Param("uuid") String uuid);
- void insert(ComponentLinkDto dto);
+ void insert(ProjectLinkDto dto);
- void update(ComponentLinkDto dto);
+ void update(ProjectLinkDto dto);
- void delete(long id);
+ void delete(String uuid);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
index edbe6931d79..4e346364ee9 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java
@@ -169,7 +169,7 @@ class PurgeCommands {
void deleteLinks(String rootUuid) {
profiler.start("deleteLinks (project_links)");
- purgeMapper.deleteProjectLinksByComponentUuid(rootUuid);
+ purgeMapper.deleteProjectLinksByProjectUuid(rootUuid);
session.commit();
profiler.stop();
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
index 2db61704c6d..a9dec7bb5b2 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java
@@ -54,7 +54,7 @@ public interface PurgeMapper {
void resolveComponentIssuesNotAlreadyResolved(@Param("componentUuids") List<String> componentUuids, @Param("dateAsLong") Long dateAsLong);
- void deleteProjectLinksByComponentUuid(@Param("rootUuid") String rootUuid);
+ void deleteProjectLinksByProjectUuid(@Param("rootUuid") String rootUuid);
void deletePropertiesByComponentIds(@Param("componentIds") List<Long> componentIds);
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml
deleted file mode 100644
index cbc4412649e..00000000000
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentLinkMapper.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
-<mapper namespace="org.sonar.db.component.ComponentLinkMapper">
-
- <sql id="componentLinkColumns">
- p.id,
- p.component_uuid as "componentUuid",
- p.link_type as "type",
- p.name as name,
- p.href as href
- </sql>
-
- <select id="selectByComponentUuid" parameterType="String" resultType="ComponentLink">
- SELECT
- <include refid="componentLinkColumns"/>
- FROM project_links p
- where p.component_uuid=#{uuid,jdbcType=VARCHAR}
- ORDER BY p.id
- </select>
-
- <select id="selectByComponentUuids" parameterType="String" resultType="ComponentLink">
- SELECT
- <include refid="componentLinkColumns"/>
- FROM project_links p
- where
- p.component_uuid in
- <foreach collection="componentUuids" open="(" close=")" item="uuid" separator=",">
- #{uuid,jdbcType=VARCHAR}
- </foreach>
- order by p.id
- </select>
-
- <select id="selectById" parameterType="long" resultType="ComponentLink">
- SELECT
- <include refid="componentLinkColumns"/>
- FROM project_links p
- where p.id=#{id,jdbcType=BIGINT}
- </select>
-
- <insert id="insert" parameterType="ComponentLink" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
- INSERT INTO project_links (component_uuid, link_type, name, href)
- VALUES (#{componentUuid,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
- #{href,jdbcType=VARCHAR})
- </insert>
-
- <insert id="update" parameterType="ComponentLink" useGeneratedKeys="false">
- UPDATE project_links SET component_uuid=#{componentUuid,jdbcType=VARCHAR}, link_type=#{type,jdbcType=VARCHAR},
- name=#{name,jdbcType=VARCHAR}, href=#{href,jdbcType=VARCHAR}
- WHERE id=#{id,jdbcType=BIGINT}
- </insert>
-
- <delete id="delete">
- DELETE FROM project_links WHERE id=#{id,jdbcType=BIGINT}
- </delete>
-
-</mapper>
-
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ProjectLinkMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ProjectLinkMapper.xml
new file mode 100644
index 00000000000..248b7ae067b
--- /dev/null
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ProjectLinkMapper.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
+<mapper namespace="org.sonar.db.component.ProjectLinkMapper">
+
+ <sql id="columns">
+ p.uuid,
+ p.project_uuid as "projectUuid",
+ p.link_type as "type",
+ p.name as name,
+ p.href as href,
+ p.created_at as "createdAt",
+ p.updated_at as "updatedAt"
+ </sql>
+
+ <select id="selectByProjectUuid" parameterType="String" resultType="org.sonar.db.component.ProjectLinkDto">
+ SELECT
+ <include refid="columns"/>
+ FROM project_links p
+ where p.project_uuid=#{uuid,jdbcType=VARCHAR}
+ ORDER BY p.uuid
+ </select>
+
+ <select id="selectByProjectUuids" parameterType="String" resultType="org.sonar.db.component.ProjectLinkDto">
+ SELECT
+ <include refid="columns"/>
+ FROM project_links p
+ where
+ p.project_uuid in
+ <foreach collection="projectUuids" open="(" close=")" item="uuid" separator=",">
+ #{uuid,jdbcType=VARCHAR}
+ </foreach>
+ order by p.uuid
+ </select>
+
+ <select id="selectByUuid" parameterType="String" resultType="org.sonar.db.component.ProjectLinkDto">
+ SELECT
+ <include refid="columns"/>
+ FROM project_links p
+ where p.uuid=#{uuid,jdbcType=VARCHAR}
+ </select>
+
+ <insert id="insert" parameterType="org.sonar.db.component.ProjectLinkDto" useGeneratedKeys="false">
+ INSERT INTO project_links (uuid, project_uuid, link_type, name, href, created_at, updated_at)
+ VALUES (
+ #{uuid,jdbcType=VARCHAR},
+ #{projectUuid,jdbcType=VARCHAR},
+ #{type,jdbcType=VARCHAR},
+ #{name,jdbcType=VARCHAR},
+ #{href,jdbcType=VARCHAR},
+ #{createdAt,jdbcType=BIGINT},
+ #{updatedAt,jdbcType=BIGINT})
+ </insert>
+
+ <insert id="update" parameterType="org.sonar.db.component.ProjectLinkDto" useGeneratedKeys="false">
+ UPDATE project_links SET
+ project_uuid=#{projectUuid,jdbcType=VARCHAR},
+ link_type=#{type,jdbcType=VARCHAR},
+ name=#{name,jdbcType=VARCHAR},
+ href=#{href,jdbcType=VARCHAR},
+ updated_at=#{updatedAt,jdbcType=BIGINT}
+ WHERE uuid=#{uuid,jdbcType=VARCHAR}
+ </insert>
+
+ <delete id="delete">
+ DELETE FROM project_links WHERE uuid=#{uuid,jdbcType=VARCHAR}
+ </delete>
+
+</mapper>
+
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
index 4f652c7cdc8..b8af25a7598 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
@@ -187,10 +187,10 @@
and resolution is null
</update>
- <delete id="deleteProjectLinksByComponentUuid" parameterType="map">
+ <delete id="deleteProjectLinksByProjectUuid" parameterType="map">
delete from project_links
where
- component_uuid = #{rootUuid,jdbcType=VARCHAR}
+ project_uuid = #{rootUuid,jdbcType=VARCHAR}
</delete>
<delete id="deletePropertiesByComponentIds" parameterType="map">
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
index 01e64c19a3c..f4d7d81ffd7 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
@@ -30,6 +30,7 @@ import org.picocontainer.containers.TransientPicoContainer;
import org.sonar.api.utils.System2;
import org.sonar.core.util.SequenceUuidFactory;
import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ProjectLinkDbTester;
import org.sonar.db.event.EventDbTester;
import org.sonar.db.favorite.FavoriteDbTester;
import org.sonar.db.issue.IssueDbTester;
@@ -42,7 +43,6 @@ import org.sonar.db.permission.template.PermissionTemplateDbTester;
import org.sonar.db.plugin.PluginDbTester;
import org.sonar.db.property.PropertyDbTester;
import org.sonar.db.qualitygate.QualityGateDbTester;
-import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.db.qualityprofile.QualityProfileDbTester;
import org.sonar.db.rule.RuleDbTester;
import org.sonar.db.source.FileSourceTester;
@@ -65,10 +65,10 @@ public class DbTester extends AbstractDbTester<TestDb> {
private boolean started = false;
private String defaultOrganizationUuid = randomAlphanumeric(40);
private OrganizationDto defaultOrganization;
- private QualityGateDto builtInQualityGate;
private final UserDbTester userTester;
private final ComponentDbTester componentTester;
+ private final ProjectLinkDbTester componentLinkTester;
private final FavoriteDbTester favoriteTester;
private final EventDbTester eventTester;
private final OrganizationDbTester organizationTester;
@@ -91,6 +91,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
initDbClient();
this.userTester = new UserDbTester(this);
this.componentTester = new ComponentDbTester(this);
+ this.componentLinkTester = new ProjectLinkDbTester(this);
this.favoriteTester = new FavoriteDbTester(this);
this.eventTester = new EventDbTester(this);
this.organizationTester = new OrganizationDbTester(this);
@@ -187,6 +188,10 @@ public class DbTester extends AbstractDbTester<TestDb> {
return componentTester;
}
+ public ProjectLinkDbTester componentLinks() {
+ return componentLinkTester;
+ }
+
public FavoriteDbTester favorites() {
return favoriteTester;
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
deleted file mode 100644
index 1cb63786c9c..00000000000
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.db.component;
-
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static java.util.Collections.emptyList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.component.ComponentLinkDto.TYPE_HOME_PAGE;
-import static org.sonar.db.component.ComponentLinkDto.TYPE_SOURCES;
-import static org.sonar.db.component.ComponentLinkTesting.newComponentLinkDto;
-
-
-public class ComponentLinkDaoTest {
-
- @Rule
- public DbTester db = DbTester.create(System2.INSTANCE);
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
-
- private ComponentLinkDao underTest = db.getDbClient().componentLinkDao();
-
- @Test
- public void select_by_component_uuid() {
- db.prepareDbUnit(getClass(), "shared.xml");
-
- List<ComponentLinkDto> links = underTest.selectByComponentUuid(db.getSession(), "ABCD");
- assertThat(links).hasSize(2);
-
- links = underTest.selectByComponentUuid(db.getSession(), "BCDE");
- assertThat(links).hasSize(1);
-
- ComponentLinkDto link = links.get(0);
- assertThat(link.getId()).isEqualTo(3L);
- assertThat(link.getComponentUuid()).isEqualTo("BCDE");
- assertThat(link.getType()).isEqualTo("homepage");
- assertThat(link.getName()).isEqualTo("Home");
- assertThat(link.getHref()).isEqualTo("http://www.struts.org");
- }
-
- @Test
- public void select_by_component_uuids() {
- String firstUuid = "COMPONENT_UUID_1";
- String secondUuid = "COMPONENT_UUID_2";
- dbClient.componentLinkDao().insert(dbSession, newComponentLinkDto().setComponentUuid(firstUuid).setType(TYPE_HOME_PAGE));
- dbClient.componentLinkDao().insert(dbSession, newComponentLinkDto().setComponentUuid(firstUuid).setType(TYPE_SOURCES));
- dbClient.componentLinkDao().insert(dbSession, newComponentLinkDto().setComponentUuid(secondUuid).setType(TYPE_HOME_PAGE));
- dbClient.componentLinkDao().insert(dbSession, newComponentLinkDto().setComponentUuid("ANOTHER_COMPONENT_UUID").setType(TYPE_HOME_PAGE));
- db.commit();
-
- List<ComponentLinkDto> result = underTest.selectByComponentUuids(dbSession, newArrayList(firstUuid, secondUuid));
-
- assertThat(result).hasSize(3).extracting(ComponentLinkDto::getComponentUuid).containsOnly(firstUuid, secondUuid);
- }
-
- @Test
- public void select_by_component_uuids_with_empty_list() {
- List<ComponentLinkDto> result = underTest.selectByComponentUuids(dbSession, emptyList());
-
- assertThat(result).isEmpty();
- }
-
- @Test
- public void select_by_id() {
- ComponentLinkDto link = underTest.insert(dbSession, newComponentLinkDto());
- db.commit();
-
- ComponentLinkDto candidate = underTest.selectById(dbSession, link.getId());
- assertThat(candidate.getId()).isNotNull();
- }
-
- @Test
- public void insert() {
- db.prepareDbUnit(getClass(), "empty.xml");
-
- underTest.insert(db.getSession(), new ComponentLinkDto()
- .setComponentUuid("ABCD")
- .setType("homepage")
- .setName("Home")
- .setHref("http://www.sonarqube.org")
- );
- db.getSession().commit();
-
- db.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "project_links");
- }
-
- @Test
- public void update() {
- db.prepareDbUnit(getClass(), "update.xml");
-
- underTest.update(db.getSession(), new ComponentLinkDto()
- .setId(1L)
- .setComponentUuid("ABCD")
- .setType("homepage")
- .setName("Home")
- .setHref("http://www.sonarqube.org")
- );
- db.getSession().commit();
-
- db.assertDbUnit(getClass(), "update-result.xml", "project_links");
- }
-
- @Test
- public void delete() {
- db.prepareDbUnit(getClass(), "delete.xml");
-
- underTest.delete(db.getSession(), 1L);
- db.getSession().commit();
-
- assertThat(db.countRowsOfTable("project_links")).isEqualTo(0);
- }
-
-}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDaoTest.java
new file mode 100644
index 00000000000..eaba69b0c37
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDaoTest.java
@@ -0,0 +1,166 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.component;
+
+import java.util.Collections;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.db.DbTester;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectLinkDaoTest {
+
+ private final static long PAST = 5_000_000_000L;
+ private final static long NOW = 10_000_000_000L;
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ private ProjectLinkDao underTest = db.getDbClient().projectLinkDao();
+
+ @Test
+ public void select_by_id() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertProvidedLink(project, c -> c
+ .setUuid("ABCD")
+ .setName("Home")
+ .setType("homepage")
+ .setHref("http://www.struts.org"));
+
+ ProjectLinkDto reloaded = underTest.selectByUuid(db.getSession(), link.getUuid());
+
+ assertThat(reloaded.getUuid()).isEqualTo("ABCD");
+ assertThat(reloaded.getProjectUuid()).isEqualTo(project.uuid());
+ assertThat(reloaded.getType()).isEqualTo("homepage");
+ assertThat(reloaded.getName()).isEqualTo("Home");
+ assertThat(reloaded.getHref()).isEqualTo("http://www.struts.org");
+ assertThat(reloaded.getCreatedAt()).isEqualTo(NOW);
+ assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW);
+ }
+
+ @Test
+ public void select_by_project_uuid() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link1 = db.componentLinks().insertProvidedLink(project);
+ ProjectLinkDto link2 = db.componentLinks().insertProvidedLink(project);
+ ProjectLinkDto link3 = db.componentLinks().insertProvidedLink(project);
+ ComponentDto otherProject = db.components().insertPrivateProject();
+ ProjectLinkDto otherLink = db.componentLinks().insertProvidedLink(otherProject);
+
+ assertThat(underTest.selectByProjectUuid(db.getSession(), project.uuid()))
+ .extracting(ProjectLinkDto::getUuid)
+ .containsExactlyInAnyOrder(link1.getUuid(), link2.getUuid(), link3.getUuid());
+ assertThat(underTest.selectByProjectUuid(db.getSession(), otherProject.uuid()))
+ .extracting(ProjectLinkDto::getUuid)
+ .containsExactlyInAnyOrder(otherLink.getUuid());
+ assertThat(underTest.selectByProjectUuid(db.getSession(), "UNKNOWN")).isEmpty();
+ }
+
+ @Test
+ public void select_by_project_uuids() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ProjectLinkDto link1 = db.componentLinks().insertProvidedLink(project1);
+ ProjectLinkDto link2 = db.componentLinks().insertProvidedLink(project1);
+ ComponentDto project2 = db.components().insertPrivateProject();
+ ProjectLinkDto link3 = db.componentLinks().insertProvidedLink(project2);
+
+ assertThat(underTest.selectByProjectUuids(db.getSession(), asList(project1.uuid(), project2.uuid())))
+ .extracting(ProjectLinkDto::getUuid)
+ .containsOnly(link1.getUuid(), link2.getUuid(), link3.getUuid());
+ assertThat(underTest.selectByProjectUuids(db.getSession(), singletonList(project1.uuid())))
+ .extracting(ProjectLinkDto::getUuid)
+ .containsOnly(link1.getUuid(), link2.getUuid());
+ assertThat(underTest.selectByProjectUuids(db.getSession(), Collections.emptyList())).isEmpty();
+ }
+
+ @Test
+ public void insert() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = ProjectLinkTesting.newProvidedLinkDto()
+ .setUuid("ABCD")
+ .setProjectUuid(project.uuid())
+ .setName("Home")
+ .setType("homepage")
+ .setHref("http://www.struts.org")
+ // These fields will be set by the DAO
+ .setCreatedAt(0L)
+ .setUpdatedAt(0L);
+
+ underTest.insert(db.getSession(), link);
+ db.getSession().commit();
+
+ ProjectLinkDto reloaded = underTest.selectByUuid(db.getSession(), link.getUuid());
+ assertThat(reloaded.getUuid()).isEqualTo("ABCD");
+ assertThat(reloaded.getProjectUuid()).isEqualTo(project.uuid());
+ assertThat(reloaded.getType()).isEqualTo("homepage");
+ assertThat(reloaded.getName()).isEqualTo("Home");
+ assertThat(reloaded.getHref()).isEqualTo("http://www.struts.org");
+ assertThat(reloaded.getCreatedAt()).isEqualTo(NOW);
+ assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW);
+ }
+
+ @Test
+ public void update() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertProvidedLink(project, c -> c
+ .setUuid("ABCD")
+ .setType("ci")
+ .setName("Gihub")
+ .setHref("http://www.github.org"));
+ // Force dates to be in the past
+ db.executeUpdateSql("UPDATE project_links SET created_at=" + PAST + " ,updated_at=" + PAST);
+
+ ComponentDto project2 = db.components().insertPrivateProject();
+ underTest.update(db.getSession(), link
+ .setProjectUuid(project2.uuid())
+ .setType("homepage")
+ .setName("Home")
+ .setHref("http://www.sonarqube.org"));
+ db.getSession().commit();
+
+ ProjectLinkDto reloaded = underTest.selectByUuid(db.getSession(), link.getUuid());
+ assertThat(reloaded.getUuid()).isEqualTo("ABCD");
+ assertThat(reloaded.getProjectUuid()).isEqualTo(project2.uuid());
+ assertThat(reloaded.getType()).isEqualTo("homepage");
+ assertThat(reloaded.getName()).isEqualTo("Home");
+ assertThat(reloaded.getHref()).isEqualTo("http://www.sonarqube.org");
+ assertThat(reloaded.getCreatedAt()).isEqualTo(PAST);
+ assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW);
+ }
+
+ @Test
+ public void delete() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
+
+ underTest.delete(db.getSession(), link.getUuid());
+ db.getSession().commit();
+
+ assertThat(db.countRowsOfTable("project_links")).isEqualTo(0);
+ }
+
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDbTester.java
new file mode 100644
index 00000000000..dcc0d2d5db2
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDbTester.java
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.component;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+
+import static org.sonar.db.component.ProjectLinkTesting.newCustomLinkDto;
+import static org.sonar.db.component.ProjectLinkTesting.newProvidedLinkDto;
+
+public class ProjectLinkDbTester {
+ private final DbTester db;
+ private final DbClient dbClient;
+ private final DbSession dbSession;
+
+ public ProjectLinkDbTester(DbTester db) {
+ this.db = db;
+ this.dbClient = db.getDbClient();
+ this.dbSession = db.getSession();
+ }
+
+ @SafeVarargs
+ public final ProjectLinkDto insertProvidedLink(ComponentDto project, Consumer<ProjectLinkDto>... dtoPopulators) {
+ return insertLink(project, newProvidedLinkDto(), dtoPopulators);
+ }
+
+ @SafeVarargs
+ public final ProjectLinkDto insertCustomLink(ComponentDto project, Consumer<ProjectLinkDto>... dtoPopulators) {
+ return insertLink(project, newCustomLinkDto(), dtoPopulators);
+ }
+
+ @SafeVarargs
+ private final ProjectLinkDto insertLink(ComponentDto project, ProjectLinkDto componentLink, Consumer<ProjectLinkDto>... dtoPopulators) {
+ Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(componentLink));
+ dbClient.projectLinkDao().insert(dbSession, componentLink.setProjectUuid(project.uuid()));
+ db.commit();
+ return componentLink;
+ }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDtoTest.java
index 6e3c8ef5e2f..3301f42d1ff 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkDtoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDtoTest.java
@@ -23,26 +23,30 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
-public class ComponentLinkDtoTest {
+public class ProjectLinkDtoTest {
@Test
public void test_getters_and_setters() {
- ComponentLinkDto dto = new ComponentLinkDto()
- .setId(1L)
- .setComponentUuid("ABCD")
+ ProjectLinkDto dto = new ProjectLinkDto()
+ .setUuid("ABCD")
+ .setProjectUuid("EFGH")
.setType("homepage")
.setName("Home")
- .setHref("http://www.sonarqube.org");
+ .setHref("http://www.sonarqube.org")
+ .setCreatedAt(1_000_000_000L)
+ .setUpdatedAt(5_000_000_000L);
- assertThat(dto.getId()).isEqualTo(1L);
- assertThat(dto.getComponentUuid()).isEqualTo("ABCD");
+ assertThat(dto.getUuid()).isEqualTo("ABCD");
+ assertThat(dto.getProjectUuid()).isEqualTo("EFGH");
assertThat(dto.getType()).isEqualTo("homepage");
assertThat(dto.getName()).isEqualTo("Home");
assertThat(dto.getHref()).isEqualTo("http://www.sonarqube.org");
+ assertThat(dto.getCreatedAt()).isEqualTo(1_000_000_000L);
+ assertThat(dto.getUpdatedAt()).isEqualTo(5_000_000_000L);
}
@Test
public void test_provided_types() {
- assertThat(ComponentLinkDto.PROVIDED_TYPES).hasSize(5);
+ assertThat(ProjectLinkDto.PROVIDED_TYPES).hasSize(5);
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkTesting.java
new file mode 100644
index 00000000000..f79d90aa655
--- /dev/null
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkTesting.java
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.component;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.sonar.core.util.Uuids;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+
+public class ProjectLinkTesting {
+
+ public static ProjectLinkDto newProvidedLinkDto() {
+ return newCommonLinkDto()
+ .setName(null)
+ .setType(ProjectLinkDto.PROVIDED_TYPES.get(RandomUtils.nextInt(ProjectLinkDto.PROVIDED_TYPES.size() - 1)));
+ }
+
+ public static ProjectLinkDto newCustomLinkDto() {
+ String nameAndType = randomAlphabetic(20);
+ return newCommonLinkDto()
+ .setName(nameAndType)
+ .setType(nameAndType);
+ }
+
+ private static ProjectLinkDto newCommonLinkDto() {
+ return new ProjectLinkDto()
+ .setUuid(Uuids.createFast())
+ .setProjectUuid(Uuids.createFast())
+ .setHref(randomAlphanumeric(128))
+ .setCreatedAt(System.currentTimeMillis())
+ .setUpdatedAt(System.currentTimeMillis());
+ }
+
+}
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
deleted file mode 100644
index 871dedcb5e9..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<dataset>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
deleted file mode 100644
index 33e9449d1dd..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
- <project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
- <project_links id="3" component_uuid="BCDE" link_type="homepage" name="Home" href="http://www.struts.org"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
deleted file mode 100644
index 6b80fc9d01c..00000000000
--- a/server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="BCDE" link_type="ci" name="CI" href="github"/>
-
-</dataset>
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java
index f5adc72ba9a..ef381ab3f82 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilder.java
@@ -19,7 +19,6 @@
*/
package org.sonar.server.platform.db.migration.sql;
-import java.util.Arrays;
import java.util.List;
import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.H2;
@@ -29,19 +28,16 @@ import org.sonar.db.dialect.Oracle;
import org.sonar.db.dialect.PostgreSql;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.sonar.server.platform.db.migration.def.Validations.validateTableName;
-/**
- * Limitation: only tables with auto-generated ID column can
- * be renamed as the Oracle implementation assumes that
- * the sequence and trigger related to ID column exist.
- */
public class RenameTableBuilder {
private final Dialect dialect;
private String name;
private String newName;
+ private boolean autoGeneratedId = true;
public RenameTableBuilder(Dialect dialect) {
this.dialect = dialect;
@@ -57,6 +53,18 @@ public class RenameTableBuilder {
return this;
}
+ /**
+ * When a table has no auto generated id, this parameter has to be set to false.
+ * On Oracle, it will allow to not try to drop and recreate the trigger.
+ * On other databases, this method is useless.
+ *
+ * Default value is true.
+ */
+ public RenameTableBuilder setAutoGeneratedId(boolean autoGeneratedId) {
+ this.autoGeneratedId = autoGeneratedId;
+ return this;
+ }
+
public List<String> build() {
validateTableName(name);
validateTableName(newName);
@@ -73,11 +81,13 @@ public class RenameTableBuilder {
case MsSql.ID:
return singletonList("EXEC sp_rename '" + name + "', '" + newName + "'");
case Oracle.ID:
- return Arrays.asList(
+ String renameSqlCommand = "RENAME " + name + " TO " + newName;
+ return autoGeneratedId ? asList(
"DROP TRIGGER " + name + "_idt",
- "RENAME " + name + " TO " + newName,
+ renameSqlCommand,
"RENAME " + name + "_seq TO " + newName + "_seq",
- CreateTableBuilder.createOracleTriggerForTable(newName));
+ CreateTableBuilder.createOracleTriggerForTable(newName))
+ : singletonList(renameSqlCommand);
default:
throw new IllegalArgumentException("Unsupported dialect id " + dialect.getId());
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java
new file mode 100644
index 00000000000..d1be6af38fc
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.CreateTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class CreateTableProjectLinks2 extends DdlChange {
+
+ private static final String TABLE_NAME = "project_links2";
+
+ public CreateTableProjectLinks2(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME)
+ .addPkColumn(newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setLimit(UUID_SIZE)
+ .setIsNullable(false)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setLimit(UUID_SIZE)
+ .setIsNullable(false)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("link_type")
+ .setLimit(20)
+ .setIsNullable(false)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("name")
+ .setLimit(128)
+ .setIsNullable(true)
+ .build())
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("href")
+ .setLimit(2048)
+ .setIsNullable(false)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("created_at")
+ .setIsNullable(false)
+ .build())
+ .addColumn(newBigIntegerColumnDefBuilder()
+ .setColumnName("updated_at")
+ .setIsNullable(false)
+ .build())
+ .build());
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java
index a1cdf16d6e3..1e18627e81c 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java
@@ -35,6 +35,11 @@ public class DbVersion71 implements DbVersion {
.add(2005, "Create table DEPRECATED_RULE_KEYS", CreateDeprecatedRuleKeysTable.class)
.add(2006, "Clean orphans in Compute Engine child tables", CleanCeChildTablesOrphans.class)
.add(2007, "Update PERMISSION_TEMPLATES.KEYS ", UpdatePermissionTooLongTemplateKeys.class)
+ .add(2008, "Make scope not nullable in rules", MakeScopeNotNullableInRules.class)
+ .add(2009, "Create table PROJECT_LINKS2", CreateTableProjectLinks2.class)
+ .add(2010, "Populate table PROJECT_LINKS2", PopulateTableProjectLinks2.class)
+ .add(2011, "Drop table PROJECT_LINKS", DropTableProjectLinks.class)
+ .add(2012, "Rename table PROJECT_LINKS2 to PROJECT_LINKS", RenameTableProjectLinks2ToProjectLinks.class)
;
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkTesting.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java
index 6eea21b6867..ca2950b8bdb 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentLinkTesting.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinks.java
@@ -17,20 +17,24 @@
* 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.db.component;
+package org.sonar.server.platform.db.migration.version.v71;
-import org.sonar.core.util.Uuids;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.DropTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+public class DropTableProjectLinks extends DdlChange {
-public class ComponentLinkTesting {
- public static ComponentLinkDto newComponentLinkDto() {
- return new ComponentLinkDto()
- .setComponentUuid(Uuids.createFast())
- .setHref(randomAlphanumeric(128))
- .setName(randomAlphabetic(128))
- .setType(ComponentLinkDto.TYPE_SOURCES);
+ private static final String TABLE_NAME = "project_links";
+
+ public DropTableProjectLinks(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new DropTableBuilder(getDialect(), TABLE_NAME).build());
}
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java
new file mode 100644
index 00000000000..a42f8694604
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2.java
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import com.google.common.collect.ImmutableList;
+import java.sql.SQLException;
+import java.util.List;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+/**
+ * Populate PROJECT_LINK2 data from PROJECT_LINK table and take the opportunity to do some cleanup :
+ * - Ignore link that are not set on project (only take component with qualifier TRK and scope PRJ)
+ * - Do not set a name on provided links (SONAR-10411)
+ * - Do not copy link on Developer Connection (SONAR-10299)
+ */
+public class PopulateTableProjectLinks2 extends DataChange {
+
+ private static final String TYPE_HOME_PAGE = "homepage";
+ private static final String TYPE_CI = "ci";
+ private static final String TYPE_ISSUE_TRACKER = "issue";
+ private static final String TYPE_SOURCES = "scm";
+ private static final String TYPE_SOURCES_DEV = "scm_dev";
+ private static final List<String> PROVIDED_TYPES = ImmutableList.of(TYPE_HOME_PAGE, TYPE_CI, TYPE_ISSUE_TRACKER, TYPE_SOURCES);
+
+ private static final String SCOPE_PROJECT = "PRJ";
+ private static final String QUALIFIER_PROJECT = "TRK";
+
+ private final UuidFactory uuidFactory;
+ private final System2 system2;
+
+ public PopulateTableProjectLinks2(Database db, UuidFactory uuidFactory, System2 system2) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ long now = system2.now();
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("SELECT" +
+ " p.component_uuid, p.link_type, p.name, p.href" +
+ " from project_links p" +
+ // Join on projects in order to sanitize orphans (if any)
+ " inner join projects prj on prj.uuid=p.component_uuid and prj.scope=? and prj.qualifier=? " +
+ " left outer join project_links2 p2" +
+ " on p2.project_uuid=p.component_uuid " +
+ " and p2.href=p.href" +
+ " and p2.link_type=p.link_type" +
+ " and (p2.name=p.name or (p2.name is null and p.link_type in (?, ?, ?, ?)))" +
+ " where" +
+ " p2.uuid is null" +
+ " order by p.id")
+ .setString(1, SCOPE_PROJECT)
+ .setString(2, QUALIFIER_PROJECT)
+ .setString(3, TYPE_HOME_PAGE)
+ .setString(4, TYPE_CI)
+ .setString(5, TYPE_ISSUE_TRACKER)
+ .setString(6, TYPE_SOURCES);
+ massUpdate.update("insert into project_links2" +
+ " (uuid, project_uuid, link_type, name, href, created_at, updated_at)" +
+ " values " +
+ " (?, ?, ?, ?, ?, ?, ?)");
+ massUpdate.rowPluralName("project links");
+ massUpdate.execute((row, update) -> {
+ String componentUuid = row.getString(1);
+ String linkType = row.getString(2);
+ String name = row.getString(3);
+ String href = row.getString(4);
+
+ // project link "developer connection" are removed
+ if (linkType.equals(TYPE_SOURCES_DEV)) {
+ return false;
+ }
+
+ update.setString(1, uuidFactory.create());
+ update.setString(2, componentUuid);
+ update.setString(3, linkType);
+ // provided type don't need anymore a name, the UI will display it by getting the i18 bundle of the link_type value
+ if (PROVIDED_TYPES.contains(linkType)) {
+ update.setString(4, null);
+ } else {
+ update.setString(4, name);
+ }
+ update.setString(5, href);
+ update.setLong(6, now);
+ update.setLong(7, now);
+ return true;
+ });
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java
new file mode 100644
index 00000000000..dd9f12c647d
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinks.java
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.sql.RenameTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class RenameTableProjectLinks2ToProjectLinks extends DdlChange {
+
+ public RenameTableProjectLinks2ToProjectLinks(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new RenameTableBuilder(getDialect())
+ .setName("project_links2")
+ .setNewName("project_links")
+ .setAutoGeneratedId(false)
+ .build());
+
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable("project_links")
+ .setName("project_links_project")
+ .addColumn(newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setLimit(UUID_SIZE)
+ .setIsNullable(false)
+ .build())
+ .build());
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java
index 1f32d803d9f..cfe6cffad87 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/sql/RenameTableBuilderTest.java
@@ -62,6 +62,11 @@ public class RenameTableBuilderTest {
}
@Test
+ public void rename_table_on_oracle_when_auto_generated_id_is_false() {
+ verifySqlWhenAutoGeneratedIdIsFalse(new Oracle(), "RENAME foo TO bar");
+ }
+
+ @Test
public void rename_table_on_postgresql() {
verifySql(new PostgreSql(), "ALTER TABLE foo RENAME TO bar");
}
@@ -89,4 +94,13 @@ public class RenameTableBuilderTest {
.build();
assertThat(actual).containsExactly(expectedSql);
}
+
+ private static void verifySqlWhenAutoGeneratedIdIsFalse(Dialect dialect, String... expectedSql) {
+ List<String> actual = new RenameTableBuilder(dialect)
+ .setName("foo")
+ .setNewName("bar")
+ .setAutoGeneratedId(false)
+ .build();
+ assertThat(actual).containsExactly(expectedSql);
+ }
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java
new file mode 100644
index 00000000000..ff65f3fcf36
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CreateTableProjectLinks2Test {
+
+ private static final String TABLE_NAME = "project_links2";
+
+ @Rule
+ public final CoreDbTester dbTester = CoreDbTester.createForSchema(CreateTableProjectLinks2Test.class, "empty.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private CreateTableProjectLinks2 underTest = new CreateTableProjectLinks2(dbTester.database());
+
+ @Test
+ public void creates_table_on_empty_db() throws SQLException {
+ underTest.execute();
+
+ assertThat(dbTester.countRowsOfTable(TABLE_NAME)).isEqualTo(0);
+
+ dbTester.assertColumnDefinition(TABLE_NAME, "uuid", Types.VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "project_uuid", Types.VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "link_type", Types.VARCHAR, 20, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "name", Types.VARCHAR, 128, true);
+ dbTester.assertColumnDefinition(TABLE_NAME, "href", Types.VARCHAR, 2048, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "created_at", Types.BIGINT, null, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "updated_at", Types.BIGINT, null, false);
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+} \ No newline at end of file
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java
index 15fee0317ac..a93444604fd 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java
@@ -36,7 +36,7 @@ public class DbVersion71Test {
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 8);
+ verifyMigrationCount(underTest, 13);
}
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java
new file mode 100644
index 00000000000..09e78e36aa1
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+public class DropTableProjectLinksTest {
+
+ @Rule
+ public final CoreDbTester dbTester = CoreDbTester.createForSchema(DropTableProjectLinksTest.class, "project_links.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private DropTableProjectLinks underTest = new DropTableProjectLinks(dbTester.database());
+
+ @Test
+ public void creates_table_on_empty_db() throws SQLException {
+ underTest.execute();
+
+ dbTester.assertTableDoesNotExist("project_links");
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java
new file mode 100644
index 00000000000..487d57fac52
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java
@@ -0,0 +1,209 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import java.util.stream.Collectors;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.SequenceUuidFactory;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class PopulateTableProjectLinks2Test {
+
+ private static final long PAST = 5_000_000_000L;
+ private static final long NOW = 10_000_000_000L;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateTableProjectLinks2Test.class, "project_links2.sql");
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+ private UuidFactory uuidFactory = new SequenceUuidFactory();
+
+ private PopulateTableProjectLinks2 underTest = new PopulateTableProjectLinks2(db.database(), uuidFactory, system2);
+
+ @Test
+ public void copy_custom_links() throws SQLException {
+ String project = insertProject();
+ insertProjectLink("Name1", "custom1", "http://link1", project);
+ insertProjectLink("Name2", "custom2", "http://link2", project);
+
+ underTest.execute();
+
+ assertProjectLinks2(
+ tuple("Name1", "custom1", "http://link1", project, NOW, NOW),
+ tuple("Name2", "custom2", "http://link2", project, NOW, NOW));
+ }
+
+ @Test
+ public void remove_name_of_provided_links() throws SQLException {
+ String project = insertProject();
+ insertProjectLink("Home", "homepage", "http://homepage", project);
+ insertProjectLink("CI", "ci", "http://ci", project);
+ insertProjectLink("Jira", "issue", "http://issue", project);
+ insertProjectLink("SCM", "scm", "http://scm", project);
+
+ underTest.execute();
+
+ assertProjectLinks2(
+ tuple(null, "homepage", "http://homepage", project, NOW, NOW),
+ tuple(null, "ci", "http://ci", project, NOW, NOW),
+ tuple(null, "issue", "http://issue", project, NOW, NOW),
+ tuple(null, "scm", "http://scm", project, NOW, NOW));
+ }
+
+ @Test
+ public void copy_links_from_different_projects() throws SQLException {
+ String project1 = insertProject();
+ insertProjectLink("Name", "custom", "http://link1", project1);
+ String project2 = insertProject();
+ insertProjectLink("Name", "custom", "http://link2", project2);
+
+ underTest.execute();
+
+ assertProjectLinks2(
+ tuple("Name", "custom", "http://link1", project1, NOW, NOW),
+ tuple("Name", "custom", "http://link2", project2, NOW, NOW));
+ }
+
+ @Test
+ public void do_not_copy_links_from_developer_connection_link() throws SQLException {
+ insertProjectLink("Dev", "scm_dev", "http://link1", insertProject());
+
+ underTest.execute();
+
+ assertNoProjectLinks2();
+ }
+
+ @Test
+ public void do_not_copy_links_from_components_that_are_not_projects() throws SQLException {
+ insertProjectLink("Name", "custom", "http://link1", insertComponent("PRJ", "BRC"));
+ insertProjectLink("Name", "custom", "http://link2", insertComponent("PRJ", "VW"));
+ insertProjectLink("Name", "custom", "http://link1", insertComponent("DIR", "DIR"));
+ insertProjectLink("Name", "custom", "http://link1", "UNKNOWN");
+
+ underTest.execute();
+
+ assertNoProjectLinks2();
+ }
+
+ @Test
+ public void do_not_copy_already_copied_data() throws SQLException {
+ String project = insertProject();
+ insertProjectLink("Name", "custom", "http://link", project);
+ insertProjectLink("Home", "homepage", "http://homepage", project);
+ insertProjectLink2("UUID1", "Name", "custom", "http://link", project, PAST);
+ insertProjectLink2("UUID2", null, "homepage", "http://homepage", project, PAST);
+
+ underTest.execute();
+
+ assertThat(db.select("SELECT UUID, NAME, LINK_TYPE, HREF, PROJECT_UUID, CREATED_AT FROM PROJECT_LINKS2")
+ .stream()
+ .map(map -> new Tuple(map.get("UUID"), map.get("NAME"), map.get("LINK_TYPE"), map.get("HREF"), map.get("PROJECT_UUID"), map.get("CREATED_AT")))
+ .collect(Collectors.toList()))
+ .containsExactlyInAnyOrder(
+ tuple("UUID1", "Name", "custom", "http://link", project, PAST),
+ tuple("UUID2", null, "homepage", "http://homepage", project, PAST));
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ String project = insertProject();
+ insertProjectLink("Name", "custom", "http://link", project);
+
+ underTest.execute();
+ underTest.execute();
+
+ assertProjectLinks2(tuple("Name", "custom", "http://link", project, NOW, NOW));
+ }
+
+ @Test
+ public void has_no_effect_if_table_is_empty() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable("project_links2")).isZero();
+ }
+
+ private void assertNoProjectLinks2() {
+ assertProjectLinks2();
+ }
+
+ private void assertProjectLinks2(Tuple... expectedTuples) {
+ assertThat(db.select("SELECT NAME, LINK_TYPE, HREF, PROJECT_UUID, CREATED_AT, UPDATED_AT FROM PROJECT_LINKS2")
+ .stream()
+ .map(map -> new Tuple(map.get("NAME"), map.get("LINK_TYPE"), map.get("HREF"), map.get("PROJECT_UUID"), map.get("CREATED_AT"), map.get("UPDATED_AT")))
+ .collect(Collectors.toList()))
+ .containsExactlyInAnyOrder(expectedTuples);
+ }
+
+ private void insertProjectLink(String name, String linkType, String href, String componentUuid) {
+ db.executeInsert(
+ "PROJECT_LINKS",
+ "COMPONENT_UUID", componentUuid,
+ "NAME", name,
+ "LINK_TYPE", linkType,
+ "HREF", href);
+ }
+
+ private void insertProjectLink2(String uuid, String name, String linkType, String href, String componentUuid, Long createdAt) {
+ db.executeInsert(
+ "PROJECT_LINKS2",
+ "UUID", uuid,
+ "PROJECT_UUID", componentUuid,
+ "NAME", name,
+ "LINK_TYPE", linkType,
+ "HREF", href,
+ "CREATED_AT", createdAt,
+ "UPDATED_AT", createdAt);
+ }
+
+ private String insertProject() {
+ return insertComponent("PRJ", "TRK");
+ }
+
+ private String insertComponent(String scope, String qualifier) {
+ String uuid = uuidFactory.create();
+ db.executeInsert("PROJECTS",
+ "ORGANIZATION_UUID", "O1",
+ "KEE", uuid,
+ "UUID", uuid,
+ "PROJECT_UUID", uuid,
+ "MAIN_BRANCH_PROJECT_UUID", uuid,
+ "UUID_PATH", ".",
+ "ROOT_UUID", uuid,
+ "PRIVATE", "true",
+ "QUALIFIER", qualifier,
+ "SCOPE", scope);
+ return uuid;
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java
new file mode 100644
index 00000000000..0440fc4e00d
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest.java
@@ -0,0 +1,58 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v71;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RenameTableProjectLinks2ToProjectLinksTest {
+
+ @Rule
+ public final CoreDbTester dbTester = CoreDbTester.createForSchema(RenameTableProjectLinks2ToProjectLinksTest.class, "project_links2.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private RenameTableProjectLinks2ToProjectLinks underTest = new RenameTableProjectLinks2ToProjectLinks(dbTester.database());
+
+ @Test
+ public void creates_table_on_empty_db() throws SQLException {
+ underTest.execute();
+
+ dbTester.assertTableDoesNotExist("project_links2");
+ assertThat(dbTester.countRowsOfTable("project_links")).isZero();
+ dbTester.assertIndex("project_links", "project_links_project", "project_uuid");
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+
+ underTest.execute();
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/CreateTableProjectLinks2Test/empty.sql
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql
new file mode 100644
index 00000000000..9588643a463
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/DropTableProjectLinksTest/project_links.sql
@@ -0,0 +1,7 @@
+CREATE TABLE "PROJECT_LINKS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "COMPONENT_UUID" VARCHAR(50),
+ "LINK_TYPE" VARCHAR(20),
+ "NAME" VARCHAR(128),
+ "HREF" VARCHAR(2048) NOT NULL
+);
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql
new file mode 100644
index 00000000000..ef474cc6421
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test/project_links2.sql
@@ -0,0 +1,64 @@
+CREATE TABLE "PROJECT_LINKS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "COMPONENT_UUID" VARCHAR(50),
+ "LINK_TYPE" VARCHAR(20),
+ "NAME" VARCHAR(128),
+ "HREF" VARCHAR(2048) NOT NULL
+);
+
+CREATE TABLE "PROJECT_LINKS2" (
+ "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "LINK_TYPE" VARCHAR(20) NOT NULL,
+ "NAME" VARCHAR(128),
+ "HREF" VARCHAR(2048) NOT NULL,
+ "CREATED_AT" BIGINT NOT NULL,
+ "UPDATED_AT" BIGINT NOT NULL
+);
+
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+ "KEE" VARCHAR(400),
+ "UUID" VARCHAR(50) NOT NULL,
+ "UUID_PATH" VARCHAR(1500) NOT NULL,
+ "ROOT_UUID" VARCHAR(50) NOT NULL,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "MODULE_UUID" VARCHAR(50),
+ "MODULE_UUID_PATH" VARCHAR(1500),
+ "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+ "NAME" VARCHAR(2000),
+ "DESCRIPTION" VARCHAR(2000),
+ "PRIVATE" BOOLEAN NOT NULL,
+ "TAGS" VARCHAR(500),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "DEPRECATED_KEE" VARCHAR(400),
+ "PATH" VARCHAR(2000),
+ "LANGUAGE" VARCHAR(20),
+ "COPY_COMPONENT_UUID" VARCHAR(50),
+ "LONG_NAME" VARCHAR(2000),
+ "DEVELOPER_UUID" VARCHAR(50),
+ "CREATED_AT" TIMESTAMP,
+ "AUTHORIZATION_UPDATED_AT" BIGINT,
+ "B_CHANGED" BOOLEAN,
+ "B_COPY_COMPONENT_UUID" VARCHAR(50),
+ "B_DESCRIPTION" VARCHAR(2000),
+ "B_ENABLED" BOOLEAN,
+ "B_UUID_PATH" VARCHAR(1500),
+ "B_LANGUAGE" VARCHAR(20),
+ "B_LONG_NAME" VARCHAR(500),
+ "B_MODULE_UUID" VARCHAR(50),
+ "B_MODULE_UUID_PATH" VARCHAR(1500),
+ "B_NAME" VARCHAR(500),
+ "B_PATH" VARCHAR(2000),
+ "B_QUALIFIER" VARCHAR(10)
+);
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER"); \ No newline at end of file
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql
new file mode 100644
index 00000000000..c29900dbd64
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/RenameTableProjectLinks2ToProjectLinksTest/project_links2.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "PROJECT_LINKS2" (
+ "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "LINK_TYPE" VARCHAR(20) NOT NULL,
+ "NAME" VARCHAR(128),
+ "HREF" VARCHAR(2048) NOT NULL,
+ "CREATED_AT" BIGINT NOT NULL,
+ "UPDATED_AT" BIGINT NOT NULL
+);
diff --git a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/ProjectLinksPage.java b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/ProjectLinksPage.java
index f114bce59ef..fd8bb42438f 100644
--- a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/ProjectLinksPage.java
+++ b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/ProjectLinksPage.java
@@ -32,7 +32,7 @@ public class ProjectLinksPage {
}
public ElementsCollection getLinks() {
- return Selenide.$$("#project-links tr[data-name]");
+ return Selenide.$$("#project-links tbody tr");
}
public List<ProjectLinkItem> getLinksAsItems() {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStep.java
index eb5b14a3d3e..c255ba1189f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStep.java
@@ -22,129 +22,88 @@ package org.sonar.server.computation.task.projectanalysis.step;
import com.google.common.collect.ImmutableMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import org.sonar.api.i18n.I18n;
+import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
-import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
-import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
import org.sonar.server.computation.task.step.ComputationStep;
-import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
+import static com.google.common.base.Preconditions.checkArgument;
-/**
- * Persist project and module links
- */
public class PersistProjectLinksStep implements ComputationStep {
private final DbClient dbClient;
- private final I18n i18n;
private final TreeRootHolder treeRootHolder;
private final BatchReportReader reportReader;
+ private final UuidFactory uuidFactory;
private static final Map<ComponentLinkType, String> typesConverter = ImmutableMap.of(
- ComponentLinkType.HOME, ComponentLinkDto.TYPE_HOME_PAGE,
- ComponentLinkType.SCM, ComponentLinkDto.TYPE_SOURCES,
- ComponentLinkType.SCM_DEV, ComponentLinkDto.TYPE_SOURCES_DEV,
- ComponentLinkType.CI, ComponentLinkDto.TYPE_CI,
- ComponentLinkType.ISSUE, ComponentLinkDto.TYPE_ISSUE_TRACKER);
+ ComponentLinkType.HOME, ProjectLinkDto.TYPE_HOME_PAGE,
+ ComponentLinkType.SCM, ProjectLinkDto.TYPE_SOURCES,
+ ComponentLinkType.SCM_DEV, ProjectLinkDto.TYPE_SOURCES_DEV,
+ ComponentLinkType.CI, ProjectLinkDto.TYPE_CI,
+ ComponentLinkType.ISSUE, ProjectLinkDto.TYPE_ISSUE_TRACKER);
- public PersistProjectLinksStep(DbClient dbClient, I18n i18n, TreeRootHolder treeRootHolder, BatchReportReader reportReader) {
+ public PersistProjectLinksStep(DbClient dbClient, TreeRootHolder treeRootHolder, BatchReportReader reportReader, UuidFactory uuidFactory) {
this.dbClient = dbClient;
- this.i18n = i18n;
this.treeRootHolder = treeRootHolder;
this.reportReader = reportReader;
+ this.uuidFactory = uuidFactory;
}
@Override
public void execute() {
try (DbSession session = dbClient.openSession(false)) {
- new DepthTraversalTypeAwareCrawler(new ProjectLinkVisitor(session))
- .visit(treeRootHolder.getRoot());
+ Component project = treeRootHolder.getRoot();
+ ScannerReport.Component batchComponent = reportReader.readComponent(project.getReportAttributes().getRef());
+ List<ProjectLinkDto> previousLinks = dbClient.projectLinkDao().selectByProjectUuid(session, project.getUuid());
+ mergeLinks(session, project.getUuid(), batchComponent.getLinkList(), previousLinks);
session.commit();
}
}
- private class ProjectLinkVisitor extends TypeAwareVisitorAdapter {
-
- private final DbSession session;
-
- private ProjectLinkVisitor(DbSession session) {
- super(CrawlerDepthLimit.FILE, PRE_ORDER);
- this.session = session;
- }
-
- @Override
- public void visitProject(Component project) {
- processComponent(project);
- }
-
- @Override
- public void visitModule(Component module) {
- processComponent(module);
- }
-
- private void processComponent(Component component) {
- ScannerReport.Component batchComponent = reportReader.readComponent(component.getReportAttributes().getRef());
- processLinks(component.getUuid(), batchComponent.getLinkList());
- }
-
- private void processLinks(String componentUuid, List<ScannerReport.ComponentLink> links) {
- List<ComponentLinkDto> previousLinks = dbClient.componentLinkDao().selectByComponentUuid(session, componentUuid);
- mergeLinks(session, componentUuid, links, previousLinks);
- }
-
- private void mergeLinks(DbSession session, String componentUuid, List<ScannerReport.ComponentLink> links, List<ComponentLinkDto> previousLinks) {
- Set<String> linkType = new HashSet<>();
- for (final ScannerReport.ComponentLink link : links) {
+ private void mergeLinks(DbSession session, String componentUuid, List<ScannerReport.ComponentLink> links, List<ProjectLinkDto> previousLinks) {
+ Set<String> linkType = new HashSet<>();
+ links.forEach(
+ link -> {
String type = convertType(link.getType());
- if (!linkType.contains(type)) {
- linkType.add(type);
- } else {
- throw new IllegalArgumentException(String.format("Link of type '%s' has already been declared on component '%s'", type, componentUuid));
- }
+ checkArgument(!linkType.contains(type), "Link of type '%s' has already been declared on component '%s'", type, componentUuid);
+ linkType.add(type);
- Optional<ComponentLinkDto> previousLink = previousLinks.stream()
+ Optional<ProjectLinkDto> previousLink = previousLinks.stream()
.filter(input -> input != null && input.getType().equals(convertType(link.getType())))
.findFirst();
if (previousLink.isPresent()) {
previousLink.get().setHref(link.getHref());
- dbClient.componentLinkDao().update(session, previousLink.get());
+ dbClient.projectLinkDao().update(session, previousLink.get());
} else {
- dbClient.componentLinkDao().insert(session,
- new ComponentLinkDto()
- .setComponentUuid(componentUuid)
+ dbClient.projectLinkDao().insert(session,
+ new ProjectLinkDto()
+ .setUuid(uuidFactory.create())
+ .setProjectUuid(componentUuid)
.setType(type)
- .setName(i18n.message(Locale.ENGLISH, "project_links." + type, null))
.setHref(link.getHref()));
}
- }
+ });
- for (ComponentLinkDto dto : previousLinks) {
- if (!linkType.contains(dto.getType()) && ComponentLinkDto.PROVIDED_TYPES.contains(dto.getType())) {
- dbClient.componentLinkDao().delete(session, dto.getId());
- }
- }
- }
+ previousLinks.stream()
+ .filter(dto -> !linkType.contains(dto.getType()))
+ .filter(dto -> ProjectLinkDto.PROVIDED_TYPES.contains(dto.getType()))
+ .forEach(dto -> dbClient.projectLinkDao().delete(session, dto.getUuid()));
+ }
- private String convertType(ComponentLinkType reportType) {
- String type = typesConverter.get(reportType);
- if (type != null) {
- return type;
- } else {
- throw new IllegalArgumentException(String.format("Unsupported type %s", reportType.name()));
- }
- }
+ private static String convertType(ComponentLinkType reportType) {
+ String type = typesConverter.get(reportType);
+ checkArgument(type != null, "Unsupported type %s", reportType.name());
+ return type;
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
index 13a77a87161..1ec0e29c2a1 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
@@ -37,8 +37,8 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentQuery;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.server.user.UserSession;
@@ -148,11 +148,11 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
}
}
- private enum ProjectLinkDtoToWs implements Function<ComponentLinkDto, Link> {
+ private enum ProjectLinkDtoToWs implements Function<ProjectLinkDto, Link> {
INSTANCE;
@Override
- public Link apply(ComponentLinkDto dto) {
+ public Link apply(ProjectLinkDto dto) {
Link.Builder link = Link.newBuilder();
link.setHref(dto.getHref());
@@ -172,7 +172,7 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
ProjectsResult searchResult = searchProjects(dbSession, request);
List<ComponentDto> projects = searchResult.projects;
List<String> projectUuids = Lists.transform(projects, ComponentDto::projectUuid);
- List<ComponentLinkDto> projectLinks = dbClient.componentLinkDao().selectByComponentUuids(dbSession, projectUuids);
+ List<ProjectLinkDto> projectLinks = dbClient.projectLinkDao().selectByProjectUuids(dbSession, projectUuids);
List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids);
List<LiveMeasureDto> qualityGates = dbClient.liveMeasureDao()
.selectByComponentUuidsAndMetricKeys(dbSession, projectUuids, singletonList(CoreMetrics.ALERT_STATUS_KEY));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
index 21361d0998b..29f9069eedb 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
@@ -27,7 +27,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.LiveMeasureDto;
@@ -37,7 +37,7 @@ import static org.sonar.api.utils.DateUtils.formatDateTime;
class SearchMyProjectsData {
private final List<ComponentDto> projects;
- private final ListMultimap<String, ComponentLinkDto> projectLinksByProjectUuid;
+ private final ListMultimap<String, ProjectLinkDto> projectLinksByProjectUuid;
private final Map<String, String> lastAnalysisDates;
private final Map<String, String> qualityGateStatuses;
private final int totalNbOfProject;
@@ -58,7 +58,7 @@ class SearchMyProjectsData {
return projects;
}
- List<ComponentLinkDto> projectLinksFor(String projectUuid) {
+ List<ProjectLinkDto> projectLinksFor(String projectUuid) {
return projectLinksByProjectUuid.get(projectUuid);
}
@@ -74,9 +74,9 @@ class SearchMyProjectsData {
return totalNbOfProject;
}
- private static ListMultimap<String, ComponentLinkDto> buildProjectLinks(List<ComponentLinkDto> dtos) {
- ImmutableListMultimap.Builder<String, ComponentLinkDto> projectLinks = ImmutableListMultimap.builder();
- dtos.forEach(projectLink -> projectLinks.put(projectLink.getComponentUuid(), projectLink));
+ private static ListMultimap<String, ProjectLinkDto> buildProjectLinks(List<ProjectLinkDto> dtos) {
+ ImmutableListMultimap.Builder<String, ProjectLinkDto> projectLinks = ImmutableListMultimap.builder();
+ dtos.forEach(projectLink -> projectLinks.put(projectLink.getProjectUuid(), projectLink));
return projectLinks.build();
}
@@ -93,7 +93,7 @@ class SearchMyProjectsData {
static class Builder {
private List<ComponentDto> projects;
- private List<ComponentLinkDto> projectLinks;
+ private List<ProjectLinkDto> projectLinks;
private List<SnapshotDto> snapshots;
private List<LiveMeasureDto> qualityGates;
private Integer totalNbOfProjects;
@@ -107,7 +107,7 @@ class SearchMyProjectsData {
return this;
}
- public Builder setProjectLinks(List<ComponentLinkDto> projectLinks) {
+ public Builder setProjectLinks(List<ProjectLinkDto> projectLinks) {
this.projectLinks = projectLinks;
return this;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/CreateAction.java
index a4c810cbfaa..2730840dde5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/CreateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/CreateAction.java
@@ -23,10 +23,11 @@ import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
+import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.ProjectLinks;
@@ -34,27 +35,30 @@ import org.sonarqube.ws.ProjectLinks.CreateWsResponse;
import static org.sonar.core.util.Slug.slugify;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonar.server.projectlink.ws.ProjectLinksWs.checkProject;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.ACTION_CREATE;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_NAME;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_ID;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_URL;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class CreateAction implements ProjectLinksWsAction {
private final DbClient dbClient;
private final UserSession userSession;
private final ComponentFinder componentFinder;
+ private final UuidFactory uuidFactory;
private static final int LINK_NAME_MAX_LENGTH = 128;
private static final int LINK_URL_MAX_LENGTH = 2048;
private static final int LINK_TYPE_MAX_LENGTH = 20;
- public CreateAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
+ public CreateAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder, UuidFactory uuidFactory) {
this.dbClient = dbClient;
this.userSession = userSession;
this.componentFinder = componentFinder;
+ this.uuidFactory = uuidFactory;
}
@Override
@@ -101,25 +105,26 @@ public class CreateAction implements ProjectLinksWsAction {
String url = createWsRequest.getUrl();
try (DbSession dbSession = dbClient.openSession(false)) {
- ComponentDto component = getComponentByUuidOrKey(dbSession, createWsRequest);
+ ComponentDto component = checkProject(getComponentByUuidOrKey(dbSession, createWsRequest));
userSession.checkComponentPermission(UserRole.ADMIN, component);
- ComponentLinkDto link = new ComponentLinkDto()
- .setComponentUuid(component.uuid())
+ ProjectLinkDto link = new ProjectLinkDto()
+ .setUuid(uuidFactory.create())
+ .setProjectUuid(component.uuid())
.setName(name)
.setHref(url)
.setType(nameToType(name));
- dbClient.componentLinkDao().insert(dbSession, link);
+ dbClient.projectLinkDao().insert(dbSession, link);
dbSession.commit();
return buildResponse(link);
}
}
- private static CreateWsResponse buildResponse(ComponentLinkDto link) {
+ private static CreateWsResponse buildResponse(ProjectLinkDto link) {
return CreateWsResponse.newBuilder().setLink(ProjectLinks.Link.newBuilder()
- .setId(String.valueOf(link.getId()))
+ .setId(String.valueOf(link.getUuid()))
.setName(link.getName())
.setType(link.getType())
.setUrl(link.getHref()))
@@ -127,7 +132,7 @@ public class CreateAction implements ProjectLinksWsAction {
}
private ComponentDto getComponentByUuidOrKey(DbSession dbSession, CreateRequest request) {
- return componentFinder.getRootComponentByUuidOrKey(
+ return componentFinder.getByUuidOrKey(
dbSession,
request.getProjectId(),
request.getProjectKey(),
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java
index 5dfaeb57bfb..bcba6beb4ed 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java
@@ -25,11 +25,11 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsUtils;
-import static org.sonar.db.component.ComponentLinkDto.PROVIDED_TYPES;
+import static org.sonar.db.component.ProjectLinkDto.PROVIDED_TYPES;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.ACTION_DELETE;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_ID;
@@ -64,27 +64,26 @@ public class DeleteAction implements ProjectLinksWsAction {
response.noContent();
}
- private void doHandle(String idParam) {
+ private void doHandle(String id) {
try (DbSession dbSession = dbClient.openSession(false)) {
- long id = Long.parseLong(idParam);
- ComponentLinkDto link = dbClient.componentLinkDao().selectById(dbSession, id);
+ ProjectLinkDto link = dbClient.projectLinkDao().selectByUuid(dbSession, id);
link = WsUtils.checkFound(link, "Link with id '%s' not found", id);
checkProjectAdminPermission(link);
checkNotProvided(link);
- dbClient.componentLinkDao().delete(dbSession, link.getId());
+ dbClient.projectLinkDao().delete(dbSession, link.getUuid());
dbSession.commit();
}
}
- private static void checkNotProvided(ComponentLinkDto link) {
+ private static void checkNotProvided(ProjectLinkDto link) {
String type = link.getType();
boolean isProvided = type != null && PROVIDED_TYPES.contains(type);
WsUtils.checkRequest(!isProvided, "Provided link cannot be deleted.");
}
- private void checkProjectAdminPermission(ComponentLinkDto link) {
- userSession.checkComponentUuidPermission(UserRole.ADMIN, link.getComponentUuid());
+ private void checkProjectAdminPermission(ProjectLinkDto link) {
+ userSession.checkComponentUuidPermission(UserRole.ADMIN, link.getProjectUuid());
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java
index bcf5ccc4c80..eb2b7fe0add 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/ProjectLinksWs.java
@@ -19,7 +19,13 @@
*/
package org.sonar.server.projectlink.ws;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Scopes;
import org.sonar.api.server.ws.WebService;
+import org.sonar.db.component.ComponentDto;
+
+import static java.lang.String.format;
+import static org.sonar.server.ws.WsUtils.checkRequest;
public class ProjectLinksWs implements WebService {
@@ -42,4 +48,10 @@ public class ProjectLinksWs implements WebService {
controller.done();
}
+ static ComponentDto checkProject(ComponentDto component) {
+ checkRequest(component.scope().equals(Scopes.PROJECT) && component.qualifier().equals(Qualifiers.PROJECT),
+ format("Component '%s' must be a project.", component.getKey()));
+ return component;
+ }
+
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java
index 5de432d37aa..2548fd3876f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/projectlink/ws/SearchAction.java
@@ -28,7 +28,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.ProjectLinks.Link;
@@ -36,12 +36,13 @@ import org.sonarqube.ws.ProjectLinks.SearchWsResponse;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonar.server.projectlink.ws.ProjectLinksWs.checkProject;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.ACTION_SEARCH;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_ID;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
+import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class SearchAction implements ProjectLinksWsAction {
private final DbClient dbClient;
@@ -67,7 +68,7 @@ public class SearchAction implements ProjectLinksWsAction {
"</ul>",
PARAM_PROJECT_ID, PARAM_PROJECT_KEY)
.setHandler(this)
- .setResponseExample(getClass().getResource("list-example.json"))
+ .setResponseExample(getClass().getResource("search-example.json"))
.setSince("6.1");
action.createParam(PARAM_PROJECT_ID)
@@ -90,13 +91,13 @@ public class SearchAction implements ProjectLinksWsAction {
private SearchWsResponse doHandle(SearchRequest searchWsRequest) {
try (DbSession dbSession = dbClient.openSession(false)) {
ComponentDto component = getComponentByUuidOrKey(dbSession, searchWsRequest);
- List<ComponentLinkDto> links = dbClient.componentLinkDao()
- .selectByComponentUuid(dbSession, component.uuid());
+ List<ProjectLinkDto> links = dbClient.projectLinkDao()
+ .selectByProjectUuid(dbSession, component.uuid());
return buildResponse(links);
}
}
- private static SearchWsResponse buildResponse(List<ComponentLinkDto> links) {
+ private static SearchWsResponse buildResponse(List<ProjectLinkDto> links) {
return SearchWsResponse.newBuilder()
.addAllLinks(links.stream()
.map(SearchAction::buildLink)
@@ -104,28 +105,26 @@ public class SearchAction implements ProjectLinksWsAction {
.build();
}
- private static Link buildLink(ComponentLinkDto link) {
+ private static Link buildLink(ProjectLinkDto link) {
Link.Builder builder = Link.newBuilder()
- .setId(String.valueOf(link.getId()))
+ .setId(String.valueOf(link.getUuid()))
+ .setType(link.getType())
.setUrl(link.getHref());
setNullable(link.getName(), builder::setName);
- setNullable(link.getType(), builder::setType);
return builder.build();
}
private ComponentDto getComponentByUuidOrKey(DbSession dbSession, SearchRequest request) {
- ComponentDto component = componentFinder.getRootComponentByUuidOrKey(
+ ComponentDto component = componentFinder.getByUuidOrKey(
dbSession,
request.getProjectId(),
request.getProjectKey(),
ComponentFinder.ParamNames.PROJECT_ID_AND_KEY);
-
if (!userSession.hasComponentPermission(UserRole.ADMIN, component) &&
!userSession.hasComponentPermission(UserRole.USER, component)) {
throw insufficientPrivilegesException();
}
-
- return component;
+ return checkProject(component);
}
private static SearchRequest toSearchWsRequest(Request request) {
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json b/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/search-example.json
index 8638919d9a0..5f0afb8c2db 100644
--- a/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/list-example.json
+++ b/server/sonar-server/src/main/resources/org/sonar/server/projectlink/ws/search-example.json
@@ -9,6 +9,7 @@
{
"id": "2",
"name": "Custom",
+ "type": "custom",
"url": "http://example.org/custom"
}
]
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest.java
index 9b13a24ea77..b13cc434b1a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest.java
@@ -19,32 +19,37 @@
*/
package org.sonar.server.computation.task.projectanalysis.step;
-import java.util.Locale;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.i18n.I18n;
+import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
-import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
-import org.sonar.server.computation.task.projectanalysis.component.VisitException;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.step.ComputationStep;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType.CI;
+import static org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType.HOME;
+import static org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType.ISSUE;
+import static org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType.SCM;
+import static org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType.SCM_DEV;
public class PersistProjectLinksStepTest extends BaseStepTest {
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@@ -52,19 +57,7 @@ public class PersistProjectLinksStepTest extends BaseStepTest {
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
- PersistProjectLinksStep step;
-
- @Before
- public void setup() {
- I18n i18n = mock(I18n.class);
- when(i18n.message(Locale.ENGLISH, "project_links.homepage", null)).thenReturn("Home");
- when(i18n.message(Locale.ENGLISH, "project_links.scm", null)).thenReturn("Sources");
- when(i18n.message(Locale.ENGLISH, "project_links.scm_dev", null)).thenReturn("Developer connection");
- when(i18n.message(Locale.ENGLISH, "project_links.ci", null)).thenReturn("Continuous integration");
- when(i18n.message(Locale.ENGLISH, "project_links.issue", null)).thenReturn("Issues");
-
- step = new PersistProjectLinksStep(dbTester.getDbClient(), i18n, treeRootHolder, reportReader);
- }
+ PersistProjectLinksStep step = new PersistProjectLinksStep(db.getDbClient(), treeRootHolder, reportReader, UuidFactoryFast.getInstance());
@Override
protected ComputationStep step() {
@@ -72,56 +65,78 @@ public class PersistProjectLinksStepTest extends BaseStepTest {
}
@Test
- public void add_links_on_project_and_module() {
- dbTester.prepareDbUnit(getClass(), "empty.xml");
-
+ public void add_links_on_project() {
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").addChildren(
ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").build())
.build());
- // project and 1 module
+ // project
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ComponentType.PROJECT)
.addChildRef(2)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.SCM).setHref("https://github.com/SonarSource/sonar").build())
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.SCM_DEV).setHref("scm:git:git@github.com:SonarSource/sonar.git/sonar").build())
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.ISSUE).setHref("http://jira.sonarsource.com/").build())
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.CI).setHref("http://bamboo.ci.codehaus.org/browse/SONAR").build())
- .build());
- reportReader.putComponent(ScannerReport.Component.newBuilder()
- .setRef(2)
- .setType(ComponentType.MODULE)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.SCM).setHref("https://github.com/SonarSource/sonar/server").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(SCM).setHref("https://github.com/SonarSource/sonar").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(SCM_DEV).setHref("scm:git:git@github.com:SonarSource/sonar.git/sonar").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(ISSUE).setHref("http://jira.sonarsource.com/").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(CI).setHref("http://bamboo.ci.codehaus.org/browse/SONAR").build())
.build());
step.execute();
- dbTester.assertDbUnit(getClass(), "add_links_on_project_and_module-result.xml", "project_links");
+ assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+ .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref, ProjectLinkDto::getName)
+ .containsExactlyInAnyOrder(
+ tuple("homepage", "http://www.sonarqube.org", null),
+ tuple("scm", "https://github.com/SonarSource/sonar", null),
+ tuple("scm_dev", "scm:git:git@github.com:SonarSource/sonar.git/sonar", null),
+ tuple("issue", "http://jira.sonarsource.com/", null),
+ tuple("ci", "http://bamboo.ci.codehaus.org/browse/SONAR", null));
}
@Test
public void nothing_to_do_when_link_already_exists() {
- dbTester.prepareDbUnit(getClass(), "nothing_to_do_when_link_already_exists.xml");
+ ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD"));
+ db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonarqube.org"));
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ComponentType.PROJECT)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
.build());
step.execute();
- dbTester.assertDbUnit(getClass(), "nothing_to_do_when_link_already_exists.xml", "project_links");
+ assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+ .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref)
+ .containsExactlyInAnyOrder(tuple("homepage", "http://www.sonarqube.org"));
}
@Test
- public void do_not_add_links_on_file() {
- dbTester.prepareDbUnit(getClass(), "empty.xml");
+ public void do_not_add_links_on_module() {
+ treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").addChildren(
+ ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").build())
+ .build());
+ reportReader.putComponent(ScannerReport.Component.newBuilder()
+ .setRef(1)
+ .setType(ComponentType.PROJECT)
+ .addChildRef(2)
+ .build());
+ reportReader.putComponent(ScannerReport.Component.newBuilder()
+ .setRef(2)
+ .setType(ComponentType.MODULE)
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
+ .build());
+ step.execute();
+
+ assertThat(db.countRowsOfTable("project_links")).isZero();
+ }
+
+ @Test
+ public void do_not_add_links_on_file() {
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").addChildren(
ReportComponent.builder(Component.Type.FILE, 2).setUuid("BCDE").build())
.build());
@@ -134,34 +149,38 @@ public class PersistProjectLinksStepTest extends BaseStepTest {
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(2)
.setType(ComponentType.FILE)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
.build());
step.execute();
- assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
+ assertThat(db.countRowsOfTable("project_links")).isZero();
}
@Test
public void update_link() {
- dbTester.prepareDbUnit(getClass(), "update_link.xml");
+ ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD"));
+ db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonar.org"));
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ComponentType.PROJECT)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
.build());
step.execute();
- dbTester.assertDbUnit(getClass(), "update_link-result.xml", "project_links");
+ assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+ .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref)
+ .containsExactlyInAnyOrder(tuple("homepage", "http://www.sonarqube.org"));
}
@Test
public void delete_link() {
- dbTester.prepareDbUnit(getClass(), "delete_link.xml");
+ ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD"));
+ db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonar.org"));
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
@@ -172,12 +191,13 @@ public class PersistProjectLinksStepTest extends BaseStepTest {
step.execute();
- assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
+ assertThat(db.countRowsOfTable("project_links")).isZero();
}
@Test
public void not_delete_custom_link() {
- dbTester.prepareDbUnit(getClass(), "not_delete_custom_link.xml");
+ ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD"));
+ db.componentLinks().insertCustomLink(project);
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
@@ -188,28 +208,23 @@ public class PersistProjectLinksStepTest extends BaseStepTest {
step.execute();
- dbTester.assertDbUnit(getClass(), "not_delete_custom_link.xml", "project_links");
+ assertThat(db.countRowsOfTable("project_links")).isEqualTo(1);
}
@Test
public void fail_when_trying_to_add_same_link_type_multiple_times() {
- dbTester.prepareDbUnit(getClass(), "empty.xml");
-
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ComponentType.PROJECT)
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
- .addLink(ScannerReport.ComponentLink.newBuilder().setType(ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
+ .addLink(ScannerReport.ComponentLink.newBuilder().setType(HOME).setHref("http://www.sonarqube.org").build())
.build());
- try {
- step.execute();
- failBecauseExceptionWasNotThrown(VisitException.class);
- } catch (VisitException e) {
- assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
- assertThat(e.getCause()).hasMessage("Link of type 'homepage' has already been declared on component 'ABCD'");
- }
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Link of type 'homepage' has already been declared on component 'ABCD'");
+
+ step.execute();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
index e9551d7315c..bcb8a89785b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/SearchMyProjectsActionTest.java
@@ -34,8 +34,8 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
@@ -87,10 +87,8 @@ public class SearchMyProjectsActionTest {
OrganizationDto organizationDto = db.organizations().insert();
ComponentDto jdk7 = insertJdk7(organizationDto);
ComponentDto cLang = insertClang(organizationDto);
- dbClient.componentLinkDao().insert(dbSession,
- new ComponentLinkDto().setComponentUuid(jdk7.uuid()).setHref("http://www.oracle.com").setType(ComponentLinkDto.TYPE_HOME_PAGE).setName("Home"));
- dbClient.componentLinkDao().insert(dbSession,
- new ComponentLinkDto().setComponentUuid(jdk7.uuid()).setHref("http://download.java.net/openjdk/jdk8/").setType(ComponentLinkDto.TYPE_SOURCES).setName("Sources"));
+ db.componentLinks().insertProvidedLink(jdk7, l -> l.setHref("http://www.oracle.com").setType(ProjectLinkDto.TYPE_HOME_PAGE).setName("Home"));
+ db.componentLinks().insertProvidedLink(jdk7, l -> l.setHref("http://download.java.net/openjdk/jdk8/").setType(ProjectLinkDto.TYPE_SOURCES).setName("Sources"));
long oneTime = DateUtils.parseDateTime("2016-06-10T13:17:53+0000").getTime();
long anotherTime = DateUtils.parseDateTime("2016-06-11T14:25:53+0000").getTime();
SnapshotDto jdk7Snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(jdk7).setCreatedAt(oneTime));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/CreateActionTest.java
index c97eaedbb19..ed689e9649b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/CreateActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/CreateActionTest.java
@@ -19,23 +19,22 @@
*/
package org.sonar.server.projectlink.ws;
-import java.io.IOException;
import java.util.Random;
import org.apache.commons.lang.StringUtils;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
@@ -47,19 +46,14 @@ import org.sonarqube.ws.ProjectLinks;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.test.JsonAssert.assertJson;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_NAME;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_ID;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_URL;
+import static org.sonar.test.JsonAssert.assertJson;
public class CreateActionTest {
- private final String PROJECT_KEY = KEY_PROJECT_EXAMPLE_001;
- private final String PROJECT_UUID = UUID_EXAMPLE_01;
-
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
@@ -70,20 +64,11 @@ public class CreateActionTest {
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
- private WsActionTester ws;
-
- private CreateAction underTest;
-
- @Before
- public void setUp() {
- ComponentFinder componentFinder = TestComponentFinder.from(db);
- underTest = new CreateAction(dbClient, userSession, componentFinder);
- ws = new WsActionTester(underTest);
- }
+ private WsActionTester ws = new WsActionTester(new CreateAction(dbClient, userSession, TestComponentFinder.from(db), UuidFactoryFast.getInstance()));
@Test
public void example_with_key() {
- ComponentDto project = insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
logInAsProjectAdministrator(project);
String result = ws.newRequest()
@@ -98,7 +83,7 @@ public class CreateActionTest {
@Test
public void example_with_id() {
- ComponentDto project = insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
logInAsProjectAdministrator(project);
String result = ws.newRequest()
@@ -112,19 +97,20 @@ public class CreateActionTest {
}
@Test
- public void require_project_admin() throws IOException {
- ComponentDto project = insertProject();
+ public void require_project_admin() {
+ ComponentDto project = db.components().insertPrivateProject();
logInAsProjectAdministrator(project);
+
createAndTest(project);
}
@Test
- public void with_long_name() throws IOException {
- ComponentDto project = insertProject();
+ public void with_long_name() {
+ ComponentDto project = db.components().insertPrivateProject();
logInAsProjectAdministrator(project);
-
String longName = StringUtils.leftPad("", 60, "a");
String expectedType = StringUtils.leftPad("", 20, "a");
+
createAndTest(project, longName, "http://example.org", expectedType);
}
@@ -180,11 +166,13 @@ public class CreateActionTest {
@Test
public void fail_if_anonymous() {
userSession.anonymous();
- insertProject();
+ ComponentDto project = db.components().insertPublicProject();
+ userSession.registerComponents(project);
expectedException.expect(ForbiddenException.class);
+
ws.newRequest()
- .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .setParam(PARAM_PROJECT_KEY, project.getKey())
.setParam(PARAM_NAME, "Custom")
.setParam(PARAM_URL, "http://example.org")
.execute();
@@ -193,11 +181,12 @@ public class CreateActionTest {
@Test
public void fail_if_not_project_admin() {
userSession.logIn();
- insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
expectedException.expect(ForbiddenException.class);
+
ws.newRequest()
- .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .setParam(PARAM_PROJECT_KEY, project.getKey())
.setParam(PARAM_NAME, "Custom")
.setParam(PARAM_URL, "http://example.org")
.execute();
@@ -225,10 +214,9 @@ public class CreateActionTest {
}
@Test
- public void fail_if_subview() {
+ public void fail_if_view() {
ComponentDto view = db.components().insertView();
- ComponentDto subview = db.components().insertComponent(ComponentTesting.newSubView(view));
- failIfNotAProject(view, subview);
+ failIfNotAProject(view, view);
}
@Test
@@ -239,7 +227,7 @@ public class CreateActionTest {
ComponentDto branch = db.components().insertProjectBranch(project);
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Project key '%s' not found", branch.getDbKey()));
+ expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
ws.newRequest()
.setParam(PARAM_PROJECT_KEY, branch.getDbKey())
@@ -256,7 +244,7 @@ public class CreateActionTest {
ComponentDto branch = db.components().insertProjectBranch(project);
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Project id '%s' not found", branch.uuid()));
+ expectedException.expectMessage(format("Component id '%s' not found", branch.uuid()));
ws.newRequest()
.setParam(PARAM_PROJECT_ID, branch.uuid())
@@ -265,11 +253,21 @@ public class CreateActionTest {
.execute();
}
+ @Test
+ public void define_create_action() {
+ WebService.Action action = ws.getDef();
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isTrue();
+ assertThat(action.handler()).isNotNull();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params()).hasSize(4);
+ }
+
private void failIfNotAProject(ComponentDto root, ComponentDto component) {
userSession.logIn().addProjectPermission(UserRole.ADMIN, root);
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Component '" + component.getDbKey() + "' (id: " + component.uuid() + ") must be a project");
+ expectedException.expectMessage("Component '" + component.getDbKey() + "' must be a project");
TestRequest testRequest = ws.newRequest();
if (new Random().nextBoolean()) {
@@ -283,12 +281,6 @@ public class CreateActionTest {
.execute();
}
- private ComponentDto insertProject() {
- OrganizationDto org = db.organizations().insert();
- return db.components().insertComponent(
- ComponentTesting.newPrivateProjectDto(org, PROJECT_UUID).setDbKey(PROJECT_KEY));
- }
-
private void createAndTest(ComponentDto project, String name, String url, String type) {
ProjectLinks.CreateWsResponse response = ws.newRequest()
.setMethod("POST")
@@ -297,15 +289,15 @@ public class CreateActionTest {
.setParam(PARAM_URL, url)
.executeProtobuf(ProjectLinks.CreateWsResponse.class);
- long newId = Long.valueOf(response.getLink().getId());
+ String newId = response.getLink().getId();
- ComponentLinkDto link = dbClient.componentLinkDao().selectById(dbSession, newId);
+ ProjectLinkDto link = dbClient.projectLinkDao().selectByUuid(dbSession, newId);
assertThat(link.getName()).isEqualTo(name);
assertThat(link.getHref()).isEqualTo(url);
assertThat(link.getType()).isEqualTo(type);
}
- private void createAndTest(ComponentDto project) throws IOException {
+ private void createAndTest(ComponentDto project) {
createAndTest(project, "Custom", "http://example.org", "custom");
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/DeleteActionTest.java
index 6b990660466..eee39643a1b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/DeleteActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/DeleteActionTest.java
@@ -19,18 +19,16 @@
*/
package org.sonar.server.projectlink.ws;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
@@ -39,15 +37,11 @@ import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_ID;
public class DeleteActionTest {
- private static final String PROJECT_KEY = KEY_PROJECT_EXAMPLE_001;
- private static final String PROJECT_UUID = UUID_EXAMPLE_01;
-
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
@@ -57,155 +51,115 @@ public class DeleteActionTest {
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
- private ComponentDbTester componentDb = new ComponentDbTester(db);
-
- private WsActionTester ws;
-
- private DeleteAction underTest;
- @Before
- public void setUp() {
- underTest = new DeleteAction(dbClient, userSession);
- ws = new WsActionTester(underTest);
- }
+ private WsActionTester ws = new WsActionTester(new DeleteAction(dbClient, userSession));
@Test
public void no_response() {
- ComponentDto project = insertProject();
- ComponentLinkDto link = insertCustomLink(project.uuid());
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
logInAsProjectAdministrator(project);
- TestResponse response = deleteLink(link.getId());
+ TestResponse response = deleteLink(link);
assertThat(response.getStatus()).isEqualTo(204);
assertThat(response.getInput()).isEmpty();
}
@Test
- public void actual_removal() {
- ComponentDto project = insertProject();
- ComponentLinkDto link = insertCustomLink(project.uuid());
- long id = link.getId();
+ public void remove_custom_link() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
logInAsProjectAdministrator(project);
- deleteLink(id);
- assertLinkIsDeleted(id);
+ deleteLink(link);
+
+ assertLinkIsDeleted(link.getUuid());
}
@Test
public void keep_links_of_another_project() {
- ComponentDto project1 = insertProject();
- ComponentDto project2 = insertProject("another", "abcd");
- ComponentLinkDto customLink1 = insertCustomLink(project1.uuid());
- ComponentLinkDto customLink2 = insertCustomLink(project2.uuid());
- Long id1 = customLink1.getId();
- Long id2 = customLink2.getId();
- userSession.logIn().addProjectPermission(UserRole.ADMIN, project1, project2);
-
- deleteLink(id1);
- assertLinkIsDeleted(id1);
- assertLinkIsNotDeleted(id2);
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ ProjectLinkDto customLink1 = db.componentLinks().insertCustomLink(project1);
+ ProjectLinkDto customLink2 = db.componentLinks().insertCustomLink(project2);
+ userSession.logIn().addProjectPermission(ADMIN, project1, project2);
+
+ deleteLink(customLink1);
+
+ assertLinkIsDeleted(customLink1.getUuid());
+ assertLinkIsNotDeleted(customLink2.getUuid());
}
@Test
public void fail_when_delete_provided_link() {
- ComponentDto project = insertProject();
- ComponentLinkDto link = insertHomepageLink(project.uuid());
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
logInAsProjectAdministrator(project);
expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("Provided link cannot be deleted");
- deleteLink(link.getId());
+ deleteLink(link);
}
@Test
- public void fail_when_no_link() {
+ public void fail_on_unknown_link() {
expectedException.expect(NotFoundException.class);
- deleteLink("175");
+ ws.newRequest()
+ .setMethod("POST")
+ .setParam(PARAM_ID, "UNKNOWN")
+ .execute();
}
@Test
public void fail_if_anonymous() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
userSession.anonymous();
- ComponentDto project = insertProject();
- ComponentLinkDto link = insertCustomLink(project.uuid());
-
expectedException.expect(ForbiddenException.class);
- deleteLink(link.getId());
+ deleteLink(link);
}
@Test
public void fail_if_not_project_admin() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
userSession.logIn();
- ComponentDto project = insertProject();
- ComponentLinkDto link = insertCustomLink(project.uuid());
-
expectedException.expect(ForbiddenException.class);
- deleteLink(link.getId());
+ deleteLink(link);
}
- private ComponentDto insertProject(String projectKey, String projectUuid) {
- return componentDb.insertComponent(new ComponentDto()
- .setOrganizationUuid("org1")
- .setUuid(projectUuid)
- .setDbKey(projectKey)
- .setUuidPath("")
- .setRootUuid("")
- .setProjectUuid(""));
- }
-
- private ComponentDto insertProject() {
- return insertProject(PROJECT_KEY, PROJECT_UUID);
- }
-
- private void insertLink(ComponentLinkDto linkDto) {
- dbClient.componentLinkDao().insert(dbSession, linkDto);
- dbSession.commit();
- }
-
- private ComponentLinkDto insertHomepageLink(String projectUuid) {
- ComponentLinkDto link = new ComponentLinkDto()
- .setComponentUuid(projectUuid)
- .setName("Homepage")
- .setType("homepage")
- .setHref("http://example.org");
- insertLink(link);
- return link;
- }
-
- private ComponentLinkDto insertCustomLink(String projectUuid) {
- ComponentLinkDto link = new ComponentLinkDto()
- .setComponentUuid(projectUuid)
- .setName("Custom")
- .setHref("http://example.org/custom");
- insertLink(link);
- return link;
+ @Test
+ public void define_delete_action() {
+ WebService.Action action = ws.getDef();
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isTrue();
+ assertThat(action.handler()).isNotNull();
+ assertThat(action.responseExample()).isNull();
+ assertThat(action.params()).hasSize(1);
}
- private TestResponse deleteLink(String id) {
+ private TestResponse deleteLink(ProjectLinkDto link) {
return ws.newRequest()
.setMethod("POST")
- .setParam(PARAM_ID, id)
+ .setParam(PARAM_ID, link.getUuid())
.execute();
}
- private TestResponse deleteLink(Long id) {
- return deleteLink(String.valueOf(id));
- }
-
- private void assertLinkIsDeleted(Long id) {
- assertThat(dbClient.componentLinkDao().selectById(dbSession, id)).isNull();
+ private void assertLinkIsDeleted(String uuid) {
+ assertThat(dbClient.projectLinkDao().selectByUuid(dbSession, uuid)).isNull();
}
- private void assertLinkIsNotDeleted(Long id) {
- assertThat(dbClient.componentLinkDao().selectById(dbSession, id)).isNotNull();
+ private void assertLinkIsNotDeleted(String uuid) {
+ assertThat(dbClient.projectLinkDao().selectByUuid(dbSession, uuid)).isNotNull();
}
private void logInAsProjectAdministrator(ComponentDto project) {
- userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+ userSession.logIn().addProjectPermission(ADMIN, project);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java
deleted file mode 100644
index 38bc02d6ca4..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/ProjectLinksWsTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.projectlink.ws;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class ProjectLinksWsTest {
-
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
- WebService.Controller controller;
-
- @Before
- public void setUp() {
- WsTester tester = new WsTester(new ProjectLinksWs(
- new SearchAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
- new CreateAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
- new DeleteAction(mock(DbClient.class), userSessionRule)
- ));
- controller = tester.controller("api/project_links");
- }
-
- @Test
- public void define_controller() {
- assertThat(controller).isNotNull();
- assertThat(controller.description()).isNotEmpty();
- assertThat(controller.since()).isEqualTo("6.1");
- assertThat(controller.actions()).hasSize(3);
- }
-
- @Test
- public void define_search_action() {
- WebService.Action action = controller.action("search");
- assertThat(action).isNotNull();
- assertThat(action.isPost()).isFalse();
- assertThat(action.handler()).isNotNull();
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(2);
- }
-
- @Test
- public void define_create_action() {
- WebService.Action action = controller.action("create");
- assertThat(action).isNotNull();
- assertThat(action.isPost()).isTrue();
- assertThat(action.handler()).isNotNull();
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(4);
- }
-
- @Test
- public void define_delete_action() {
- WebService.Action action = controller.action("delete");
- assertThat(action).isNotNull();
- assertThat(action.isPost()).isTrue();
- assertThat(action.handler()).isNotNull();
- assertThat(action.responseExample()).isNull();
- assertThat(action.params()).hasSize(1);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java
index 6d288e3b487..8974e886bb5 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/projectlink/ws/SearchActionTest.java
@@ -19,23 +19,19 @@
*/
package org.sonar.server.projectlink.ws;
-import java.io.IOException;
import java.util.Random;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectLinkDto;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
@@ -49,18 +45,12 @@ import org.sonarqube.ws.ProjectLinks.SearchWsResponse;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.test.JsonAssert.assertJson;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_ID;
import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_PROJECT_KEY;
+import static org.sonar.test.JsonAssert.assertJson;
public class SearchActionTest {
- private final String PROJECT_KEY = KEY_PROJECT_EXAMPLE_001;
- private final String PROJECT_UUID = UUID_EXAMPLE_01;
-
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
@@ -69,125 +59,120 @@ public class SearchActionTest {
public DbTester db = DbTester.create(System2.INSTANCE);
private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
- private ComponentDbTester componentDb = new ComponentDbTester(db);
-
- private SearchAction underTest;
- private WsActionTester ws;
- @Before
- public void setUp() {
- ComponentFinder componentFinder = TestComponentFinder.from(db);
- underTest = new SearchAction(dbClient, userSession, componentFinder);
- ws = new WsActionTester(underTest);
- }
+ private WsActionTester ws = new WsActionTester(new SearchAction(dbClient, userSession, TestComponentFinder.from(db)));
@Test
public void example() {
- ComponentDto project = insertProject();
- insertHomepageLink(project.uuid());
- insertCustomLink(project.uuid());
+ ComponentDto project = db.components().insertPrivateProject();
+ db.componentLinks().insertProvidedLink(project, l -> l.setUuid("1").setType("homepage").setName("Homepage").setHref("http://example.org"));
+ db.componentLinks().insertCustomLink(project, l -> l.setUuid("2").setType("custom").setName("Custom").setHref("http://example.org/custom"));
logInAsProjectAdministrator(project);
String result = ws.newRequest()
- .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
+ .setParam(PARAM_PROJECT_KEY, project.getKey())
.execute().getInput();
- assertJson(result).ignoreFields("id").isSimilarTo(getClass().getResource("list-example.json"));
+ assertJson(result).isSimilarTo(getClass().getResource("search-example.json"));
}
@Test
- public void request_by_project_id() throws IOException {
- ComponentDto project = insertProject();
- insertHomepageLink(project.uuid());
+ public void request_by_project_id() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
logInAsProjectAdministrator(project);
SearchWsResponse response = callByUuid(project.uuid());
- assertThat(response.getLinksCount()).isEqualTo(1);
- assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::getName)
+ .containsExactlyInAnyOrder(tuple(link.getUuid(), link.getName()));
}
@Test
- public void request_by_project_key() throws IOException {
- ComponentDto project = insertProject();
- insertHomepageLink(project.uuid());
+ public void request_by_project_key() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
logInAsProjectAdministrator(project);
- SearchWsResponse response = callByKey(project.getDbKey());
+ SearchWsResponse response = callByKey(project.getKey());
- assertThat(response.getLinksCount()).isEqualTo(1);
- assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::getName)
+ .containsExactlyInAnyOrder(tuple(link.getUuid(), link.getName()));
}
@Test
- public void response_fields() throws IOException {
- ComponentDto project = insertProject();
- ComponentLinkDto homepageLink = insertHomepageLink(project.uuid());
- ComponentLinkDto customLink = insertCustomLink(project.uuid());
+ public void response_fields() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto homepageLink = db.componentLinks().insertProvidedLink(project);
+ ProjectLinkDto customLink = db.componentLinks().insertCustomLink(project);
logInAsProjectAdministrator(project);
- SearchWsResponse response = callByKey(project.getDbKey());
+ SearchWsResponse response = callByKey(project.getKey());
- assertThat(response.getLinksCount()).isEqualTo(2);
assertThat(response.getLinksList()).extracting(Link::getId, Link::getName, Link::getType, Link::getUrl)
- .containsOnlyOnce(
- tuple(homepageLink.getIdAsString(), homepageLink.getName(), homepageLink.getType(), homepageLink.getHref()),
- tuple(customLink.getIdAsString(), customLink.getName(), customLink.getType(), customLink.getHref()));
+ .containsExactlyInAnyOrder(
+ tuple(homepageLink.getUuid(), "", homepageLink.getType(), homepageLink.getHref()),
+ tuple(customLink.getUuid(), customLink.getName(), customLink.getType(), customLink.getHref()));
}
@Test
- public void several_projects() throws IOException {
- ComponentDto project1 = insertProject();
- ComponentDto project2 = insertProject("another", "abcd");
- ComponentLinkDto customLink1 = insertCustomLink(project1.uuid());
- insertCustomLink(project2.uuid());
+ public void several_projects() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+ ProjectLinkDto link1 = db.componentLinks().insertCustomLink(project1);
+ ProjectLinkDto link2 = db.componentLinks().insertCustomLink(project2);
userSession.logIn().setRoot();
- SearchWsResponse response = callByKey(project1.getDbKey());
+ SearchWsResponse response = callByKey(project1.getKey());
- assertThat(response.getLinksCount()).isEqualTo(1);
- assertThat(response.getLinks(0).getId()).isEqualTo(customLink1.getIdAsString());
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::getName)
+ .containsExactlyInAnyOrder(tuple(link1.getUuid(), link1.getName()));
}
@Test
- public void request_does_not_fail_when_link_has_no_name() throws IOException {
+ public void request_does_not_fail_when_link_has_no_name() {
ComponentDto project = db.components().insertPrivateProject();
- ComponentLinkDto foo = new ComponentLinkDto().setComponentUuid(project.uuid()).setHref("foo").setType("type");
- insertLink(foo);
+ ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
logInAsProjectAdministrator(project);
- callByKey(project.getDbKey());
- }
-
- @Test
- public void request_does_not_fail_when_link_has_no_type() throws IOException {
- ComponentDto project = db.components().insertPrivateProject();
- ComponentLinkDto foo = new ComponentLinkDto().setComponentUuid(project.uuid()).setHref("foo").setName("name");
- insertLink(foo);
- logInAsProjectAdministrator(project);
+ SearchWsResponse response = callByKey(project.getKey());
- callByKey(project.getDbKey());
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::hasName)
+ .containsExactlyInAnyOrder(tuple(link.getUuid(), false));
}
@Test
- public void project_administrator_can_search_for_links() throws IOException {
- ComponentDto project = insertProject();
+ public void project_administrator_can_search_for_links() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
- checkItWorks(project);
+ SearchWsResponse response = callByKey(project.getKey());
+
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::getName)
+ .containsExactlyInAnyOrder(tuple(link.getUuid(), link.getName()));
}
@Test
- public void project_user_can_search_for_links() throws IOException {
- ComponentDto project = insertProject();
+ public void project_user_can_search_for_links() {
+ ComponentDto project = db.components().insertPrivateProject();
+ ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
userSession.logIn().addProjectPermission(UserRole.USER, project);
- checkItWorks(project);
+ SearchWsResponse response = callByKey(project.getKey());
+
+ assertThat(response.getLinksList())
+ .extracting(Link::getId, Link::getName)
+ .containsExactlyInAnyOrder(tuple(link.getUuid(), link.getName()));
}
@Test
- public void fail_when_no_project() throws IOException {
+ public void fail_when_no_project() {
expectedException.expect(NotFoundException.class);
callByKey("unknown");
}
@@ -214,56 +199,41 @@ public class SearchActionTest {
}
@Test
- public void fail_if_subview() {
+ public void fail_if_view() {
ComponentDto view = db.components().insertView();
- ComponentDto subview = db.components().insertComponent(ComponentTesting.newSubView(view));
- failIfNotAProject(view, subview);
- }
-
- private void failIfNotAProject(ComponentDto root, ComponentDto component) {
- userSession.logIn().addProjectPermission(UserRole.ADMIN, root);
-
- expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Component '" + component.getDbKey() + "' (id: " + component.uuid() + ") must be a project");
-
- TestRequest testRequest = ws.newRequest();
- if (new Random().nextBoolean()) {
- testRequest.setParam(PARAM_PROJECT_KEY, component.getDbKey());
- } else {
- testRequest.setParam(PARAM_PROJECT_ID, component.uuid());
- }
- testRequest.execute();
+ failIfNotAProject(view, view);
}
@Test
- public void fail_if_insufficient_privileges() throws IOException {
+ public void fail_if_insufficient_privileges() {
userSession.anonymous();
- insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
expectedException.expect(ForbiddenException.class);
- callByKey(PROJECT_KEY);
+
+ callByKey(project.getKey());
}
@Test
public void fail_when_both_id_and_key_are_provided() {
- ComponentDto project = insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
logInAsProjectAdministrator(project);
expectedException.expect(IllegalArgumentException.class);
ws.newRequest()
- .setParam(PARAM_PROJECT_KEY, project.getDbKey())
+ .setParam(PARAM_PROJECT_KEY, project.getKey())
.setParam(PARAM_PROJECT_ID, project.uuid())
.execute();
}
@Test
public void fail_when_no_id_nor_key_are_provided() {
- insertProject();
+ ComponentDto project = db.components().insertPrivateProject();
expectedException.expect(IllegalArgumentException.class);
ws.newRequest()
- .setParam(PARAM_PROJECT_KEY, PROJECT_KEY)
- .setParam(PARAM_PROJECT_ID, PROJECT_UUID)
+ .setParam(PARAM_PROJECT_KEY, project.getKey())
+ .setParam(PARAM_PROJECT_ID, project.uuid())
.execute();
}
@@ -275,7 +245,7 @@ public class SearchActionTest {
ComponentDto branch = db.components().insertProjectBranch(project);
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Project key '%s' not found", branch.getDbKey()));
+ expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
ws.newRequest()
.setParam(PARAM_PROJECT_KEY, branch.getDbKey())
@@ -290,44 +260,21 @@ public class SearchActionTest {
ComponentDto branch = db.components().insertProjectBranch(project);
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage(format("Project id '%s' not found", branch.uuid()));
+ expectedException.expectMessage(format("Component id '%s' not found", branch.uuid()));
ws.newRequest()
.setParam(PARAM_PROJECT_ID, branch.uuid())
.execute();
}
- private ComponentDto insertProject(String projectKey, String projectUuid) {
- return componentDb.insertComponent(newPrivateProjectDto(db.organizations().insert(), projectUuid).setDbKey(projectKey));
- }
-
- private ComponentDto insertProject() {
- return insertProject(PROJECT_KEY, PROJECT_UUID);
- }
-
- private void insertLink(ComponentLinkDto linkDto) {
- dbClient.componentLinkDao().insert(dbSession, linkDto);
- dbSession.commit();
- }
-
- private ComponentLinkDto insertHomepageLink(String projectUuid) {
- ComponentLinkDto link = new ComponentLinkDto()
- .setComponentUuid(projectUuid)
- .setName("Homepage")
- .setType("homepage")
- .setHref("http://example.org");
- insertLink(link);
- return link;
- }
-
- private ComponentLinkDto insertCustomLink(String projectUuid) {
- ComponentLinkDto link = new ComponentLinkDto()
- .setComponentUuid(projectUuid)
- .setName("Custom")
- .setType("Custom")
- .setHref("http://example.org/custom");
- insertLink(link);
- return link;
+ @Test
+ public void define_search_action() {
+ WebService.Action action = ws.getDef();
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isFalse();
+ assertThat(action.handler()).isNotNull();
+ assertThat(action.responseExampleAsString()).isNotEmpty();
+ assertThat(action.params()).hasSize(2);
}
private SearchWsResponse callByKey(String projectKey) {
@@ -342,14 +289,22 @@ public class SearchActionTest {
.executeProtobuf(SearchWsResponse.class);
}
- private void checkItWorks(ComponentDto project) throws IOException {
- insertHomepageLink(project.uuid());
- SearchWsResponse response = callByKey(project.getDbKey());
- assertThat(response.getLinksCount()).isEqualTo(1);
- assertThat(response.getLinks(0).getName()).isEqualTo("Homepage");
- }
-
private void logInAsProjectAdministrator(ComponentDto project) {
userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
}
+
+ private void failIfNotAProject(ComponentDto root, ComponentDto component) {
+ userSession.logIn().addProjectPermission(UserRole.ADMIN, root);
+
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("Component '" + component.getKey() + "' must be a project");
+
+ TestRequest testRequest = ws.newRequest();
+ if (new Random().nextBoolean()) {
+ testRequest.setParam(PARAM_PROJECT_KEY, component.getDbKey());
+ } else {
+ testRequest.setParam(PARAM_PROJECT_ID, component.uuid());
+ }
+ testRequest.execute();
+ }
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/add_links_on_project_and_module-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/add_links_on_project_and_module-result.xml
deleted file mode 100644
index 008f804103e..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/add_links_on_project_and_module-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
- <project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
- <project_links id="3" component_uuid="ABCD" link_type="scm_dev" name="Developer connection" href="scm:git:git@github.com:SonarSource/sonar.git/sonar"/>
- <project_links id="4" component_uuid="ABCD" link_type="issue" name="Issues" href="http://jira.sonarsource.com/"/>
- <project_links id="5" component_uuid="ABCD" link_type="ci" name="Continuous integration" href="http://bamboo.ci.codehaus.org/browse/SONAR"/>
-
- <project_links id="6" component_uuid="BCDE" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar/server"/>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/delete_link.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/delete_link.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/delete_link.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/empty.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/empty.xml
deleted file mode 100644
index 871dedcb5e9..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/empty.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<dataset>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/not_delete_custom_link.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/not_delete_custom_link.xml
deleted file mode 100644
index 78c6c1dd41a..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/not_delete_custom_link.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="custom" name="custom" href="http://www.custom.org"/>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/nothing_to_do_when_link_already_exists.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/nothing_to_do_when_link_already_exists.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/nothing_to_do_when_link_already_exists.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link-result.xml
deleted file mode 100644
index 8b89e7223ec..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link-result.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
-
-</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link.xml
deleted file mode 100644
index d40281088f3..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/task/projectanalysis/step/PersistProjectLinksStepTest/update_link.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonar.org"/>
-
-</dataset>
diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectLinksTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectLinksTest.java
index a2a63ee87c9..1cbb95dd0e0 100644
--- a/tests/src/test/java/org/sonarqube/tests/project/ProjectLinksTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectLinksTest.java
@@ -50,7 +50,7 @@ public class ProjectLinksTest {
@ClassRule
public static RuleChain ruleChain = RuleChain.outerRule(orchestrator).around(tester);
- private long customLinkId;
+ private String customLinkId;
private String adminUser;
@BeforeClass
@@ -62,7 +62,7 @@ public class ProjectLinksTest {
@Before
public void prepare() {
- customLinkId = Long.parseLong(createCustomLink().getLink().getId());
+ customLinkId = createCustomLink().getLink().getId();
adminUser = tester.users().generateAdministratorOnDefaultOrganization().getLogin();
}
@@ -136,9 +136,9 @@ public class ProjectLinksTest {
.setUrl("http://example.org/custom"));
}
- private void deleteLink(long id) {
+ private void deleteLink(String id) {
try {
- tester.wsClient().projectLinks().delete(new DeleteRequest().setId("" + id));
+ tester.wsClient().projectLinks().delete(new DeleteRequest().setId(id));
} catch (Exception e) {
// fail silently
}