]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5663 Reindex issues when renaming a project Key
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 1 Oct 2014 17:19:58 +0000 (19:19 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 2 Oct 2014 13:28:07 +0000 (15:28 +0200)
14 files changed:
server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java
server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/BackendCleanupMediumTest.java
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb

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
new file mode 100644 (file)
index 0000000..534ae2f
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.component;
+
+import com.google.common.collect.ImmutableMap;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.resource.ResourceKeyUpdaterDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.permission.InternalPermissionService;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Date;
+
+public class ComponentService implements ServerComponent {
+
+  private final DbClient dbClient;
+
+  private final ResourceKeyUpdaterDao resourceKeyUpdaterDao;
+  private final InternalPermissionService permissionService;
+  private final PreviewCache previewCache;
+
+  public ComponentService(DbClient dbClient, ResourceKeyUpdaterDao resourceKeyUpdaterDao, InternalPermissionService permissionService, PreviewCache previewCache) {
+    this.dbClient = dbClient;
+    this.resourceKeyUpdaterDao = resourceKeyUpdaterDao;
+    this.permissionService = permissionService;
+    this.previewCache = previewCache;
+  }
+
+  public ComponentDto getByKey(String key) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      return dbClient.componentDao().getByKey(session, key);
+    } finally {
+      session.close();
+    }
+  }
+
+  @CheckForNull
+  public ComponentDto getNullableByKey(String key) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      return dbClient.componentDao().getNullableByKey(session, key);
+    } finally {
+      session.close();
+    }
+  }
+
+  public ComponentDto getByKey(DbSession session, String key) {
+    return dbClient.componentDao().getByKey(session, key);
+  }
+
+  public void updateKey(String projectOrModuleKey, String newKey) {
+    UserSession.get().checkComponentPermission(UserRole.ADMIN, projectOrModuleKey);
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      ComponentDto projectOrModule = getByKey(projectOrModuleKey);
+      ComponentDto oldRootProject = dbClient.componentDao().getRootProjectByKey(projectOrModuleKey, session);
+
+      resourceKeyUpdaterDao.updateKey(projectOrModule.getId(), newKey);
+      session.commit();
+
+      ComponentDto newRootProject = dbClient.componentDao().getRootProjectByKey(newKey, session);
+      updateIssuesIndex(session, oldRootProject.key(), newRootProject.key());
+
+      previewCache.reportResourceModification(newRootProject.key());
+
+      session.commit();
+    } 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);
+
+      resourceKeyUpdaterDao.bulkUpdateKey(project.getId(), stringToReplace, replacementString);
+      session.commit();
+
+      ComponentDto newProject = dbClient.componentDao().getById(project.getId(), session);
+      updateIssuesIndex(session, projectKey, newProject.key());
+
+      previewCache.reportResourceModification(newProject.key());
+
+      session.commit();
+    } finally {
+      session.close();
+    }
+  }
+
+  private void updateIssuesIndex(DbSession session, String oldKey, String newKey) {
+    // Remove permission on old project key
+    permissionService.synchronizePermissions(session, oldKey);
+
+    // Add permission on new project key
+    permissionService.synchronizePermissions(session, newKey);
+
+    // Reindex issues on new project key
+    dbClient.issueDao().synchronizeAfter(session, new Date(0),
+      ImmutableMap.of("project", newKey));
+  }
+
+}
index 94de74f57e41af0dd5926600b5f53e5f8c6543f3..de8be6e979189dc2d7d15008fc1e4dd915524000 100644 (file)
@@ -43,12 +43,14 @@ public class DefaultRubyComponentService implements RubyComponentService {
   private final ResourceDao resourceDao;
   private final DefaultComponentFinder finder;
   private final ResourceIndexerDao resourceIndexerDao;
+  private final ComponentService componentService;
   private final I18n i18n;
 
-  public DefaultRubyComponentService(ResourceDao resourceDao, DefaultComponentFinder finder, ResourceIndexerDao resourceIndexerDao, I18n i18n) {
+  public DefaultRubyComponentService(ResourceDao resourceDao, DefaultComponentFinder finder, ResourceIndexerDao resourceIndexerDao, ComponentService componentService, I18n i18n) {
     this.resourceDao = resourceDao;
     this.finder = finder;
     this.resourceIndexerDao = resourceIndexerDao;
+    this.componentService = componentService;
     this.i18n = i18n;
   }
 
@@ -114,6 +116,14 @@ public class DefaultRubyComponentService implements RubyComponentService {
     return resourceDao.selectProvisionedProjects(query.qualifiers());
   }
 
+  public void updateKey(String projectOrModuleKey, String newKey) {
+    componentService.updateKey(projectOrModuleKey, newKey);
+  }
+
+  public void bulkUpdateKey(String projectKey, String stringToReplace, String replacementString) {
+    componentService.bulkUpdateKey(projectKey, stringToReplace, replacementString);
+  }
+
   static ComponentQuery toQuery(Map<String, Object> props) {
     ComponentQuery.Builder builder = ComponentQuery.builder()
       .keys(RubyUtils.toStrings(props.get("keys")))
index a765263734efa8c1c55823dd7cb69b29719d8963..b55ff6507879fea54a4334ae82e5223fccf0a78a 100644 (file)
@@ -79,6 +79,7 @@ import org.sonar.server.authentication.ws.AuthenticationWs;
 import org.sonar.server.batch.*;
 import org.sonar.server.charts.ChartFactory;
 import org.sonar.server.component.ComponentCleanerService;
+import org.sonar.server.component.ComponentService;
 import org.sonar.server.component.DefaultComponentFinder;
 import org.sonar.server.component.DefaultRubyComponentService;
 import org.sonar.server.component.db.ComponentDao;
@@ -474,6 +475,7 @@ class ServerComponents {
     // components
     pico.addSingleton(DefaultComponentFinder.class);
     pico.addSingleton(DefaultRubyComponentService.class);
+    pico.addSingleton(ComponentService.class);
     pico.addSingleton(ComponentDao.class);
     pico.addSingleton(ResourcesWs.class);
     pico.addSingleton(ComponentsWs.class);
index adfc9545ece6f19f934f96e27e7c9efe5a92fce1..f0cc57a8ab9b8e5ef5ce7e612a595490e5dfbb26 100644 (file)
@@ -170,7 +170,7 @@ public class UploadReportActionMediumTest {
       .setProjectId_unit_test_only(project.getId())
       .setKey("MyComponent");
     db.componentDao().insert(session, resource);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource, project));
 
     RuleDto rule = RuleTesting.newXooX1();
     tester.get(RuleDao.class).insert(session, rule);
@@ -218,7 +218,7 @@ public class UploadReportActionMediumTest {
       .setProjectId_unit_test_only(project.getId())
       .setKey("MyComponent");
     db.componentDao().insert(session, resource);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource, project));
 
     RuleDto rule = RuleTesting.newXooX1();
     tester.get(RuleDao.class).insert(session, rule);
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
new file mode 100644 (file)
index 0000000..9415fd8
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.component;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+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.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+
+import java.util.Date;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ComponentServiceMediumTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbClient db;
+  IndexClient indexClient;
+  DbSession session;
+
+  ComponentService service;
+
+  ComponentDto project;
+  RuleDto rule;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    db = tester.get(DbClient.class);
+    indexClient = tester.get(IndexClient.class);
+    session = db.openSession(false);
+    service = tester.get(ComponentService.class);
+
+    project = ComponentTesting.newProjectDto().setKey("sample:root");
+    tester.get(ComponentDao.class).insert(session, project);
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForProject(project));
+
+    // project can be seen by anyone
+    tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+    db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+    rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(session, rule);
+
+    session.commit();
+  }
+
+  @After
+  public void after() {
+    session.close();
+  }
+
+  @Test
+  public void get_by_key() throws Exception {
+    assertThat(service.getByKey(project.getKey())).isNotNull();
+  }
+
+  @Test
+  public void get_nullable_by_key() throws Exception {
+    assertThat(service.getNullableByKey(project.getKey())).isNotNull();
+    assertThat(service.getNullableByKey("unknown")).isNull();
+  }
+
+  @Test
+  public void update_project_key() throws Exception {
+    ComponentDto file = ComponentTesting.newFileDto(project).setKey("sample:root:src/File.xoo");
+    tester.get(ComponentDao.class).insert(session, file);
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project));
+
+    IssueDto issue = IssueTesting.newDto(rule, file, project);
+    db.issueDao().insert(session, issue);
+
+    session.commit();
+
+    MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, project.key(), project.key());
+    service.updateKey(project.key(), "sample2:root");
+    session.commit();
+
+    // Check project key has been updated
+    assertThat(service.getNullableByKey(project.key())).isNull();
+    assertThat(service.getNullableByKey("sample2:root")).isNotNull();
+
+    // Check file key has been updated
+    assertThat(service.getNullableByKey(file.key())).isNull();
+    assertThat(service.getNullableByKey("sample2:root:src/File.xoo")).isNotNull();
+
+    // Check issue have been updated
+    assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:src/File.xoo");
+    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);
+
+    // Check Issue Authorization index
+    assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull();
+    assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull();
+
+    // Check dry run cache have been updated
+    assertThat(db.propertiesDao().selectProjectProperties("sample2:root", session)).hasSize(1);
+  }
+
+  @Test
+  public void update_module_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 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));
+
+    IssueDto issue = IssueTesting.newDto(rule, file, project);
+    db.issueDao().insert(session, issue);
+
+    session.commit();
+
+    MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, project.key(), module.key());
+    service.updateKey(module.key(), "sample:root2:module");
+    session.commit();
+
+    // Project key has not changed
+    assertThat(service.getNullableByKey(project.key())).isNotNull();
+
+    // Check module key has been updated
+    assertThat(service.getNullableByKey(module.key())).isNull();
+    assertThat(service.getNullableByKey("sample:root2:module")).isNotNull();
+
+    // Check file key has been updated
+    assertThat(service.getNullableByKey(file.key())).isNull();
+    assertThat(service.getNullableByKey("sample:root2:module:src/File.xoo")).isNotNull();
+
+    // Check issue have been updated
+    assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample:root2:module:src/File.xoo");
+    assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo(project.key());
+
+    // Check Issue Authorization index
+    assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNotNull();
+
+    // Check dry run cache have been updated -> on a module it's the project cache that is updated
+    assertThat(db.propertiesDao().selectProjectProperties(project.key(), 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());
+    service.updateKey(project.key(), "sample2:root");
+  }
+
+  @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);
+    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));
+
+    IssueDto issue = IssueTesting.newDto(rule, file, project);
+    db.issueDao().insert(session, issue);
+
+    session.commit();
+
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ADMIN, project.key());
+    service.bulkUpdateKey("sample:root", "sample", "sample2");
+    session.commit();
+
+    // Check project key has been updated
+    assertThat(service.getNullableByKey(project.key())).isNull();
+    assertThat(service.getNullableByKey("sample2:root")).isNotNull();
+
+    // Check module key has been updated
+    assertThat(service.getNullableByKey(module.key())).isNull();
+    assertThat(service.getNullableByKey("sample2:root:module")).isNotNull();
+
+    // Check file key has been updated
+    assertThat(service.getNullableByKey(file.key())).isNull();
+    assertThat(service.getNullableByKey("sample2:root:module:src/File.xoo")).isNotNull();
+
+    // Check issue have been updated
+    assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:module:src/File.xoo");
+    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);
+
+    // Check Issue Authorization index
+    assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull();
+    assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull();
+
+    // Check dry run cache have been updated
+    assertThat(db.propertiesDao().selectProjectProperties("sample2:root", 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());
+    service.bulkUpdateKey("sample:root", "sample", "sample2");
+  }
+
+}
index 493ca99d7898c66aa1fef466a4f3099e1e54033a..d729e8329e968a4ef0509a7b69a6ad1043da905a 100644 (file)
@@ -45,7 +45,7 @@ public class ComponentTesting {
       .setName("Module")
       .setLongName("Module")
       .setSubProjectId(subProjectOrProject.getId())
-      .setScope(Scopes.FILE)
+      .setScope(Scopes.PROJECT)
       .setQualifier(Qualifiers.MODULE)
       .setPath("module")
       .setLanguage(null)
index 4acd2671ed294da0d282be3a0041fa15a94d7ea7..28e52b6217aab1b9a134c64c09d81c3463e65fa4 100644 (file)
@@ -42,26 +42,26 @@ import static com.google.common.collect.Maps.newHashMap;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 public class DefaultRubyComponentServiceTest {
 
-  private ResourceDao resourceDao;
-  private DefaultComponentFinder finder;
-  private ResourceIndexerDao resourceIndexerDao;
-  private I18n i18n;
-  private DefaultRubyComponentService componentService;
+  ResourceDao resourceDao;
+  DefaultComponentFinder finder;
+  ResourceIndexerDao resourceIndexerDao;
+  ComponentService componentService;
+  I18n i18n;
+
+  DefaultRubyComponentService service;
 
   @Before
   public void before() {
     resourceDao = mock(ResourceDao.class);
     finder = mock(DefaultComponentFinder.class);
     resourceIndexerDao = mock(ResourceIndexerDao.class);
+    componentService = mock(ComponentService.class);
     i18n = mock(I18n.class);
-    componentService = new DefaultRubyComponentService(resourceDao, finder, resourceIndexerDao, i18n);
+    service = new DefaultRubyComponentService(resourceDao, finder, resourceIndexerDao, componentService, i18n);
   }
 
   @Test
@@ -69,7 +69,7 @@ public class DefaultRubyComponentServiceTest {
     Component<?> component = mock(Component.class);
     when(resourceDao.findByKey("struts")).thenReturn(component);
 
-    assertThat(componentService.findByKey("struts")).isEqualTo(component);
+    assertThat(service.findByKey("struts")).isEqualTo(component);
   }
 
   @Test
@@ -82,7 +82,7 @@ public class DefaultRubyComponentServiceTest {
     when(component.getId()).thenReturn(componentId);
     when(resourceDao.findByKey(componentKey)).thenReturn(null).thenReturn(component);
 
-    componentService.createComponent(componentKey, componentName, qualifier);
+    service.createComponent(componentKey, componentName, qualifier);
 
     ArgumentCaptor<ResourceDto> resourceCaptor = ArgumentCaptor.forClass(ResourceDto.class);
     verify(resourceDao).insertOrUpdate(resourceCaptor.capture());
@@ -103,7 +103,7 @@ public class DefaultRubyComponentServiceTest {
     String qualifier = Qualifiers.PROJECT;
     when(resourceDao.findByKey(componentKey)).thenReturn(null);
 
-    componentService.createComponent(componentKey, componentName, qualifier);
+    service.createComponent(componentKey, componentName, qualifier);
   }
 
   @Test(expected = BadRequestException.class)
@@ -113,19 +113,19 @@ public class DefaultRubyComponentServiceTest {
     String qualifier = Qualifiers.PROJECT;
     when(resourceDao.findByKey(componentKey)).thenReturn(mock(ComponentDto.class));
 
-    componentService.createComponent(componentKey, componentName, qualifier);
+    service.createComponent(componentKey, componentName, qualifier);
   }
 
   @Test(expected = BadRequestException.class)
   public void should_throw_if_malformed_key1() {
-    componentService.createComponent("1234", "New Project", Qualifiers.PROJECT);
+    service.createComponent("1234", "New Project", Qualifiers.PROJECT);
   }
 
   @Test(expected = NotFoundException.class)
   public void should_throw_if_updating_unknown_component() {
     final long componentId = 1234l;
     when(resourceDao.getResource(componentId)).thenReturn(null);
-    componentService.updateComponent(componentId, "key", "name");
+    service.updateComponent(componentId, "key", "name");
   }
 
   @Test
@@ -137,7 +137,7 @@ public class DefaultRubyComponentServiceTest {
     when(resourceDao.getResource(componentId)).thenReturn(resource);
     when(resource.setKey(newKey)).thenReturn(resource);
     when(resource.setName(newName)).thenReturn(resource);
-    componentService.updateComponent(componentId, newKey, newName);
+    service.updateComponent(componentId, newKey, newName);
     verify(resource).setKey(newKey);
     verify(resource).setName(newName);
     verify(resourceDao).insertOrUpdate(resource);
@@ -150,7 +150,7 @@ public class DefaultRubyComponentServiceTest {
     final String newName = "newName";
     ResourceDto resource = mock(ResourceDto.class);
     when(resourceDao.getResource(componentId)).thenReturn(resource);
-    componentService.updateComponent(componentId, newKey, newName);
+    service.updateComponent(componentId, newKey, newName);
   }
 
   @Test
@@ -166,7 +166,7 @@ public class DefaultRubyComponentServiceTest {
     map.put("sort", "NAME");
     map.put("asc", true);
 
-    componentService.find(map);
+    service.find(map);
     verify(resourceDao).selectProjectsByQualifiers(anyListOf(String.class));
     verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
   }
@@ -184,7 +184,7 @@ public class DefaultRubyComponentServiceTest {
     map.put("sort", "NAME");
     map.put("asc", true);
 
-    componentService.findWithUncompleteProjects(map);
+    service.findWithUncompleteProjects(map);
     verify(resourceDao).selectProjectsIncludingNotCompletedOnesByQualifiers(anyListOf(String.class));
     verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
   }
@@ -202,7 +202,7 @@ public class DefaultRubyComponentServiceTest {
     map.put("sort", "NAME");
     map.put("asc", true);
 
-    componentService.findGhostsProjects(map);
+    service.findGhostsProjects(map);
     verify(resourceDao).selectGhostsProjects(anyListOf(String.class));
     verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
   }
@@ -214,7 +214,7 @@ public class DefaultRubyComponentServiceTest {
     Map<String, Object> map = newHashMap();
     map.put("qualifiers", qualifiers);
 
-    componentService.findProvisionedProjects(map);
+    service.findProvisionedProjects(map);
     verify(resourceDao).selectProvisionedProjects(anyListOf(String.class));
   }
 
@@ -255,4 +255,16 @@ public class DefaultRubyComponentServiceTest {
     assertThat(query.sort()).isEqualTo(ComponentQuery.SORT_BY_NAME);
     assertThat(query.asc()).isTrue();
   }
+
+  @Test
+  public void update_key() {
+    service.updateKey("oldKey", "newKey");
+    verify(componentService).updateKey("oldKey", "newKey");
+  }
+
+  @Test
+  public void bulk_update_key() {
+    service.bulkUpdateKey("oldKey", "old", "new");
+    verify(componentService).bulkUpdateKey("oldKey", "old", "new");
+  }
 }
index 1ec6081f08dd6f1e00c0f80519a16fed0f7cd73a..845728744e531f84e1de7aa26afe11dec80cc67a 100644 (file)
@@ -25,10 +25,20 @@ import org.sonar.core.component.SnapshotDto;
 
 public class SnapshotTesting {
 
-  public static SnapshotDto createForComponent(ComponentDto component) {
+  /**
+   * When project is null, that means that the component is a project
+   */
+  public static SnapshotDto createForComponent(ComponentDto component, ComponentDto project) {
     return new SnapshotDto()
       .setResourceId(component.getId())
-      .setRootProjectId(component.subProjectId())
+      .setRootProjectId(project.getId())
+      .setLast(true);
+  }
+
+  public static SnapshotDto createForProject(ComponentDto project) {
+    return new SnapshotDto()
+      .setResourceId(project.getId())
+      .setRootProjectId(project.getId())
       .setLast(true);
   }
 
index dc59a5187a4268f91b343aed602f85eeef50baf8..d21e8100baa55306bc82075a4f4b773f9308174b 100644 (file)
@@ -91,14 +91,14 @@ public class IssueBulkChangeServiceMediumTest {
       .setQualifier(Qualifiers.PROJECT)
       .setScope(Scopes.PROJECT);
     tester.get(ComponentDao.class).insert(session, project);
-    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForProject(project));
 
     file = new ComponentDto()
       .setSubProjectId(project.getId())
       .setKey("MyComponent")
       .setLongName("My Component");
     tester.get(ComponentDao.class).insert(session, file);
-    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file));
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project));
 
     // project can be seen by anyone
     tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
index c2fe8dddf1dfd5d80e15b816a524ff64afc88888..b935d1fe797c3fa9533201487c62dac5387228df 100644 (file)
@@ -96,14 +96,14 @@ public class IssueServiceMediumTest {
       .setQualifier(Qualifiers.PROJECT)
       .setScope(Scopes.PROJECT);
     tester.get(ComponentDao.class).insert(session, project);
-    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForProject(project));
 
     file = new ComponentDto()
       .setSubProjectId(project.getId())
       .setKey("MyComponent")
       .setLongName("My Component");
     tester.get(ComponentDao.class).insert(session, file);
-    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file));
+    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project));
 
     // project can be seen by anyone
     tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
