aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-10-02 10:25:35 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-10-02 15:28:17 +0200
commit5725b5108f1c1a507e3134080fa6ba2a31ec069d (patch)
treee1c46ffe799f0ebda808f49b3181a488d8b77aad
parentdd9b60a85b5cb8e76ca29759fb93fc16219b4133 (diff)
downloadsonarqube-5725b5108f1c1a507e3134080fa6ba2a31ec069d.tar.gz
sonarqube-5725b5108f1c1a507e3134080fa6ba2a31ec069d.zip
SONAR-5663 Fix issue when updating provisioned project key
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java97
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java6
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb20
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java25
8 files changed, 154 insertions, 50 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
index 534ae2f4689..c70e96f8541 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
@@ -23,9 +23,11 @@ package org.sonar.server.component;
import com.google.common.collect.ImmutableMap;
import org.sonar.api.ServerComponent;
import org.sonar.api.web.UserRole;
+import org.sonar.core.component.AuthorizedComponentDto;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.resource.ResourceDto;
import org.sonar.core.resource.ResourceKeyUpdaterDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.permission.InternalPermissionService;
@@ -34,6 +36,7 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import java.util.Date;
+import java.util.Map;
public class ComponentService implements ServerComponent {
@@ -50,20 +53,20 @@ public class ComponentService implements ServerComponent {
this.previewCache = previewCache;
}
- public ComponentDto getByKey(String key) {
+ public AuthorizedComponentDto getByKey(String key) {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.componentDao().getByKey(session, key);
+ return dbClient.componentDao().getAuthorizedComponentByKey(key, session);
} finally {
session.close();
}
}
@CheckForNull
- public ComponentDto getNullableByKey(String key) {
+ public AuthorizedComponentDto getNullableByKey(String key) {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.componentDao().getNullableByKey(session, key);
+ return dbClient.componentDao().getNullableAuthorizedComponentByKey(key, session);
} finally {
session.close();
}
@@ -78,16 +81,16 @@ public class ComponentService implements ServerComponent {
DbSession session = dbClient.openSession(false);
try {
- ComponentDto projectOrModule = getByKey(projectOrModuleKey);
- ComponentDto oldRootProject = dbClient.componentDao().getRootProjectByKey(projectOrModuleKey, session);
+ AuthorizedComponentDto projectOrModule = getByKey(projectOrModuleKey);
+ ResourceDto oldRootProject = dbClient.resourceDao().getRootProjectByComponentKey(session, projectOrModuleKey);
resourceKeyUpdaterDao.updateKey(projectOrModule.getId(), newKey);
session.commit();
- ComponentDto newRootProject = dbClient.componentDao().getRootProjectByKey(newKey, session);
- updateIssuesIndex(session, oldRootProject.key(), newRootProject.key());
+ ResourceDto newRootProject = dbClient.resourceDao().getRootProjectByComponentKey(session, newKey);
+ updateIssuesIndex(session, oldRootProject.getKey(), newRootProject.getKey());
- previewCache.reportResourceModification(newRootProject.key());
+ previewCache.reportResourceModification(newRootProject.getKey());
session.commit();
} finally {
@@ -95,17 +98,28 @@ public class ComponentService implements ServerComponent {
}
}
+ public Map<String, String> checkModuleKeysBeforeRenaming(String projectKey, String stringToReplace, String replacementString) {
+ UserSession.get().checkProjectPermission(UserRole.ADMIN, projectKey);
+ DbSession session = dbClient.openSession(false);
+ try {
+ AuthorizedComponentDto project = getByKey(projectKey);
+ return resourceKeyUpdaterDao.checkModuleKeysBeforeRenaming(project.getId(), stringToReplace, replacementString);
+ } finally {
+ session.close();
+ }
+ }
+
public void bulkUpdateKey(String projectKey, String stringToReplace, String replacementString) {
UserSession.get().checkProjectPermission(UserRole.ADMIN, projectKey);
DbSession session = dbClient.openSession(false);
try {
- ComponentDto project = getByKey(projectKey);
+ AuthorizedComponentDto project = getByKey(projectKey);
resourceKeyUpdaterDao.bulkUpdateKey(project.getId(), stringToReplace, replacementString);
session.commit();
- ComponentDto newProject = dbClient.componentDao().getById(project.getId(), session);
+ AuthorizedComponentDto newProject = dbClient.componentDao().getNullableAuthorizedComponentById(project.getId(), session);
updateIssuesIndex(session, projectKey, newProject.key());
previewCache.reportResourceModification(newProject.key());
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
index de8be6e9791..62ad40944e3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
@@ -120,6 +120,10 @@ public class DefaultRubyComponentService implements RubyComponentService {
componentService.updateKey(projectOrModuleKey, newKey);
}
+ public Map<String, String> checkModuleKeysBeforeRenaming(String projectKey, String stringToReplace, String replacementString) {
+ return componentService.checkModuleKeysBeforeRenaming(projectKey, stringToReplace, replacementString);
+ }
+
public void bulkUpdateKey(String projectKey, String stringToReplace, String replacementString) {
componentService.bulkUpdateKey(projectKey, stringToReplace, replacementString);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index 277d7a13070..5fdc07b3fca 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -34,7 +34,6 @@ import org.sonar.api.web.*;
import org.sonar.core.persistence.Database;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.resource.ResourceIndexerDao;
-import org.sonar.core.resource.ResourceKeyUpdaterDao;
import org.sonar.core.timemachine.Periods;
import org.sonar.server.component.ComponentCleanerService;
import org.sonar.server.db.migrations.DatabaseMigrator;
@@ -363,19 +362,6 @@ public final class JRubyFacade {
return Platform.getInstance().getContainer();
}
- // UPDATE PROJECT KEY ------------------------------------------------------------------
- public void updateResourceKey(long projectId, String newKey) {
- get(ResourceKeyUpdaterDao.class).updateKey(projectId, newKey);
- }
-
- public Map<String, String> checkModuleKeysBeforeRenaming(long projectId, String stringToReplace, String replacementString) {
- return get(ResourceKeyUpdaterDao.class).checkModuleKeysBeforeRenaming(projectId, stringToReplace, replacementString);
- }
-
- public void bulkUpdateKey(long projectId, String stringToReplace, String replacementString) {
- get(ResourceKeyUpdaterDao.class).bulkUpdateKey(projectId, stringToReplace, replacementString);
- }
-
// USERS
public void onNewUser(Map<String, String> fields) {
NewUserNotifier notifier = get(NewUserNotifier.class);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java
index 9415fd8e9d5..b3e602dbd55 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java
@@ -35,18 +35,19 @@ import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.index.IssueAuthorizationIndex;
import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
+import org.sonar.server.search.IndexDefinition;
+import org.sonar.server.search.SearchClient;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
import java.util.Date;
+import java.util.Map;
import static org.fest.assertions.Assertions.assertThat;
@@ -130,11 +131,12 @@ public class ComponentServiceMediumTest {
assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root");
// Check that no new issue has been added
- assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().build(), new QueryContext()).getTotal()).isEqualTo(1);
+ assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1);
// Check Issue Authorization index
assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull();
assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull();
+ assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES_AUTHORIZATION.getIndexName()).setTypes(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType()).get().getCount()).isEqualTo(1);
// Check dry run cache have been updated
assertThat(db.propertiesDao().selectProjectProperties("sample2:root", session)).hasSize(1);
@@ -181,6 +183,25 @@ public class ComponentServiceMediumTest {
assertThat(db.propertiesDao().selectProjectProperties(project.key(), session)).hasSize(1);
}
+ @Test
+ public void update_provisioned_project_key() throws Exception {
+ ComponentDto provisionedProject = ComponentTesting.newProjectDto().setKey("provisionedProject");
+ tester.get(ComponentDao.class).insert(session, provisionedProject);
+
+ session.commit();
+
+ MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, provisionedProject.key(), provisionedProject.key());
+ service.updateKey(provisionedProject.key(), "provisionedProject2");
+ session.commit();
+
+ // Check project key has been updated
+ assertThat(service.getNullableByKey(provisionedProject.key())).isNull();
+ assertThat(service.getNullableByKey("provisionedProject2")).isNotNull();
+
+ // Check dry run cache have been updated
+ assertThat(db.propertiesDao().selectProjectProperties("provisionedProject2", session)).hasSize(1);
+ }
+
@Test(expected = ForbiddenException.class)
public void fail_to_update_project_key_without_admin_permission() throws Exception {
MockUserSession.set().setLogin("john").addComponentPermission(UserRole.USER, project.key(), project.key());
@@ -188,6 +209,52 @@ public class ComponentServiceMediumTest {
}
@Test
+ public void check_module_keys_before_renaming() throws Exception {
+ ComponentDto module = ComponentTesting.newModuleDto(project).setKey("sample:root:module");
+ tester.get(ComponentDao.class).insert(session, module);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(module, project));
+
+ ComponentDto file = ComponentTesting.newFileDto(module).setKey("sample:root:module:src/File.xoo");
+ tester.get(ComponentDao.class).insert(session, file);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project));
+
+ session.commit();
+
+ MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ADMIN, project.key());
+ Map<String, String> result = service.checkModuleKeysBeforeRenaming(project.key(), "sample", "sample2");
+
+ assertThat(result).hasSize(2);
+ assertThat(result.get("sample:root")).isEqualTo("sample2:root");
+ assertThat(result.get("sample:root:module")).isEqualTo("sample2:root:module");
+ }
+
+ @Test
+ public void check_module_keys_before_renaming_return_duplicate_key() throws Exception {
+ ComponentDto module = ComponentTesting.newModuleDto(project).setKey("sample:root:module");
+ tester.get(ComponentDao.class).insert(session, module);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(module, project));
+
+ ComponentDto module2 = ComponentTesting.newModuleDto(project).setKey("foo:module");
+ tester.get(ComponentDao.class).insert(session, module2);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(module2, project));
+
+ session.commit();
+
+ MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ADMIN, project.key());
+ Map<String, String> result = service.checkModuleKeysBeforeRenaming(project.key(), "sample:root", "foo");
+
+ assertThat(result).hasSize(2);
+ assertThat(result.get("sample:root")).isEqualTo("foo");
+ assertThat(result.get("sample:root:module")).isEqualTo("#duplicate_key#");
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void fail_to_check_module_keys_before_renaming_without_admin_permission() throws Exception {
+ MockUserSession.set().setLogin("john").addComponentPermission(UserRole.USER, project.key(), project.key());
+ service.checkModuleKeysBeforeRenaming(project.key(), "sample", "sample2");
+ }
+
+ @Test
public void bulk_update_project_key() throws Exception {
ComponentDto module = ComponentTesting.newModuleDto(project).setKey("sample:root:module");
tester.get(ComponentDao.class).insert(session, module);
@@ -203,7 +270,7 @@ public class ComponentServiceMediumTest {
session.commit();
MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ADMIN, project.key());
- service.bulkUpdateKey("sample:root", "sample", "sample2");
+ service.bulkUpdateKey(project.key(), "sample", "sample2");
session.commit();
// Check project key has been updated
@@ -223,16 +290,36 @@ public class ComponentServiceMediumTest {
assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root");
// Check that no new issue has been added
- assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().build(), new QueryContext()).getTotal()).isEqualTo(1);
+ assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1);
// Check Issue Authorization index
assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull();
assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull();
+ assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES_AUTHORIZATION.getIndexName()).setTypes(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType()).get().getCount()).isEqualTo(1);
// Check dry run cache have been updated
assertThat(db.propertiesDao().selectProjectProperties("sample2:root", session)).hasSize(1);
}
+ @Test
+ public void bulk_update_provisioned_project_key() throws Exception {
+ ComponentDto provisionedProject = ComponentTesting.newProjectDto().setKey("provisionedProject");
+ tester.get(ComponentDao.class).insert(session, provisionedProject);
+
+ session.commit();
+
+ MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, provisionedProject.key(), provisionedProject.key());
+ service.bulkUpdateKey(provisionedProject.key(), "provisionedProject", "provisionedProject2");
+ session.commit();
+
+ // Check project key has been updated
+ assertThat(service.getNullableByKey(provisionedProject.key())).isNull();
+ assertThat(service.getNullableByKey("provisionedProject2")).isNotNull();
+
+ // Check dry run cache have been updated
+ assertThat(db.propertiesDao().selectProjectProperties("provisionedProject2", session)).hasSize(1);
+ }
+
@Test(expected = ForbiddenException.class)
public void fail_to_bulk_update_project_key_without_admin_permission() throws Exception {
MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
index 28e52b6217a..8860c8c501c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
@@ -263,6 +263,12 @@ public class DefaultRubyComponentServiceTest {
}
@Test
+ public void check_module_keys_before_renaming() {
+ service.checkModuleKeysBeforeRenaming("oldKey", "old", "new");
+ verify(componentService).checkModuleKeysBeforeRenaming("oldKey", "old", "new");
+ }
+
+ @Test
public void bulk_update_key() {
service.bulkUpdateKey("oldKey", "old", "new");
verify(componentService).bulkUpdateKey("oldKey", "old", "new");
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
index 09148fc3bec..8af012accdd 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
@@ -182,17 +182,19 @@ class ProjectController < ApplicationController
flash[:error] = message('update_key.fieds_cant_be_blank_for_bulk_update')
redirect_to :action => 'key', :id => @project.id
else
- @key_check_results = java_facade.checkModuleKeysBeforeRenaming(@project.id, @string_to_replace, @replacement_string)
- @can_update = false
- @duplicate_key_found = false
- @key_check_results.each do |key, value|
- if value=="#duplicate_key#"
- @duplicate_key_found = true
- else
- @can_update = true
+ call_backend do
+ @key_check_results = Internal.component_api.checkModuleKeysBeforeRenaming(@project.key, @string_to_replace, @replacement_string)
+ @can_update = false
+ @duplicate_key_found = false
+ @key_check_results.each do |key, value|
+ if value=="#duplicate_key#"
+ @duplicate_key_found = true
+ else
+ @can_update = true
+ end
end
+ @can_update = false if @duplicate_key_found
end
- @can_update = false if @duplicate_key_found
end
end
diff --git a/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java b/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java
index 7be4c1deed9..ee13722ce7c 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java
@@ -26,7 +26,7 @@ import org.sonar.core.persistence.Dto;
* Used to check that a project exists. Can return provisionned projects and projects from analysis.
* The root project id is not available because no join on snapshot is done to retrieve it.
*
- * Warning, this component should not be retrieve from db using a join on snapshots, otherwise provisionned projects will not be returned anymore.
+ * Warning, this component should not be retrieve from db using a join on snapshots, otherwise provisioned projects will not be returned anymore.
*/
public class AuthorizedComponentDto extends Dto<String> {
diff --git a/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java b/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java
index 41ae718bf99..c47cf8b997c 100644
--- a/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java
@@ -220,19 +220,24 @@ public class ResourceDao implements DaoComponent {
* The implementation should rather use a new column already containing the root project, see https://jira.codehaus.org/browse/SONAR-5188.
*/
@CheckForNull
+ public ResourceDto getRootProjectByComponentKey(DbSession session, String componentKey) {
+ ResourceDto component = getResource(ResourceQuery.create().setKey(componentKey), session);
+ if (component != null) {
+ Long rootId = component.getRootId();
+ if (rootId != null) {
+ return getParentModuleByComponentId(rootId, session);
+ } else {
+ return component;
+ }
+ }
+ return null;
+ }
+
+ @CheckForNull
public ResourceDto getRootProjectByComponentKey(String componentKey) {
DbSession session = mybatis.openSession(false);
try {
- ResourceDto component = getResource(ResourceQuery.create().setKey(componentKey), session);
- if (component != null) {
- Long rootId = component.getRootId();
- if (rootId != null) {
- return getParentModuleByComponentId(rootId, session);
- } else {
- return component;
- }
- }
- return null;
+ return getRootProjectByComponentKey(session, componentKey);
} finally {
MyBatis.closeQuietly(session);
}