public void bulkUpdateKey(DbSession dbSession, ComponentDto projectOrModule, String stringToReplace, String replacementString) { Set<ComponentKeyUpdaterDao.RekeyedResource> rekeyedProjects = dbClient.componentKeyUpdaterDao().bulkUpdateKey( dbSession, projectOrModule.uuid(), stringToReplace, replacementString, ComponentService::isMainProject); projectIndexers.commitAndIndex(dbSession, singletonList(projectOrModule), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); if (!rekeyedProjects.isEmpty()) { projectLifeCycleListeners.onProjectsRekeyed(rekeyedProjects.stream() .map(ComponentService::toRekeyedProject) .collect(MoreCollectors.toSet(rekeyedProjects.size()))); } }
private BulkUpdateKeyWsResponse doHandle(BulkUpdateKeyRequest request) { try (DbSession dbSession = dbClient.openSession(false)) { ComponentDto projectOrModule = componentFinder.getByUuidOrKey(dbSession, request.getId(), request.getKey(), ParamNames.ID_AND_KEY); checkIsProjectOrModule(projectOrModule); userSession.checkComponentPermission(UserRole.ADMIN, projectOrModule); Map<String, String> newKeysByOldKeys = componentKeyUpdater.simulateBulkUpdateKey(dbSession, projectOrModule.uuid(), request.getFrom(), request.getTo()); Map<String, Boolean> newKeysWithDuplicateMap = componentKeyUpdater.checkComponentKeys(dbSession, ImmutableList.copyOf(newKeysByOldKeys.values())); if (!request.isDryRun()) { checkNoDuplicate(newKeysWithDuplicateMap); bulkUpdateKey(dbSession, request, projectOrModule); } return buildResponse(newKeysByOldKeys, newKeysWithDuplicateMap); } }
ComponentKeyUpdaterMapper mapper = session.getMapper(ComponentKeyUpdaterMapper.class); Set<ResourceDto> modules = collectAllModules(projectUuid, stringToReplace, mapper, true); checkNewNameOfAllModules(modules, stringToReplace, replacementString, mapper); .filter(branch -> !projectUuid.equals(branch.getUuid())) .forEach(branch -> { Set<ResourceDto> branchModules = collectAllModules(branch.getUuid(), stringToReplace, mapper, true); modules.addAll(branchModules); branchModules.forEach(module -> branchBaseKeys.put(module.getKey(), branchBaseKey(module.getKey()))); }); String oldModuleKey = module.getKey(); oldModuleKey = branchBaseKeys.getOrDefault(oldModuleKey, oldModuleKey); String newModuleKey = computeNewKey(oldModuleKey, stringToReplace, replacementString); Collection<ResourceDto> resources = Lists.newArrayList(module); resources.addAll(allResourcesByModuleMap.get(module)); runBatchUpdateForAllResources(resources, oldModuleKey, newModuleKey, mapper, (resource, oldKey) -> { RekeyedResource rekeyedResource = new RekeyedResource(resource, oldKey);
/** * * @return a map with currentKey/newKey is a bulk update was executed */ public Map<String, String> simulateBulkUpdateKey(DbSession dbSession, String projectUuid, String stringToReplace, String replacementString) { return collectAllModules(projectUuid, stringToReplace, mapper(dbSession), false) .stream() .collect(Collectors.toMap( ResourceDto::getKey, component -> { String newKey = computeNewKey(component.getKey(), stringToReplace, replacementString); checkProjectKey(newKey); return newKey; })); }
@Test public void updateKey_changes_the_key_of_tree_of_components() { db.prepareDbUnit(getClass(), "shared.xml"); underTest.updateKey(dbSession, "B", "struts:core"); dbSession.commit(); db.assertDbUnit(getClass(), "shouldUpdateKey-result.xml", "projects"); }
public void updateKey(DbSession dbSession, ComponentDto projectOrModule, String newKey) { userSession.checkComponentPermission(UserRole.ADMIN, projectOrModule); checkIsProjectOrModule(projectOrModule); checkProjectOrModuleKeyFormat(newKey); dbClient.componentKeyUpdaterDao().updateKey(dbSession, projectOrModule.uuid(), newKey); projectIndexers.commitAndIndex(dbSession, singletonList(projectOrModule), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); if (isMainProject(projectOrModule)) { Project newProject = new Project(projectOrModule.uuid(), newKey, projectOrModule.name(), projectOrModule.description(), projectOrModule.getTags()); projectLifeCycleListeners.onProjectsRekeyed(singleton(new RekeyedProject(newProject, projectOrModule.getDbKey()))); } }
public Map<String, String> checkModuleKeysBeforeRenaming(String projectUuid, String stringToReplace, String replacementString) { SqlSession session = mybatis.openSession(false); ComponentKeyUpdaterMapper mapper = session.getMapper(ComponentKeyUpdaterMapper.class); Map<String, String> result = Maps.newHashMap(); try { Set<ResourceDto> modules = collectAllModules(projectUuid, stringToReplace, mapper); for (ResourceDto module : modules) { String newKey = computeNewKey(module.getKey(), stringToReplace, replacementString); if (mapper.countResourceByKey(newKey) > 0) { result.put(module.getKey(), "#duplicate_key#"); } else { result.put(module.getKey(), newKey); } } } finally { MyBatis.closeQuietly(session); } return result; }
private static void checkNewNameOfAllModules(Set<ResourceDto> modules, String stringToReplace, String replacementString, ComponentKeyUpdaterMapper mapper) { for (ResourceDto module : modules) { String newKey = computeNewKey(module.getKey(), stringToReplace, replacementString); checkArgument(isValidProjectKey(newKey), "Malformed key for '%s'. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", newKey); if (mapper.countResourceByKey(newKey) > 0) { throw new IllegalArgumentException("Impossible to update key: a component with key \"" + newKey + "\" already exists."); } } }
@Test public void simulate_bulk_update_key() { db.prepareDbUnit(getClass(), "shared.xml"); Map<String, String> result = underTest.simulateBulkUpdateKey(dbSession, "A", "org.struts", "foo"); assertThat(result) .hasSize(3) .containsOnly(entry("org.struts:struts", "foo:struts"), entry("org.struts:struts-core", "foo:struts-core"), entry("org.struts:struts-ui", "foo:struts-ui")); }
@Test public void check_component_keys() { db.prepareDbUnit(getClass(), "shared.xml"); Map<String, Boolean> result = underTest.checkComponentKeys(dbSession, newArrayList("foo:struts", "foo:struts-core", "foo:struts-ui")); assertThat(result) .hasSize(3) .containsOnly(entry("foo:struts", false), entry("foo:struts-core", true), entry("foo:struts-ui", false)); }
private static Set<ResourceDto> collectAllModules(String projectUuid, String stringToReplace, ComponentKeyUpdaterMapper mapper, boolean includeDisabled) { ResourceDto project = mapper.selectProjectByUuid(projectUuid); Set<ResourceDto> modules = new HashSet<>(); if (project.getKey().contains(stringToReplace) && (project.isEnabled() || includeDisabled)) { modules.add(project); } for (ResourceDto submodule : mapper.selectDescendantProjects(projectUuid)) { modules.addAll(collectAllModules(submodule.getUuid(), stringToReplace, mapper, includeDisabled)); } return modules; }
/** * @return a map with the component key as key, and boolean as true if key already exists in db */ public Map<String, Boolean> checkComponentKeys(DbSession dbSession, List<String> newComponentKeys) { return newComponentKeys.stream().collect(Collectors.toMap(Function.identity(), key -> mapper(dbSession).countResourceByKey(key) > 0)); }
public void updateKey(DbSession dbSession, String projectOrModuleUuid, String newKey) { ComponentKeyUpdaterMapper mapper = dbSession.getMapper(ComponentKeyUpdaterMapper.class); if (mapper.countResourceByKey(newKey) > 0) { throw new IllegalArgumentException("Impossible to update key: a component with key \"" + newKey + "\" already exists."); } // must SELECT first everything ResourceDto project = mapper.selectProjectByUuid(projectOrModuleUuid); String projectOldKey = project.getKey(); List<ResourceDto> resources = mapper.selectProjectResources(projectOrModuleUuid); resources.add(project); // add branch components dbSession.getMapper(BranchMapper.class).selectByProjectUuid(projectOrModuleUuid) .stream() .filter(branch -> !projectOrModuleUuid.equals(branch.getUuid())) .forEach(branch -> { resources.addAll(mapper.selectProjectResources(branch.getUuid())); resources.add(mapper.selectProjectByUuid(branch.getUuid())); }); // and then proceed with the batch UPDATE at once runBatchUpdateForAllResources(resources, projectOldKey, newKey, mapper, (resource, oldKey) -> { }); }
/** * * @return a map with currentKey/newKey is a bulk update was executed */ public Map<String, String> simulateBulkUpdateKey(DbSession dbSession, String projectUuid, String stringToReplace, String replacementString) { return collectAllModules(projectUuid, stringToReplace, mapper(dbSession)) .stream() .collect(Collectors.toMap( ResourceDto::getKey, component -> { String newKey = computeNewKey(component.getKey(), stringToReplace, replacementString); checkModuleKey(newKey); return newKey; })); }
@Test public void updateKey_throws_IAE_if_component_with_specified_key_does_not_exist() { db.prepareDbUnit(getClass(), "shared.xml"); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Impossible to update key: a component with key \"org.struts:struts-ui\" already exists."); underTest.updateKey(dbSession, "B", "org.struts:struts-ui"); }
public void updateKey(DbSession dbSession, ComponentDto projectOrModule, String newKey) { userSession.checkComponentPermission(UserRole.ADMIN, projectOrModule); checkIsProjectOrModule(projectOrModule); checkProjectOrModuleKeyFormat(newKey); dbClient.componentKeyUpdaterDao().updateKey(dbSession, projectOrModule.uuid(), newKey); projectIndexers.commitAndIndex(dbSession, singletonList(projectOrModule), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); if (isMainProject(projectOrModule)) { Project newProject = new Project(projectOrModule.uuid(), newKey, projectOrModule.name(), projectOrModule.description()); projectLifeCycleListeners.onProjectsRekeyed(singleton(new RekeyedProject(newProject, projectOrModule.getDbKey()))); } }
@Test public void compute_new_key() { assertThat(computeNewKey("my_project", "my_", "your_")).isEqualTo("your_project"); assertThat(computeNewKey("my_project", "my_", "$()_")).isEqualTo("$()_project"); }
@Test public void simulate_bulk_update_key_does_not_return_disable_components() { ComponentDto project = db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "A").setDbKey("project")); db.components().insertComponent(newModuleDto(project).setDbKey("project:enabled-module")); db.components().insertComponent(newModuleDto(project).setDbKey("project:disabled-module").setEnabled(false)); db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "D").setDbKey("other-project")); Map<String, String> result = underTest.simulateBulkUpdateKey(dbSession, "A", "project", "new-project"); assertThat(result).containsOnly( entry("project", "new-project"), entry("project:enabled-module", "new-project:enabled-module")); }
@Test public void check_component_keys_checks_inactive_components() { OrganizationDto organizationDto = db.organizations().insert(); db.components().insertComponent(ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey("my-project")); db.components().insertComponent(ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey("your-project").setEnabled(false)); Map<String, Boolean> result = underTest.checkComponentKeys(dbSession, newArrayList("my-project", "your-project", "new-project")); assertThat(result) .hasSize(3) .containsOnly(entry("my-project", true), entry("your-project", true), entry("new-project", false)); }
private static Set<ResourceDto> collectAllModules(String projectUuid, String stringToReplace, ComponentKeyUpdaterMapper mapper) { ResourceDto project = mapper.selectProject(projectUuid); Set<ResourceDto> modules = Sets.newHashSet(); if (project.getKey().contains(stringToReplace)) { modules.add(project); } for (ResourceDto submodule : mapper.selectDescendantProjects(projectUuid)) { modules.addAll(collectAllModules(submodule.getUuid(), stringToReplace, mapper)); } return modules; }