index 00ac616f8b33394a46872c6366a03a508ec7d02a..823f7ae17f8dd90ba3d7386052620565e2f486ea 100644 (file)
@@ -639,7 +639,7 @@ public class IssueIndexMediumTest {
       .setSubProjectId(project.getId())
       .setKey("MyComponent");
     db.componentDao().insert(session, resource);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource, project));
 
     List<String> issueKeys = newArrayList();
     for (int i = 0; i < numberOfIssues; i++) {
index 4ba6aef26d4b56480459962d7f49ecb63f549f9b..2416470c4785530b24af3996f8940f4fe0b995f7 100644 (file)
@@ -84,7 +84,7 @@ public class SearchActionMediumTest {
     project = new ComponentDto()
       .setKey("MyProject");
     db.componentDao().insert(session, project);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project));
+    db.snapshotDao().insert(session, SnapshotTesting.createForProject(project));
 
     // project can be seen by anyone
     tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
@@ -94,7 +94,7 @@ public class SearchActionMediumTest {
       .setKey("MyComponent")
       .setSubProjectId(project.getId());
     db.componentDao().insert(session, file);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, project));
 
     UserDto john = new UserDto().setLogin("john").setName("John").setEmail("john@email.com");
     db.userDao().insert(session, john);
@@ -266,7 +266,7 @@ public class SearchActionMediumTest {
       .setKey("ProjectHavingModule")
       .setScope("PRJ");
     db.componentDao().insert(session, project);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project));
