diff options
29 files changed, 397 insertions, 405 deletions
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java index 1c271fb2b72..f422f6f6020 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java @@ -49,7 +49,7 @@ public class TimeMachineConfigurationPersisterTest extends AbstractDbUnitTestCas ResourceCache resourceCache = new ResourceCache(); Project project = new Project("foo"); - resourceCache.add(project, null, projectSnapshot); + resourceCache.add(project, null).setSnapshot(projectSnapshot); TimeMachineConfigurationPersister persister = new TimeMachineConfigurationPersister(timeMachineConfiguration, resourceCache, getSession()); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java b/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java index dd3406b824b..f5049b91f49 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java @@ -32,14 +32,13 @@ public class BatchResource { private final long batchId; private final Resource r; - private final Snapshot s; + private Snapshot s; private final BatchResource parent; private final Collection<BatchResource> children = new ArrayList<BatchResource>(); - public BatchResource(long batchId, Resource r, Snapshot s, @Nullable BatchResource parent) { + public BatchResource(long batchId, Resource r, @Nullable BatchResource parent) { this.batchId = batchId; this.r = r; - this.s = s; this.parent = parent; if (parent != null) { parent.children.add(this); @@ -54,6 +53,11 @@ public class BatchResource { return r; } + public BatchResource setSnapshot(Snapshot snapshot) { + this.s = snapshot; + return this; + } + public int snapshotId() { return s.getId(); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index b2a0c7b2a4d..59dab76609b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -55,7 +55,6 @@ import org.sonar.batch.issue.ModuleIssues; import org.sonar.batch.scan.measure.MeasureCache; import org.sonar.batch.scan2.DefaultSensorContext; import org.sonar.core.component.ComponentKeys; -import org.sonar.core.component.ScanGraph; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -75,9 +74,8 @@ public class DefaultIndex extends SonarIndex { private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class); - private ResourcePersister resourcePersister; - private MetricFinder metricFinder; - private final ScanGraph graph; + private final ResourceCache resourceCache; + private final MetricFinder metricFinder; // caches private Project currentProject; @@ -95,16 +93,15 @@ public class DefaultIndex extends SonarIndex { private final LinkPersister linkPersister; private final EventPersister eventPersister; - public DefaultIndex(ResourcePersister resourcePersister, DependencyPersister dependencyPersister, + public DefaultIndex(ResourceCache resourceCache, DependencyPersister dependencyPersister, LinkPersister linkPersister, EventPersister eventPersister, ProjectTree projectTree, MetricFinder metricFinder, - ScanGraph graph, DeprecatedViolations deprecatedViolations, ResourceKeyMigration migration, MeasureCache measureCache) { - this.resourcePersister = resourcePersister; + DeprecatedViolations deprecatedViolations, ResourceKeyMigration migration, MeasureCache measureCache) { + this.resourceCache = resourceCache; this.dependencyPersister = dependencyPersister; this.linkPersister = linkPersister; this.eventPersister = eventPersister; this.projectTree = projectTree; this.metricFinder = metricFinder; - this.graph = graph; this.deprecatedViolations = deprecatedViolations; this.migration = migration; this.measureCache = measureCache; @@ -121,7 +118,7 @@ public class DefaultIndex extends SonarIndex { Bucket bucket = new Bucket(rootProject); addBucket(rootProject, bucket); migration.checkIfMigrationNeeded(rootProject); - resourcePersister.saveProject(rootProject, null); + resourceCache.add(rootProject, null); currentProject = rootProject; for (Project module : rootProject.getModules()) { @@ -593,10 +590,7 @@ public class DefaultIndex extends SonarIndex { addBucket(resource, bucket); Resource parentResource = parentBucket != null ? parentBucket.getResource() : null; - BatchResource batchResource = resourcePersister.saveResource(currentProject, resource, parentResource); - if (ResourceUtils.isPersistable(resource) && !Qualifiers.LIBRARY.equals(resource.getQualifier())) { - graph.addComponent(resource, batchResource.snapshotId()); - } + resourceCache.add(resource, parentResource); return bucket; } 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 deleted file mode 100644 index 04c27434027..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * 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.batch.index; - -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.database.model.ResourceModel; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.Language; -import org.sonar.api.resources.Library; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.resources.Scopes; -import org.sonar.api.security.ResourcePermissions; -import org.sonar.api.utils.SonarException; -import org.sonar.api.utils.internal.Uuids; - -import javax.annotation.Nullable; -import javax.persistence.NonUniqueResultException; -import javax.persistence.Query; - -import java.util.Date; -import java.util.List; - -public final class DefaultResourcePersister implements ResourcePersister { - - private static final String RESOURCE_ID = "resourceId"; - private static final String LAST = "last"; - private static final String VERSION = "version"; - private static final String SCOPE = "scope"; - private static final String QUALIFIER = "qualifier"; - - private final DatabaseSession session; - private final ResourcePermissions permissions; - private final ResourceCache resourceCache; - - public DefaultResourcePersister(DatabaseSession session, ResourcePermissions permissions, ResourceCache resourceCache) { - this.session = session; - this.permissions = permissions; - this.resourceCache = resourceCache; - } - - @Override - public void saveProject(Project project, @Nullable Project parent) { - BatchResource batchResource = resourceCache.get(project.getEffectiveKey()); - if (batchResource == null) { - Snapshot snapshot = persistProject(project, parent); - addToCache(project, project.getParent(), snapshot); - } - } - - private BatchResource addToCache(Resource resource, @Nullable Resource parent, Snapshot snapshot) { - return resourceCache.add(resource, parent, snapshot); - } - - private Snapshot persistProject(Project project, @Nullable Project parent) { - // temporary hack - project.setEffectiveKey(project.getKey()); - - 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 - model.setLanguageKey(null); - - // For views - if (project instanceof ResourceCopy) { - model.setCopyResourceId(((ResourceCopy) project).getCopyResourceId()); - } - - Snapshot parentSnapshot = null; - if (parent != null) { - // assume that the parent project has already been saved - parentSnapshot = resourceCache.get(project.getParent().getEffectiveKey()).snapshot(); - model.setRootId((Integer) ObjectUtils.defaultIfNull(parentSnapshot.getRootProjectId(), parentSnapshot.getResourceId())); - } else { - model.setRootId(null); - } - model = session.save(model); - project.setId(model.getId()); - project.setUuid(model.getUuid()); - - Snapshot snapshot = new Snapshot(model, parentSnapshot); - snapshot.setVersion(project.getAnalysisVersion()); - snapshot.setCreatedAt(project.getAnalysisDate()); - snapshot.setBuildDate(new Date()); - snapshot = session.save(snapshot); - session.commit(); - - if (!permissions.hasRoles(project)) { - permissions.grantDefaultRoles(project); - } - - return snapshot; - } - - @Override - public BatchResource saveResource(Project project, Resource resource) { - return saveResource(project, resource, null); - } - - @Override - public BatchResource saveResource(Project project, Resource resource, @Nullable Resource parent) { - BatchResource batchResource = resourceCache.get(resource.getEffectiveKey()); - if (batchResource == null || ResourceUtils.isLibrary(resource)) { - Snapshot s = persist(project, resource, parent); - batchResource = addToCache(resource, parent, s); - } - return batchResource; - } - - private Snapshot persist(Project project, Resource resource, @Nullable Resource parent) { - Snapshot snapshot; - if (resource instanceof Project) { - // should not occur, please use the method saveProject() - snapshot = persistProject((Project) resource, (Project) parent); - - } else if (resource instanceof Library) { - snapshot = persistLibrary(project, (Library) resource); - - } else { - snapshot = persistFileOrDirectory(project, resource, parent); - } - - return snapshot; - } - - private Snapshot persistLibrary(Project project, Library 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()); - if (snapshot == null) { - snapshot = new Snapshot(model, null); - snapshot.setCreatedAt(project.getAnalysisDate()); - snapshot.setBuildDate(new Date()); - snapshot.setVersion(library.getVersion()); - snapshot.setStatus(Snapshot.STATUS_PROCESSED); - - // see http://jira.codehaus.org/browse/SONAR-1850 - // The qualifier must be LIB, even if the resource is TRK, because this snapshot has no measures. - snapshot.setQualifier(Qualifiers.LIBRARY); - snapshot = session.save(snapshot); - } - session.commit(); - return snapshot; - } - - private Snapshot findLibrarySnapshot(Integer resourceId, String version) { - Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + - " s WHERE s.resourceId=:resourceId AND s.version=:version AND s.scope=:scope AND s.qualifier<>:qualifier AND s.last=:last"); - query.setParameter(RESOURCE_ID, resourceId); - query.setParameter(VERSION, version); - query.setParameter(SCOPE, Scopes.PROJECT); - query.setParameter(QUALIFIER, Qualifiers.LIBRARY); - query.setParameter(LAST, Boolean.TRUE); - List<Snapshot> snapshots = query.getResultList(); - if (snapshots.isEmpty()) { - snapshots = session.getResults(Snapshot.class, RESOURCE_ID, resourceId, VERSION, version, SCOPE, Scopes.PROJECT, QUALIFIER, Qualifiers.LIBRARY); - } - return snapshots.isEmpty() ? null : snapshots.get(0); - } - - /** - * Everything except project and library - */ - private Snapshot persistFileOrDirectory(Project project, Resource resource, @Nullable Resource parentReference) { - BatchResource moduleResource = resourceCache.get(project.getEffectiveKey()); - Integer moduleId = moduleResource.resource().getId(); - 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; - if (parentReference != null) { - parentSnapshot = resourceCache.get(parentReference.getEffectiveKey()).snapshot(); - } else { - parentSnapshot = moduleResource.snapshot(); - } - - Snapshot snapshot = new Snapshot(model, parentSnapshot); - snapshot.setBuildDate(new Date()); - snapshot = session.save(snapshot); - session.commit(); - return snapshot; - } - - private ResourceModel findOrCreateModel(Resource resource, @Nullable Resource parentResource) { - ResourceModel model; - try { - model = session.getSingleResult(ResourceModel.class, "key", resource.getEffectiveKey()); - if (model == null) { - 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, parentResource); - - } else { - mergeModel(model, resource); - } - updateUuids(resource, parentResource, model); - return model; - - } catch (NonUniqueResultException e) { - throw new SonarException("The resource '" + resource.getEffectiveKey() + "' is duplicated in database.", e); - } - } - - 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(Uuids.create()); - model.setPath(resource.getPath()); - Language language = resource.getLanguage(); - if (language != null) { - model.setLanguageKey(language.getKey()); - } - if (StringUtils.isNotBlank(resource.getName())) { - model.setName(resource.getName()); - } else { - model.setName(resource.getKey()); - } - model.setLongName(resource.getLongName()); - model.setScope(resource.getScope()); - model.setQualifier(resource.getQualifier()); - return model; - } - - private void updateUuids(Resource resource, Resource parentResource, ResourceModel model) { - // Don't override uuids when persisting a library and a project already exists - if (ResourceUtils.isLibrary(resource) && !Qualifiers.LIBRARY.equals(model.getQualifier())) { - return; - } - 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 (Scopes.isProject(parentResource)) { - model.setModuleUuid(parentResource.getUuid()); - String parentModuleUuidPath = parentModel.getModuleUuidPath(); - model.setModuleUuidPath(StringUtils.isNotBlank(parentModuleUuidPath) ? parentModuleUuidPath + "." + parentModel.getUuid() : parentModel.getUuid()); - } else { - model.setModuleUuid(parentModel.getModuleUuid()); - String parentModuleUuidPath = parentModel.getModuleUuidPath(); - model.setModuleUuidPath(StringUtils.isNotBlank(parentModuleUuidPath) ? parentModuleUuidPath : parentModel.getUuid()); - } - } else { - // Root module && libraries - model.setProjectUuid(model.getUuid()); - model.setModuleUuidPath(""); - } - } - - static void mergeModel(ResourceModel model, Resource resource) { - model.setEnabled(true); - model.setKey(resource.getEffectiveKey()); - if (StringUtils.isNotBlank(resource.getName())) { - model.setName(resource.getName()); - } - if (StringUtils.isNotBlank(resource.getLongName())) { - model.setLongName(resource.getLongName()); - } - if (StringUtils.isNotBlank(resource.getDescription())) { - model.setDescription(resource.getDescription()); - } - if (StringUtils.isNotBlank(resource.getPath())) { - model.setPath(resource.getPath()); - } - if (!ResourceUtils.isLibrary(resource)) { - model.setScope(resource.getScope()); - model.setQualifier(resource.getQualifier()); - } - Language language = resource.getLanguage(); - if (language != null) { - model.setLanguageKey(language.getKey()); - } - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java index 01add749f84..afa2ed7fee3 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java @@ -23,7 +23,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Maps; import org.sonar.api.BatchComponent; -import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Library; import org.sonar.api.resources.Resource; @@ -35,9 +34,9 @@ import java.util.Map; public class ResourceCache implements BatchComponent { // resource by component key - private final Map<String, BatchResource> resources = Maps.newHashMap(); + private final Map<String, BatchResource> resources = Maps.newLinkedHashMap(); // dedicated cache for libraries - private final Map<Library, BatchResource> libraries = Maps.newHashMap(); + private final Map<Library, BatchResource> libraries = Maps.newLinkedHashMap(); @CheckForNull public BatchResource get(String componentKey) { @@ -53,11 +52,11 @@ public class ResourceCache implements BatchComponent { } } - public BatchResource add(Resource resource, @Nullable Resource parentResource, Snapshot s) { + public BatchResource add(Resource resource, @Nullable Resource parentResource) { String componentKey = resource.getEffectiveKey(); Preconditions.checkState(!Strings.isNullOrEmpty(componentKey), "Missing resource effective key"); BatchResource parent = parentResource != null ? get(parentResource.getEffectiveKey()) : null; - BatchResource batchResource = new BatchResource((long) resources.size() + 1, resource, s, parent); + BatchResource batchResource = new BatchResource((long) resources.size() + 1, resource, parent); if (!(resource instanceof Library)) { // Libraries can have the same effective key than a project so we can't cache by effectiveKey resources.put(componentKey, batchResource); @@ -70,4 +69,8 @@ public class ResourceCache implements BatchComponent { public Collection<BatchResource> all() { return resources.values(); } + + public Collection<BatchResource> allLibraries() { + return libraries.values(); + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java index edb47fb6f54..df0979454f5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java @@ -19,23 +19,310 @@ */ package org.sonar.batch.index; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.ResourceModel; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Library; import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.resources.Scopes; +import org.sonar.api.security.ResourcePermissions; +import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.internal.Uuids; +import org.sonar.batch.ProjectTree; +import org.sonar.core.component.ScanGraph; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import javax.persistence.NonUniqueResultException; +import javax.persistence.Query; -public interface ResourcePersister { +import java.util.Date; +import java.util.List; - void saveProject(Project project, @Nullable Project parent); +public final class ResourcePersister implements ScanPersister { - /** - * Persist a resource in database. - */ - BatchResource saveResource(Project project, Resource resource, @Nullable Resource parent); + private static final String RESOURCE_ID = "resourceId"; + private static final String LAST = "last"; + private static final String VERSION = "version"; + private static final String SCOPE = "scope"; + private static final String QUALIFIER = "qualifier"; + + private final DatabaseSession session; + private final ResourcePermissions permissions; + private final ResourceCache resourceCache; + private final ScanGraph graph; + private final ProjectTree projectTree; + + public ResourcePersister(ProjectTree projectTree, DatabaseSession session, ResourcePermissions permissions, ResourceCache resourceCache, ScanGraph graph) { + this.projectTree = projectTree; + this.session = session; + this.permissions = permissions; + this.resourceCache = resourceCache; + this.graph = graph; + } + + @Override + public void persist() { + for (BatchResource resource : resourceCache.all()) { + persist(resource); + } + + for (BatchResource lib : resourceCache.allLibraries()) { + Snapshot s = persistLibrary(projectTree.getRootProject().getAnalysisDate(), (Library) lib.resource()); + lib.setSnapshot(s); + } + } + + private void persist(BatchResource batchResource) { + if (batchResource.snapshot() != null) { + // already persisted + return; + } + BatchResource parentBatchResource = batchResource.parent(); + if (parentBatchResource != null) { + persist(parentBatchResource); + } + Snapshot s = persist(findParentModule(batchResource), batchResource.resource(), parentBatchResource != null ? parentBatchResource.resource() : null); + batchResource.setSnapshot(s); + if (ResourceUtils.isPersistable(batchResource.resource())) { + graph.addComponent(batchResource.resource(), batchResource.snapshotId()); + } + } + + @CheckForNull + private Project findParentModule(BatchResource batchResource) { + if (batchResource != null && batchResource.parent() != null) { + if (batchResource.parent().resource() instanceof Project) { + return (Project) batchResource.parent().resource(); + } else { + return findParentModule(batchResource.parent()); + } + } + return null; + } + + private Snapshot persistProject(Project project, @Nullable Project parent) { + // temporary hack + project.setEffectiveKey(project.getKey()); + + 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 + model.setLanguageKey(null); + + // For views + if (project instanceof ResourceCopy) { + model.setCopyResourceId(((ResourceCopy) project).getCopyResourceId()); + } + + Snapshot parentSnapshot = null; + if (parent != null) { + // assume that the parent project has already been saved + parentSnapshot = resourceCache.get(project.getParent().getEffectiveKey()).snapshot(); + model.setRootId((Integer) ObjectUtils.defaultIfNull(parentSnapshot.getRootProjectId(), parentSnapshot.getResourceId())); + } else { + model.setRootId(null); + } + model = session.save(model); + project.setId(model.getId()); + project.setUuid(model.getUuid()); + + Snapshot snapshot = new Snapshot(model, parentSnapshot); + snapshot.setVersion(project.getAnalysisVersion()); + snapshot.setCreatedAt(project.getAnalysisDate()); + snapshot.setBuildDate(new Date()); + snapshot = session.save(snapshot); + session.commit(); + + if (!permissions.hasRoles(project)) { + permissions.grantDefaultRoles(project); + } + + return snapshot; + } + + Snapshot persist(Project project, Resource resource, @Nullable Resource parent) { + Snapshot snapshot; + if (resource instanceof Project) { + // should not occur, please use the method saveProject() + snapshot = persistProject((Project) resource, (Project) parent); + + } else if (resource instanceof Library) { + snapshot = persistLibrary(project.getAnalysisDate(), (Library) resource); + + } else { + snapshot = persistFileOrDirectory(project, resource, parent); + } + + return snapshot; + } + + private Snapshot persistLibrary(Date analysisDate, Library 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()); + if (snapshot == null) { + snapshot = new Snapshot(model, null); + snapshot.setCreatedAt(analysisDate); + snapshot.setBuildDate(new Date()); + snapshot.setVersion(library.getVersion()); + snapshot.setStatus(Snapshot.STATUS_PROCESSED); + + // see http://jira.codehaus.org/browse/SONAR-1850 + // The qualifier must be LIB, even if the resource is TRK, because this snapshot has no measures. + snapshot.setQualifier(Qualifiers.LIBRARY); + snapshot = session.save(snapshot); + } + session.commit(); + return snapshot; + } + + private Snapshot findLibrarySnapshot(Integer resourceId, String version) { + Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + + " s WHERE s.resourceId=:resourceId AND s.version=:version AND s.scope=:scope AND s.qualifier<>:qualifier AND s.last=:last"); + query.setParameter(RESOURCE_ID, resourceId); + query.setParameter(VERSION, version); + query.setParameter(SCOPE, Scopes.PROJECT); + query.setParameter(QUALIFIER, Qualifiers.LIBRARY); + query.setParameter(LAST, Boolean.TRUE); + List<Snapshot> snapshots = query.getResultList(); + if (snapshots.isEmpty()) { + snapshots = session.getResults(Snapshot.class, RESOURCE_ID, resourceId, VERSION, version, SCOPE, Scopes.PROJECT, QUALIFIER, Qualifiers.LIBRARY); + } + return snapshots.isEmpty() ? null : snapshots.get(0); + } /** - * Persist a resource in database. + * Everything except project and library */ - BatchResource saveResource(Project project, Resource resource); + private Snapshot persistFileOrDirectory(Project project, Resource resource, @Nullable Resource parentReference) { + BatchResource moduleResource = resourceCache.get(project.getEffectiveKey()); + Integer moduleId = moduleResource.resource().getId(); + 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; + if (parentReference != null) { + parentSnapshot = resourceCache.get(parentReference.getEffectiveKey()).snapshot(); + } else { + parentSnapshot = moduleResource.snapshot(); + } + + Snapshot snapshot = new Snapshot(model, parentSnapshot); + snapshot.setBuildDate(new Date()); + snapshot = session.save(snapshot); + session.commit(); + return snapshot; + } + + private ResourceModel findOrCreateModel(Resource resource, @Nullable Resource parentResource) { + ResourceModel model; + try { + model = session.getSingleResult(ResourceModel.class, "key", resource.getEffectiveKey()); + if (model == null) { + 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, parentResource); + + } else { + mergeModel(model, resource); + } + updateUuids(resource, parentResource, model); + return model; + + } catch (NonUniqueResultException e) { + throw new SonarException("The resource '" + resource.getEffectiveKey() + "' is duplicated in database.", e); + } + } + + 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(Uuids.create()); + model.setPath(resource.getPath()); + Language language = resource.getLanguage(); + if (language != null) { + model.setLanguageKey(language.getKey()); + } + if (StringUtils.isNotBlank(resource.getName())) { + model.setName(resource.getName()); + } else { + model.setName(resource.getKey()); + } + model.setLongName(resource.getLongName()); + model.setScope(resource.getScope()); + model.setQualifier(resource.getQualifier()); + return model; + } + + private void updateUuids(Resource resource, Resource parentResource, ResourceModel model) { + // Don't override uuids when persisting a library and a project already exists + if (ResourceUtils.isLibrary(resource) && !Qualifiers.LIBRARY.equals(model.getQualifier())) { + return; + } + 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 (Scopes.isProject(parentResource)) { + model.setModuleUuid(parentResource.getUuid()); + String parentModuleUuidPath = parentModel.getModuleUuidPath(); + model.setModuleUuidPath(StringUtils.isNotBlank(parentModuleUuidPath) ? parentModuleUuidPath + "." + parentModel.getUuid() : parentModel.getUuid()); + } else { + model.setModuleUuid(parentModel.getModuleUuid()); + String parentModuleUuidPath = parentModel.getModuleUuidPath(); + model.setModuleUuidPath(StringUtils.isNotBlank(parentModuleUuidPath) ? parentModuleUuidPath : parentModel.getUuid()); + } + } else { + // Root module && libraries + model.setProjectUuid(model.getUuid()); + model.setModuleUuidPath(""); + } + } + static void mergeModel(ResourceModel model, Resource resource) { + model.setEnabled(true); + model.setKey(resource.getEffectiveKey()); + if (StringUtils.isNotBlank(resource.getName())) { + model.setName(resource.getName()); + } + if (StringUtils.isNotBlank(resource.getLongName())) { + model.setLongName(resource.getLongName()); + } + if (StringUtils.isNotBlank(resource.getDescription())) { + model.setDescription(resource.getDescription()); + } + if (StringUtils.isNotBlank(resource.getPath())) { + model.setPath(resource.getPath()); + } + if (!ResourceUtils.isLibrary(resource)) { + model.setScope(resource.getScope()); + model.setQualifier(resource.getQualifier()); + } + Language language = resource.getLanguage(); + if (language != null) { + model.setLanguageKey(language.getKey()); + } + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 3706c13d501..5ae7992ac4d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -47,7 +47,7 @@ import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.Caches; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.index.DefaultIndex; -import org.sonar.batch.index.DefaultResourcePersister; +import org.sonar.batch.index.ResourcePersister; import org.sonar.batch.index.DependencyPersister; import org.sonar.batch.index.DuplicationPersister; import org.sonar.batch.index.EventPersister; @@ -134,7 +134,7 @@ public class ProjectScanContainer extends ComponentContainer { LinkPersister.class, MeasurePersister.class, DuplicationPersister.class, - DefaultResourcePersister.class, + ResourcePersister.class, SourcePersister.class, CodeColorizers.class, DefaultNotificationManager.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java index 6e2d5769a29..947534699f5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java @@ -29,6 +29,7 @@ import org.sonar.api.resources.Languages; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.batch.index.ResourceKeyMigration; +import org.sonar.batch.index.ResourcePersister; import org.sonar.batch.util.DeprecatedKeyUtils; /** @@ -42,15 +43,27 @@ public class ComponentIndexer implements BatchComponent { private final SonarIndex sonarIndex; private final ResourceKeyMigration migration; private final Project module; + private final ResourcePersister resourcePersister; - public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceKeyMigration migration) { + public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceKeyMigration migration, + ResourcePersister resourcePersister) { this.module = module; this.languages = languages; this.sonarIndex = sonarIndex; this.migration = migration; + this.resourcePersister = resourcePersister; + } + + public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceKeyMigration migration) { + this(module, languages, sonarIndex, migration, null); } public void execute(FileSystem fs) { + if (resourcePersister != null) { + // Force persistence of module structure in order to know if project should be migrated + resourcePersister.persist(); + } + migration.migrateIfNeeded(module, fs); for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) { @@ -68,6 +81,11 @@ public class ComponentIndexer implements BatchComponent { } sonarIndex.index(sonarFile); } + + if (resourcePersister != null) { + // Persist all files in order to have snapshot availables + resourcePersister.persist(); + } } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java index e943cf779ca..42ca92d27b2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java @@ -25,7 +25,6 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.measure.MetricFinder; -import org.sonar.api.database.model.Snapshot; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.MeasuresFilters; @@ -45,13 +44,11 @@ import org.sonar.batch.ProjectTree; import org.sonar.batch.issue.DeprecatedViolations; import org.sonar.batch.issue.ModuleIssues; import org.sonar.batch.scan.measure.MeasureCache; -import org.sonar.core.component.ScanGraph; import java.io.IOException; import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -80,8 +77,8 @@ public class DefaultIndexTest { ruleFinder = mock(RuleFinder.class); ProjectTree projectTree = mock(ProjectTree.class); - ResourcePersister resourcePersister = mock(ResourcePersister.class); - index = new DefaultIndex(resourcePersister, null, null, null, projectTree, metricFinder, mock(ScanGraph.class), deprecatedViolations, + ResourceCache resourceCache = new ResourceCache(); + index = new DefaultIndex(resourceCache, null, null, null, projectTree, metricFinder, deprecatedViolations, mock(ResourceKeyMigration.class), mock(MeasureCache.class)); @@ -95,9 +92,6 @@ public class DefaultIndexTest { moduleB1 = new Project("moduleB1").setParent(moduleB); when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1"))); - when(resourcePersister.saveResource(any(Project.class), any(Resource.class), any(Resource.class))).thenReturn( - new BatchResource(1, mock(Resource.class), new Snapshot().setId(1), null)); - RulesProfile rulesProfile = RulesProfile.create(); rule = Rule.create("repoKey", "ruleKey", "Rule"); rule.setId(1); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/FileHashesPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/FileHashesPersisterTest.java index c66809ec396..5d01dde9045 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/FileHashesPersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/FileHashesPersisterTest.java @@ -57,7 +57,7 @@ public class FileHashesPersisterTest extends AbstractDaoTestCase { Snapshot snapshot = new Snapshot(); snapshot.setId(100); snapshot.setResourceId(200); - resourceCache.add(new Project("myProject").setId(200), null, snapshot); + resourceCache.add(new Project("myProject").setId(200), null).setSnapshot(snapshot); data = new ComponentDataCache(caches); data.setStringData("myProject", SnapshotDataTypes.FILE_HASHES, "org/struts/Action.java=123ABC"); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java index 3ebb40264a2..8beab279cbf 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java @@ -201,7 +201,7 @@ public class MeasurePersisterTest extends AbstractDaoTestCase { private static BatchResource batchResource(Resource resource, int id) { Snapshot snapshot = mock(Snapshot.class); when(snapshot.getId()).thenReturn(id); - return new BatchResource(1, resource, snapshot, null); + return new BatchResource(1, resource, null).setSnapshot(snapshot); } private static Metric ncloc() { diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceCacheTest.java index bc4330f8734..466947602c0 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceCacheTest.java @@ -20,7 +20,6 @@ package org.sonar.batch.index; import org.junit.Test; -import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.File; import org.sonar.api.resources.Resource; @@ -33,7 +32,7 @@ public class ResourceCacheTest { ResourceCache cache = new ResourceCache(); String componentKey = "struts:src/org/struts/Action.java"; Resource resource = new File("org/struts/Action.java").setEffectiveKey(componentKey); - cache.add(resource, null, new Snapshot()); + cache.add(resource, null); assertThat(cache.get(componentKey).resource()).isSameAs(resource); assertThat(cache.get("other")).isNull(); @@ -44,7 +43,7 @@ public class ResourceCacheTest { ResourceCache cache = new ResourceCache(); Resource resource = new File("org/struts/Action.java").setEffectiveKey(null); try { - cache.add(resource, null, new Snapshot()); + cache.add(resource, null); fail(); } catch (IllegalStateException e) { // success diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java index d08e6b9ded3..33da7d65bed 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultResourcePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java @@ -57,7 +57,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { +public class ResourcePersisterTest extends AbstractDbUnitTestCase { @Rule public ExpectedException thrown = ExpectedException.none(); @@ -68,6 +68,12 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { private Project singleProject, singleCopyProject, multiModuleProject, moduleA, moduleB, moduleB1, existingProject; private ResourceCache resourceCache; + private ResourcePersister persister; + + private ProjectTree projectTree; + + private ResourcePermissions permissions; + @Before public void before() throws ParseException { resourceCache = new ResourceCache(); @@ -99,14 +105,17 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { moduleB1.setName("B1").setAnalysisDate(format.parse("25/12/2010")); moduleB1.setParent(moduleB); moduleB1.setPath("/moduleB1"); + + projectTree = mock(ProjectTree.class); + permissions = mock(ResourcePermissions.class); + persister = new ResourcePersister(projectTree, getSession(), permissions, resourceCache, mock(ScanGraph.class)); } @Test public void shouldSaveNewProject() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(singleProject, null); + persister.persist(null, singleProject, null); checkTables("shouldSaveNewProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -128,8 +137,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveCopyProject() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(singleCopyProject, null); + persister.persist(null, singleCopyProject, null); checkTables("shouldSaveCopyProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -148,15 +156,14 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewMultiModulesProject() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(multiModuleProject, null); - persister.saveProject(moduleA, multiModuleProject); - persister.saveProject(moduleB, multiModuleProject); - persister.saveProject(moduleB1, moduleB); + resourceCache.add(multiModuleProject, null).setSnapshot(persister.persist(null, multiModuleProject, null)); + resourceCache.add(moduleA, multiModuleProject).setSnapshot(persister.persist(null, moduleA, multiModuleProject)); + resourceCache.add(moduleB, multiModuleProject).setSnapshot(persister.persist(null, moduleB, multiModuleProject)); + resourceCache.add(moduleB1, moduleB).setSnapshot(persister.persist(null, moduleB1, moduleB)); Resource file = File.create("src/main/java/org/Foo.java").setEffectiveKey("b1:src/main/java/org/Foo.java"); file.getParent().setEffectiveKey("b1:src/main/java/org"); - persister.saveResource(moduleB1, file.getParent()); - persister.saveResource(moduleB1, file, file.getParent()); + resourceCache.add(file.getParent(), moduleB1).setSnapshot(persister.persist(moduleB1, file.getParent(), null)); + persister.persist(moduleB1, file, file.getParent()); checkTables("shouldSaveNewMultiModulesProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -209,16 +216,13 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { java.io.File baseDir = temp.newFolder(); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - - ProjectTree projectTree = mock(ProjectTree.class); when(projectTree.getRootProject()).thenReturn(multiModuleProject); when(projectTree.getProjectDefinition(multiModuleProject)).thenReturn(ProjectDefinition.create().setBaseDir(baseDir)); when(projectTree.getProjectDefinition(moduleA)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleA"))); when(projectTree.getProjectDefinition(moduleB)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB"))); when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1"))); - DefaultIndex index = new DefaultIndex(persister, null, null, null, projectTree, mock(MetricFinder.class), mock(ScanGraph.class), + DefaultIndex index = new DefaultIndex(resourceCache, null, null, null, projectTree, mock(MetricFinder.class), mock(DeprecatedViolations.class), mock(ResourceKeyMigration.class), mock(MeasureCache.class)); @@ -233,6 +237,8 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { // Emulate another project having library dependency on moduleA index.addResource(new Library(moduleA.getKey(), "1.0")); + persister.persist(); + checkTables("shouldSaveNewMultiModulesProjectAndLibrary", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -285,10 +291,8 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewDirectory() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(singleProject, null); - persister.saveResource(singleProject, - Directory.create("src/main/java/org/foo", "org.foo").setEffectiveKey("foo:src/main/java/org/foo")); + resourceCache.add(singleProject, null).setSnapshot(persister.persist(null, singleProject, null)); + persister.persist(singleProject, Directory.create("src/main/java/org/foo", "org.foo").setEffectiveKey("foo:src/main/java/org/foo"), null); // check that the directory is attached to the project checkTables("shouldSaveNewDirectory", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -319,11 +323,11 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldSaveNewLibrary() { setupData("shared"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(singleProject, null); - persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit")); - 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")); + persister.persist(null, singleProject, null); + persister.persist(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"), null); + persister.persist(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"), null);// do nothing, already + // saved + persister.persist(singleProject, new Library("junit:junit", "3.2").setEffectiveKey("junit:junit"), null); checkTables("shouldSaveNewLibrary", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots"); @@ -344,10 +348,9 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldUpdateExistingResource() { setupData("shouldUpdateExistingResource"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); singleProject.setName("new name"); singleProject.setDescription("new description"); - persister.saveProject(singleProject, null); + persister.persist(null, singleProject, null); checkTables("shouldUpdateExistingResource", new String[] {"build_date", "created_at", "authorization_updated_at"}, "projects", "snapshots"); } @@ -357,8 +360,7 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldRemoveRootIndexIfResourceIsProject() { setupData("shouldRemoveRootIndexIfResourceIsProject"); - ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), resourceCache); - persister.saveProject(singleProject, null); + persister.persist(null, singleProject, null); checkTables("shouldRemoveRootIndexIfResourceIsProject", new String[] {"build_date", "created_at", "authorization_updated_at"}, "projects", "snapshots"); } @@ -367,11 +369,9 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldGrantDefaultPermissionsIfNewProject() { setupData("shared"); - ResourcePermissions permissions = mock(ResourcePermissions.class); when(permissions.hasRoles(singleProject)).thenReturn(false); - ResourcePersister persister = new DefaultResourcePersister(getSession(), permissions, resourceCache); - persister.saveProject(singleProject, null); + persister.persist(null, singleProject, null); verify(permissions).grantDefaultRoles(singleProject); } @@ -380,11 +380,9 @@ public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase { public void shouldNotGrantDefaultPermissionsIfExistingProject() { setupData("shared"); - ResourcePermissions permissions = mock(ResourcePermissions.class); when(permissions.hasRoles(singleProject)).thenReturn(true); - ResourcePersister persister = new DefaultResourcePersister(getSession(), permissions, resourceCache); - persister.saveProject(singleProject, null); + persister.persist(null, singleProject, null); verify(permissions, never()).grantDefaultRoles(singleProject); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java index 40d6d14ce34..8f7289f2466 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/SourcePersisterTest.java @@ -384,7 +384,7 @@ public class SourcePersisterTest extends AbstractDaoTestCase { private void mockResourceCache(String relativePathEmpty, String projectKey, String uuid) { File sonarFile = File.create(relativePathEmpty); sonarFile.setUuid(uuid); - when(resourceCache.get(projectKey + ":" + relativePathEmpty)).thenReturn(new BatchResource(1, sonarFile, new Snapshot(), null)); + when(resourceCache.get(projectKey + ":" + relativePathEmpty)).thenReturn(new BatchResource(1, sonarFile, null)); } private byte[] md5(String string) { diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedViolationsTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedViolationsTest.java index a94578a5769..b5c7862c740 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedViolationsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedViolationsTest.java @@ -20,7 +20,6 @@ package org.sonar.batch.issue; import org.junit.Test; -import org.sonar.api.database.model.Snapshot; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; @@ -50,7 +49,7 @@ public class DeprecatedViolationsTest { public void test_toViolation() throws Exception { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycles"); when(ruleFinder.findByKey(ruleKey)).thenReturn(new Rule("squid", "AvoidCycles")); - when(resourceCache.get("org.apache:struts")).thenReturn(new BatchResource(1, new Project("org.apache:struts"), new Snapshot(), null)); + when(resourceCache.get("org.apache:struts")).thenReturn(new BatchResource(1, new Project("org.apache:struts"), null)); DefaultIssue issue = newIssue(ruleKey); @@ -80,7 +79,7 @@ public class DeprecatedViolationsTest { public void test_get() throws Exception { RuleKey ruleKey = RuleKey.of("squid", "AvoidCycles"); when(ruleFinder.findByKey(ruleKey)).thenReturn(new Rule("squid", "AvoidCycles")); - when(resourceCache.get("org.apache:struts")).thenReturn(new BatchResource(1, new Project("org.apache:struts"), new Snapshot(), null)); + when(resourceCache.get("org.apache:struts")).thenReturn(new BatchResource(1, new Project("org.apache:struts"), null)); when(issueCache.byComponent("org.apache:struts")).thenReturn(Arrays.asList(newIssue(ruleKey))); List<Violation> violations = deprecatedViolations.get("org.apache:struts"); diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java index f323737ca37..f33205097d1 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java @@ -95,7 +95,7 @@ public class QualityGateVerifierTest { project = new Project("foo"); resourceCache = new ResourceCache(); - resourceCache.add(project, null, snapshot); + resourceCache.add(project, null).setSnapshot(snapshot); verifier = new QualityGateVerifier(qualityGate, resourceCache, periods, i18n, durations); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java index 28932c22148..8c2722d11bc 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java @@ -28,7 +28,12 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.*; +import org.sonar.api.resources.Directory; +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; import org.sonar.batch.index.ResourceCache; import java.io.File; @@ -47,27 +52,27 @@ public class ComponentsPublisherTest { Project root = new Project("foo").setName("Root project").setAnalysisDate(new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012")); root.setId(1); - resourceCache.add(root, null, new Snapshot().setId(11)); + resourceCache.add(root, null).setSnapshot(new Snapshot().setId(11)); Project module1 = new Project("module1").setName("Module1"); module1.setParent(root); module1.setId(2); - resourceCache.add(module1, root, new Snapshot().setId(12)); + resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12)); Directory dir1 = Directory.create("src"); dir1.setEffectiveKey("foo:src"); dir1.setId(3); - resourceCache.add(dir1, module1, new Snapshot().setId(13)); + resourceCache.add(dir1, module1).setSnapshot(new Snapshot().setId(13)); org.sonar.api.resources.File mainFile = org.sonar.api.resources.File.create("src/Foo.java", "Foo.java", Java.INSTANCE, false); mainFile.setEffectiveKey("foo:src/Foo.java"); mainFile.setId(4); - resourceCache.add(mainFile, dir1, new Snapshot().setId(14)); + resourceCache.add(mainFile, dir1).setSnapshot(new Snapshot().setId(14)); Directory dir2 = Directory.create("test"); dir2.setEffectiveKey("foo:test"); dir2.setId(5); - resourceCache.add(dir2, module1, new Snapshot().setId(15)); + resourceCache.add(dir2, module1).setSnapshot(new Snapshot().setId(15)); org.sonar.api.resources.File testFile = org.sonar.api.resources.File.create("test/FooTest.java", "FooTest.java", Java.INSTANCE, true); testFile.setEffectiveKey("foo:test/FooTest.java"); testFile.setId(6); - resourceCache.add(testFile, dir2, new Snapshot().setId(16)); + resourceCache.add(testFile, dir2).setSnapshot(new Snapshot().setId(16)); File exportDir = temp.newFolder(); publisher.export(exportDir); @@ -87,12 +92,12 @@ public class ComponentsPublisherTest { View view = new View("ALL_PROJECT"); view.setId(1); view.setAnalysisDate(new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012")); - resourceCache.add(view, null, new Snapshot().setId(11)); + resourceCache.add(view, null).setSnapshot(new Snapshot().setId(11)); org.sonar.api.resources.File mainFile = org.sonar.api.resources.File.create("ALL_PROJECTsample", "ALL_PROJECTsample", null, false); mainFile.setEffectiveKey("ALL_PROJECTsample"); mainFile.setId(2); - resourceCache.add(mainFile, view, new Snapshot().setId(12)); + resourceCache.add(mainFile, view).setSnapshot(new Snapshot().setId(12)); File exportDir = temp.newFolder(); publisher.export(exportDir); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/PreviousFileHashLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/PreviousFileHashLoaderTest.java index 86fa1d726b5..6ae7fef716a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/PreviousFileHashLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/PreviousFileHashLoaderTest.java @@ -59,7 +59,7 @@ public class PreviousFileHashLoaderTest { @Before public void prepare() { resourceCache = new ResourceCache(); - resourceCache.add(project, null, snapshot); + resourceCache.add(project, null).setSnapshot(snapshot); loader = new PreviousFileHashLoader(project, resourceCache, snapshotDataDao, pastSnapshotFinder); } diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shared.xml index e031ae4ef66..e031ae4ef66 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shared.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shared.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject-result.xml index 283baaf3dde..283baaf3dde 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject.xml index 81d3d953079..81d3d953079 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldRemoveRootIndexIfResourceIsProject.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveCopyProject-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveCopyProject-result.xml index 833ebcd5438..833ebcd5438 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveCopyProject-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveCopyProject-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewDirectory-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewDirectory-result.xml index 4ac03aed376..4ac03aed376 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewDirectory-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewDirectory-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewLibrary-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewLibrary-result.xml index 1f2478a3fc3..1f2478a3fc3 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewLibrary-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewLibrary-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml index f25ce3cbece..f25ce3cbece 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewMultiModulesProjectAndLibrary-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProjectAndLibrary-result.xml index c16c139570f..c16c139570f 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewMultiModulesProjectAndLibrary-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProjectAndLibrary-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewProject-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewProject-result.xml index 7b0e006507a..7b0e006507a 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldSaveNewProject-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewProject-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldUpdateExistingResource-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource-result.xml index d04674f42b8..d04674f42b8 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldUpdateExistingResource-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource-result.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldUpdateExistingResource.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource.xml index 674397123dd..674397123dd 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/DefaultResourcePersisterTest/shouldUpdateExistingResource.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource.xml |