From a8e03360a82c53415fde082001a3f9dd3deff0b8 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 22 Oct 2014 14:19:01 +0200 Subject: [PATCH] SONAR-5753 Populate columns *_uuid when creating resources --- .../batch/index/DefaultResourcePersister.java | 46 ++++++++++++++++--- .../index/DefaultResourcePersisterTest.java | 41 +++++++++++++++-- .../org/sonar/api/resources/Resource.java | 26 +++++++++-- 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java index d9e84a88160..4284dbd9098 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java @@ -94,7 +94,7 @@ public final class DefaultResourcePersister implements ResourcePersister { // temporary hack project.setEffectiveKey(project.getKey()); - ResourceModel model = findOrCreateModel(project); + ResourceModel model = findOrCreateModel(project, parent); // Used by ResourceKeyMigration in order to know that a project has already being migrated model.setDeprecatedKey(project.getKey()); // language is null for project since multi-language support @@ -115,6 +115,7 @@ public final class DefaultResourcePersister implements ResourcePersister { } model = session.save(model); project.setId(model.getId()); + project.setUuid(model.getUuid()); Snapshot snapshot = new Snapshot(model, parentSnapshot); snapshot.setVersion(project.getAnalysisVersion()); @@ -193,10 +194,11 @@ public final class DefaultResourcePersister implements ResourcePersister { } private Snapshot persistLibrary(Project project, Library library) { - ResourceModel model = findOrCreateModel(library); + ResourceModel model = findOrCreateModel(library, null); model = session.save(model); // TODO to be removed library.setId(model.getId()); + library.setUuid(model.getUuid()); library.setEffectiveKey(library.getKey()); Snapshot snapshot = findLibrarySnapshot(model.getId(), library.getVersion()); @@ -237,10 +239,11 @@ public final class DefaultResourcePersister implements ResourcePersister { private Snapshot persistFileOrDirectory(Project project, Resource resource, @Nullable Resource parentReference) { Snapshot moduleSnapshot = snapshotsByResource.get(project); Integer moduleId = moduleSnapshot.getResourceId(); - ResourceModel model = findOrCreateModel(resource); + ResourceModel model = findOrCreateModel(resource, parentReference != null ? parentReference : project); model.setRootId(moduleId); model = session.save(model); resource.setId(model.getId()); + resource.setUuid(model.getUuid()); Snapshot parentSnapshot = (Snapshot) ObjectUtils.defaultIfNull(getSnapshot(parentReference), moduleSnapshot); Snapshot snapshot = new Snapshot(model, parentSnapshot); @@ -277,7 +280,7 @@ public final class DefaultResourcePersister implements ResourcePersister { } } - private ResourceModel findOrCreateModel(Resource resource) { + private ResourceModel findOrCreateModel(Resource resource, @Nullable Resource parentReference) { ResourceModel model; try { model = session.getSingleResult(ResourceModel.class, "key", resource.getEffectiveKey()); @@ -285,7 +288,7 @@ public final class DefaultResourcePersister implements ResourcePersister { if (StringUtils.isBlank(resource.getEffectiveKey())) { throw new SonarException("Unable to persist resource " + resource.toString() + ". Resource effective key is blank. This may be caused by an outdated plugin."); } - model = createModel(resource); + model = createModel(resource, parentReference); } else { mergeModel(model, resource); @@ -297,12 +300,12 @@ public final class DefaultResourcePersister implements ResourcePersister { } } - static ResourceModel createModel(Resource resource) { + ResourceModel createModel(Resource resource, @Nullable Resource parentResource) { ResourceModel model = new ResourceModel(); model.setEnabled(Boolean.TRUE); model.setDescription(resource.getDescription()); model.setKey(resource.getEffectiveKey()); - model.setUuid(UUID.randomUUID().toString()); + setUuids(resource, parentResource, model); model.setPath(resource.getPath()); Language language = resource.getLanguage(); if (language != null) { @@ -319,6 +322,35 @@ public final class DefaultResourcePersister implements ResourcePersister { return model; } + private void setUuids(Resource resource, Resource parentResource, ResourceModel model) { + model.setUuid(UUID.randomUUID().toString()); + if (parentResource != null) { + ResourceModel parentModel = session.getSingleResult(ResourceModel.class, "id", parentResource.getId()); + if (parentModel.getProjectUuid() != null) { + model.setProjectUuid(parentModel.getProjectUuid()); + } else { + model.setProjectUuid(parentModel.getUuid()); + } + if (Qualifiers.isProject(parentResource, true)) { + model.setModuleUuid(parentResource.getUuid()); + } else { + model.setModuleUuid(parentModel.getModuleUuid()); + } + if (Qualifiers.isProject(resource, true)) { + String parentModuleUuidPath = parentModel.getModuleUuidPath(); + model.setModuleUuidPath(parentModuleUuidPath != null ? parentModuleUuidPath + "." + parentModel.getUuid() : parentModel.getUuid()); + } else { + String parentModuleUuidPath = parentModel.getModuleUuidPath(); + model.setModuleUuidPath(parentModuleUuidPath != null ? parentModuleUuidPath : parentModel.getUuid()); + } + } else { + if (Qualifiers.isProject(resource, false)) { + // Root module + model.setProjectUuid(model.getUuid()); + } + } + } + static void mergeModel(ResourceModel model, Resource resource) { model.setEnabled(true); model.setKey(resource.getEffectiveKey()); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java index c8f440f6718..3c80b7237d3 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java @@ -98,7 +98,8 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache); persister.saveProject(singleProject, null); - checkTables("shouldSaveNewProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid"}, "projects", "snapshots"); + checkTables("shouldSaveNewProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, + "projects", "snapshots"); // Need to enable snapshot to make resource visible using ComponentMapper enableSnapshot(1001); @@ -106,6 +107,9 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { try { ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo"); assertThat(newProject.uuid()).isNotNull(); + assertThat(newProject.projectUuid()).isEqualTo(newProject.uuid()); + assertThat(newProject.moduleUuid()).isNull(); + assertThat(newProject.moduleUuidPath()).isNull(); // SONAR-3636 : created_at must be fed when inserting a new entry in the 'projects' table assertThat(newProject.getCreatedAt()).isNotNull(); } finally { @@ -120,13 +124,17 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache); persister.saveProject(singleCopyProject, null); - checkTables("shouldSaveCopyProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid"}, "projects", "snapshots"); + checkTables("shouldSaveCopyProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, + "projects", "snapshots"); // Need to enable snapshot to make resource visible using ComponentMapper enableSnapshot(1001); SqlSession session = getMyBatis().openSession(false); try { ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo"); assertThat(newProject.uuid()).isNotNull(); + assertThat(newProject.projectUuid()).isEqualTo(newProject.uuid()); + assertThat(newProject.moduleUuid()).isNull(); + assertThat(newProject.moduleUuidPath()).isNull(); } finally { MyBatis.closeQuietly(session); } @@ -142,7 +150,8 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { persister.saveProject(moduleB, multiModuleProject); persister.saveProject(moduleB1, moduleB); - checkTables("shouldSaveNewMultiModulesProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid"}, "projects", "snapshots"); + checkTables("shouldSaveNewMultiModulesProject", + new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); // Need to enable snapshot to make resource visible using ComponentMapper enableSnapshot(1001); @@ -153,12 +162,24 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { try { ComponentDto root = session.getMapper(ComponentMapper.class).selectByKey("root"); assertThat(root.uuid()).isNotNull(); + assertThat(root.projectUuid()).isEqualTo(root.uuid()); + assertThat(root.moduleUuid()).isNull(); + assertThat(root.moduleUuidPath()).isNull(); ComponentDto a = session.getMapper(ComponentMapper.class).selectByKey("a"); assertThat(a.uuid()).isNotNull(); + assertThat(a.projectUuid()).isEqualTo(root.uuid()); + assertThat(a.moduleUuid()).isEqualTo(root.uuid()); + assertThat(a.moduleUuidPath()).isEqualTo(root.uuid()); ComponentDto b = session.getMapper(ComponentMapper.class).selectByKey("b"); assertThat(b.uuid()).isNotNull(); + assertThat(b.projectUuid()).isEqualTo(root.uuid()); + assertThat(b.moduleUuid()).isEqualTo(root.uuid()); + assertThat(b.moduleUuidPath()).isEqualTo(root.uuid()); ComponentDto b1 = session.getMapper(ComponentMapper.class).selectByKey("b1"); assertThat(b1.uuid()).isNotNull(); + assertThat(b1.projectUuid()).isEqualTo(root.uuid()); + assertThat(b1.moduleUuid()).isEqualTo(b.uuid()); + assertThat(b1.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid()); } finally { MyBatis.closeQuietly(session); } @@ -173,14 +194,20 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { persister.saveResource(singleProject, Directory.create("src/main/java/org/foo", "org.foo").setEffectiveKey("foo:src/main/java/org/foo")); // check that the directory is attached to the project - checkTables("shouldSaveNewDirectory", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid"}, "projects", "snapshots"); + checkTables("shouldSaveNewDirectory", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, + "projects", "snapshots"); // Need to enable snapshot to make resource visible using ComponentMapper + enableSnapshot(1001); enableSnapshot(1002); SqlSession session = getMyBatis().openSession(false); try { + ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo"); ComponentDto newDir = session.getMapper(ComponentMapper.class).selectByKey("foo:src/main/java/org/foo"); assertThat(newDir.uuid()).isNotNull(); + assertThat(newDir.projectUuid()).isEqualTo(newProject.uuid()); + assertThat(newDir.moduleUuid()).isEqualTo(newProject.uuid()); + assertThat(newDir.moduleUuidPath()).isEqualTo(newProject.uuid()); } finally { MyBatis.closeQuietly(session); } @@ -205,7 +232,8 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"));// do nothing, already saved persister.saveResource(singleProject, new Library("junit:junit", "3.2").setEffectiveKey("junit:junit")); - checkTables("shouldSaveNewLibrary", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid"}, "projects", "snapshots"); + checkTables("shouldSaveNewLibrary", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, + "projects", "snapshots"); // Need to enable snapshot to make resource visible using ComponentMapper enableSnapshot(1002); @@ -213,6 +241,9 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { try { ComponentDto newLib = session.getMapper(ComponentMapper.class).selectByKey("junit:junit"); assertThat(newLib.uuid()).isNotNull(); + assertThat(newLib.projectUuid()).isEqualTo(newLib.projectUuid()); + assertThat(newLib.moduleUuid()).isNull(); + assertThat(newLib.moduleUuidPath()).isNull(); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java index 89101ba6aa1..dd9e05b1155 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Resource.java @@ -123,15 +123,17 @@ public abstract class Resource implements Serializable { @Deprecated public static final String QUALIFIER_UNIT_TEST_CLASS = Qualifiers.UNIT_TEST_FILE; - private Integer id = null; + private Integer id; - private String key = null; + private String key; - private String deprecatedKey = null; + private String uuid; - private String path = null; + private String deprecatedKey; - private String effectiveKey = null; + private String path; + + private String effectiveKey; /** * @return the resource key @@ -147,6 +149,20 @@ public abstract class Resource implements Serializable { this.key = s; } + /** + * @since 5.0 + */ + public final String getUuid() { + return uuid; + } + + /** + * Internal use only + */ + public void setUuid(String s) { + this.uuid = s; + } + /** * @return the resource deprecated key. Should not be used except to deal with backward compatibility. * @since 4.2 -- 2.39.5