+    db.snapshotDao().insert(session, SnapshotTesting.createForProject(project));
 
     // project can be seen by anyone
     tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
@@ -277,14 +277,14 @@ public class SearchActionMediumTest {
       .setScope("PRJ")
       .setSubProjectId(project.getId());
     db.componentDao().insert(session, module);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(module));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(module, project));
 
     ComponentDto file = new ComponentDto()
       .setKey("FileLinkedToModule")
       .setScope("FIL")
       .setSubProjectId(module.getId());
     db.componentDao().insert(session, file);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, project));
 
     IssueDto issue = IssueTesting.newDto(rule, file, project);
     db.issueDao().insert(session, issue);
index 4afc1f1c78698231de051bf3c5b5b7996f90e302..d7ebf51e4616bb72649dd271a4f5f347ea3073f1 100644 (file)
@@ -77,13 +77,13 @@ public class BackendCleanupMediumTest {
     project = new ComponentDto()
       .setKey("MyProject");
     tester.get(ComponentDao.class).insert(session, project);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project));
+    db.snapshotDao().insert(session, SnapshotTesting.createForProject(project));
 
     file = new ComponentDto()
       .setProjectId_unit_test_only(project.getId())
       .setKey("MyComponent");
     tester.get(ComponentDao.class).insert(session, file);
