diff options
16 files changed, 221 insertions, 19 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 4f9ac63c11f..1c271fb2b72 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, projectSnapshot); + resourceCache.add(project, null, projectSnapshot); TimeMachineConfigurationPersister persister = new TimeMachineConfigurationPersister(timeMachineConfiguration, resourceCache, getSession()); diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/resource/ReportComponent.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/resource/ReportComponent.java index ef24686d4b2..578cf92d73d 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/resource/ReportComponent.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/resource/ReportComponent.java @@ -19,6 +19,8 @@ */ package org.sonar.batch.protocol.output.resource; +import javax.annotation.CheckForNull; + import java.util.ArrayList; import java.util.Collection; @@ -28,7 +30,9 @@ public class ReportComponent { PRJ, MOD, DIR, - FIL + FIL, + VIEW, + SUBVIEW } private long batchId; @@ -37,6 +41,9 @@ public class ReportComponent { private String path; private String name; private Type type; + // Only for files + private Boolean isTest; + private String languageKey; private Collection<ReportComponent> children = new ArrayList<ReportComponent>(); @@ -94,6 +101,28 @@ public class ReportComponent { return type; } + public ReportComponent setTest(Boolean isTest) { + this.isTest = isTest; + return this; + } + + /** + * @return null when not a file + */ + @CheckForNull + public Boolean isTest() { + return isTest; + } + + public ReportComponent setLanguageKey(String languageKey) { + this.languageKey = languageKey; + return this; + } + + public String languageKey() { + return languageKey; + } + public ReportComponent addChild(ReportComponent child) { this.children.add(child); return this; diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/resource/ReportComponentsTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/resource/ReportComponentsTest.java index 085a0c0f65a..b3b989aa8f8 100644 --- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/resource/ReportComponentsTest.java +++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/resource/ReportComponentsTest.java @@ -64,7 +64,9 @@ public class ReportComponentsTest { .setName("Foo.java") .setSnapshotId(444) .setPath("Foo.java") - .setType(Type.FIL); + .setType(Type.FIL) + .setTest(true) + .setLanguageKey("java"); dir.addChild(file); res.setRoot(root); @@ -89,6 +91,8 @@ public class ReportComponentsTest { assertThat(root.path()).isNull(); assertThat(root.type()).isEqualTo(Type.PRJ); assertThat(root.children()).hasSize(1); + assertThat(root.isTest()).isNull(); + assertThat(root.languageKey()).isNull(); } } diff --git a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/output/resource/ReportResourceTest/expected.json b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/output/resource/ReportResourceTest/expected.json index 4c642a06ba0..581bbc5ea23 100644 --- a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/output/resource/ReportResourceTest/expected.json +++ b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/output/resource/ReportResourceTest/expected.json @@ -30,6 +30,8 @@ "path": "Foo.java", "name": "Foo.java", "type": "FIL", + "languageKey": "java", + "isTest": true, "children": [] } ] 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 b7d5418555c..5c74459778a 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 @@ -65,12 +65,12 @@ public final class DefaultResourcePersister implements ResourcePersister { BatchResource batchResource = resourceCache.get(project.getEffectiveKey()); if (batchResource == null) { Snapshot snapshot = persistProject(project, parent); - addToCache(project, snapshot); + addToCache(project, project.getParent(), snapshot); } } - private BatchResource addToCache(Resource resource, Snapshot snapshot) { - return resourceCache.add(resource, 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) { @@ -124,7 +124,7 @@ public final class DefaultResourcePersister implements ResourcePersister { BatchResource batchResource = resourceCache.get(resource.getEffectiveKey()); if (batchResource == null || ResourceUtils.isLibrary(resource)) { Snapshot s = persist(project, resource, parent); - batchResource = addToCache(resource, s); + batchResource = addToCache(resource, parent, s); } return batchResource; } 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 088a50de84c..01add749f84 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 @@ -28,6 +28,7 @@ import org.sonar.api.resources.Library; import org.sonar.api.resources.Resource; import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; @@ -52,10 +53,9 @@ public class ResourceCache implements BatchComponent { } } - public BatchResource add(Resource resource, Snapshot s) { + public BatchResource add(Resource resource, @Nullable Resource parentResource, Snapshot s) { String componentKey = resource.getEffectiveKey(); Preconditions.checkState(!Strings.isNullOrEmpty(componentKey), "Missing resource effective key"); - Resource parentResource = resource.getParent(); BatchResource parent = parentResource != null ? get(parentResource.getEffectiveKey()) : null; BatchResource batchResource = new BatchResource((long) resources.size() + 1, resource, s, parent); if (!(resource instanceof Library)) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java index f5011b50648..85f5081d29f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java @@ -21,6 +21,7 @@ package org.sonar.batch.report; import org.apache.commons.io.FileUtils; import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; import org.sonar.batch.index.BatchResource; @@ -46,6 +47,7 @@ public class ComponentsPublisher implements ReportPublisher { ReportComponents components = new ReportComponents(); BatchResource rootProject = resourceCache.get(reactor.getRoot().getKeyWithBranch()); components.setRoot(buildResourceForReport(rootProject)); + components.setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate()); File resourcesFile = new File(reportDir, "components.json"); FileUtils.write(resourcesFile, components.toJson()); } @@ -56,15 +58,30 @@ public class ComponentsPublisher implements ReportPublisher { .setBatchId(batchResource.batchId()) .setSnapshotId(batchResource.snapshotId()) .setId(r.getId()) - .setName(r.getName()) + .setName(getName(r)) .setPath(r.getPath()) - .setType(getType(r)); + .setType(getType(r)) + .setLanguageKey(getLanguageKey(r)) + .setTest(isTest(r)); for (BatchResource child : batchResource.children()) { result.addChild(buildResourceForReport(child)); } return result; } + private Boolean isTest(Resource r) { + return ResourceUtils.isFile(r) ? ResourceUtils.isUnitTestClass(r) : null; + } + + private String getLanguageKey(Resource r) { + return ResourceUtils.isFile(r) ? r.getLanguage().getKey() : null; + } + + private String getName(Resource r) { + // Don't return name for directories and files since it can be guessed from the path + return (ResourceUtils.isFile(r) || ResourceUtils.isDirectory(r)) ? null : r.getName(); + } + private ReportComponent.Type getType(Resource r) { if (ResourceUtils.isFile(r)) { return ReportComponent.Type.FIL; @@ -74,6 +91,10 @@ public class ComponentsPublisher implements ReportPublisher { return ReportComponent.Type.MOD; } else if (ResourceUtils.isRootProject(r)) { return ReportComponent.Type.PRJ; + } else if (ResourceUtils.isView(r)) { + return ReportComponent.Type.VIEW; + } else if (ResourceUtils.isSubview(r)) { + return ReportComponent.Type.SUBVIEW; } throw new IllegalArgumentException("Unknow resource type: " + r); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java index 16b5dbd59d7..fdaa2843e9a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java @@ -111,7 +111,7 @@ public class PublishReportJob implements BatchComponent { request.trustAllHosts(); request.header("User-Agent", String.format("SonarQube %s", server.getVersion())); request.basic(serverClient.getLogin(), serverClient.getPassword()); - request.part("report", report); + request.part("report", null, "application/octet-stream", report); if (!request.ok()) { int responseCode = request.code(); if (responseCode == 401) { 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 3e6c4866245..c66809ec396 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), snapshot); + resourceCache.add(new Project("myProject").setId(200), null, 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/ResourceCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceCacheTest.java index d59709a0bd6..bc4330f8734 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 @@ -33,7 +33,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, new Snapshot()); + cache.add(resource, null, new Snapshot()); assertThat(cache.get(componentKey).resource()).isSameAs(resource); assertThat(cache.get("other")).isNull(); @@ -44,7 +44,7 @@ public class ResourceCacheTest { ResourceCache cache = new ResourceCache(); Resource resource = new File("org/struts/Action.java").setEffectiveKey(null); try { - cache.add(resource, new Snapshot()); + cache.add(resource, null, new Snapshot()); fail(); } catch (IllegalStateException e) { // success 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 63a11312309..f323737ca37 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, snapshot); + resourceCache.add(project, null, 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 new file mode 100644 index 00000000000..d5a700b9d8f --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java @@ -0,0 +1,84 @@ +/* + * 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.report; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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.Directory; +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Project; +import org.sonar.batch.index.ResourceCache; + +import java.io.File; +import java.text.SimpleDateFormat; + +public class ComponentsPublisherTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void testComponentPublisher() throws Exception { + ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo")); + ResourceCache resourceCache = new ResourceCache(); + ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache); + + 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)); + Project module1 = new Project("module1").setName("Module1"); + module1.setParent(root); + module1.setId(2); + resourceCache.add(module1, root, new Snapshot().setId(12)); + Directory dir1 = Directory.create("src"); + dir1.setEffectiveKey("foo:src"); + dir1.setId(3); + resourceCache.add(dir1, module1, 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)); + Directory dir2 = Directory.create("test"); + dir2.setEffectiveKey("foo:test"); + dir2.setId(5); + resourceCache.add(dir2, module1, 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)); + + File exportDir = temp.newFolder(); + publisher.export(exportDir); + + System.out.println(FileUtils.readFileToString(new File(exportDir, "components.json"))); + + JSONAssert + .assertEquals( + IOUtils.toString(this.getClass().getResourceAsStream("ComponentsPublisherTest/expected.json"), "UTF-8"), + FileUtils.readFileToString(new File(exportDir, "components.json")), true); + } +} 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 98664860bae..86fa1d726b5 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, snapshot); + resourceCache.add(project, null, snapshot); loader = new PreviousFileHashLoader(project, resourceCache, snapshotDataDao, pastSnapshotFinder); } diff --git a/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json b/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json new file mode 100644 index 00000000000..09d60b6c0dd --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json @@ -0,0 +1,59 @@ +{ + "analysisDate": "2012-12-12T00:00:00+0100", + "root": { + "batchId": 1, + "id": 1, + "snapshotId": 11, + "name": "Root project", + "type": "PRJ", + "children": [ + { + "batchId": 2, + "id": 2, + "snapshotId": 12, + "name": "Module1", + "type": "MOD", + "children": [ + { + "batchId": 3, + "id": 3, + "snapshotId": 13, + "path": "src", + "type": "DIR", + "children": [ + { + "batchId": 4, + "id": 4, + "snapshotId": 14, + "path": "src/Foo.java", + "type": "FIL", + "isTest": false, + "languageKey": "java", + "children": [] + } + ] + }, + { + "batchId": 5, + "id": 5, + "snapshotId": 15, + "path": "test", + "type": "DIR", + "children": [ + { + "batchId": 6, + "id": 6, + "snapshotId": 16, + "path": "test/FooTest.java", + "type": "FIL", + "isTest": true, + "languageKey": "java", + "children": [] + } + ] + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java index bc866693f9b..950eb020e2d 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java @@ -26,6 +26,7 @@ import org.sonar.api.CoreProperties; import org.sonar.api.component.Component; import org.sonar.api.config.Settings; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import java.util.ArrayList; @@ -323,6 +324,7 @@ public class Project extends Resource implements Component { return false; } + @CheckForNull @Override public Project getParent() { return parent; 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 dd9e05b1155..a07c226a73b 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 @@ -214,11 +214,12 @@ public abstract class Resource implements Serializable { public abstract String getQualifier(); /** - * The parent is used to build the resources tree, for example for relations between classes, packages and projects. + * The parent is used to build the resources tree, for example for relations between files, directories and projects. * <p> - * Return null if the parent is the project. + * Return null if the parent is the current project (or module in case of multi-module). * </p> */ + @CheckForNull public abstract Resource getParent(); /** |