-    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file));
+    db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, project));
 
     // project can be seen by anyone
     tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
index 150b37a3e7e372fe50ee75875f1abe9d51d5018c..09148fc3bec00a03252d563f5f5a17651b56d21f 100644 (file)
@@ -164,13 +164,9 @@ class ProjectController < ApplicationController
     elsif Project.by_key(new_key)
       flash[:error] = message('update_key.cant_update_x_because_resource_already_exist_with_key_x', :params => [project.key, new_key])
     else
-      begin
-        java_facade.updateResourceKey(project.id, new_key)
-        reportProjectModification(project.id)
+      call_backend do
+        Internal.component_api.updateKey(project.key, new_key)
         flash[:notice] = message('update_key.key_updated')
-      rescue Exception => e
-        flash[:error] = message('update_key.error_occured_while_renaming_key_of_x',
-                                :params => [project.key, Api::Utils.exception_message(e, :backtrace => false)])
       end
     end
 
@@ -207,13 +203,9 @@ class ProjectController < ApplicationController
     replacement_string = params[:replacement_string].strip
 
     unless string_to_replace.blank? || replacement_string.blank?
-      begin
-        java_facade.bulkUpdateKey(project.id, string_to_replace, replacement_string)
-        reportProjectModification(project.id)
+      call_backend do
+        Internal.component_api.bulkUpdateKey(project.key, string_to_replace, replacement_string)
         flash[:notice] = message('update_key.key_updated')
-      rescue Exception => e
-        flash[:error] = message('update_key.error_occured_while_renaming_key_of_x',
-                                :params => [project.key, Api::Utils.exception_message(e, :backtrace => false)])
       end
     end