]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6273 SONAR-6274 Feed links in compute report and remove links sensor API
authorJulien HENRY <julien.henry@sonarsource.com>
Thu, 12 Mar 2015 09:16:10 +0000 (10:16 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Mar 2015 15:06:21 +0000 (16:06 +0100)
18 files changed:
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
sonar-batch/src/main/java/org/sonar/batch/deprecated/DeprecatedSensorContext.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/main/java/org/sonar/batch/index/LinkPersister.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/sensor/ProjectLinksSensor.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java
sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/sensor/ProjectLinksSensorTest.java [deleted file]
sonar-core/src/main/resources/META-INF/persistence.xml
sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
sonar-plugin-api/src/main/java/org/sonar/api/database/model/ResourceModel.java
sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/resources/ProjectLinkTest.java [deleted file]

index 31c78a9d8b72028b04c38e06261ed74a9026afad..666a6d1a95e67c4d181616201a2460a3bf3dc68a 100644 (file)
@@ -21,23 +21,12 @@ package org.sonar.batch.bootstrap;
 
 import com.google.common.collect.Lists;
 import org.sonar.batch.cpd.CpdComponents;
-import org.sonar.batch.design.DirectoryDsmDecorator;
-import org.sonar.batch.design.DirectoryTangleIndexDecorator;
-import org.sonar.batch.design.FileTangleIndexDecorator;
-import org.sonar.batch.design.MavenDependenciesSensor;
-import org.sonar.batch.design.ProjectDsmDecorator;
-import org.sonar.batch.design.SubProjectDsmDecorator;
+import org.sonar.batch.design.*;
 import org.sonar.batch.issue.tracking.IssueTracking;
 import org.sonar.batch.maven.MavenProjectBootstrapper;
 import org.sonar.batch.maven.MavenProjectBuilder;
 import org.sonar.batch.maven.MavenProjectConverter;
-import org.sonar.batch.scan.report.ConsoleReport;
-import org.sonar.batch.scan.report.HtmlReport;
-import org.sonar.batch.scan.report.IssuesReportBuilder;
-import org.sonar.batch.scan.report.JSONReport;
-import org.sonar.batch.scan.report.RuleNameProvider;
-import org.sonar.batch.scan.report.SourceProvider;
-import org.sonar.batch.scan.sensor.ProjectLinksSensor;
+import org.sonar.batch.scan.report.*;
 import org.sonar.batch.scan.sensor.VersionEventsSensor;
 import org.sonar.batch.scm.ScmConfiguration;
 import org.sonar.batch.scm.ScmSensor;
@@ -71,7 +60,6 @@ public class BatchComponents {
       ScmSensor.class,
 
       LinesSensor.class,
-      ProjectLinksSensor.class,
       VersionEventsSensor.class,
 
       // Issues tracking
index 6558fa59c0b85dd217cebc89496c44cdb336ba0f..0e421a788e0e5411a3446b17ee2aeb161395f247 100644 (file)
@@ -37,12 +37,7 @@ import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.*;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.sensor.DefaultSensorContext;
@@ -239,16 +234,6 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
     // useless since 4.2.
   }
 
-  @Override
-  public void saveLink(ProjectLink link) {
-    index.addLink(link);
-  }
-
-  @Override
-  public void deleteLink(String key) {
-    index.deleteLink(key);
-  }
-
   @Override
   public List<Event> getEvents(Resource resource) {
     return index.getEvents(resource);
index 0bec73c2c3e03a842e83bb66f97a88ca0c42f4e8..d2f26e4cecfe871b4c51e41ac31199452c11748b 100644 (file)
@@ -90,7 +90,6 @@ public class DefaultIndex extends SonarIndex {
   private final MeasureCache measureCache;
   private final ResourceKeyMigration migration;
   private final DependencyPersister dependencyPersister;
-  private final LinkPersister linkPersister;
   private final EventPersister eventPersister;
   // caches
   private Project currentProject;
@@ -102,11 +101,10 @@ public class DefaultIndex extends SonarIndex {
   private ModuleIssues moduleIssues;
 
   public DefaultIndex(ResourceCache resourceCache, DependencyPersister dependencyPersister,
-    LinkPersister linkPersister, EventPersister eventPersister, ProjectTree projectTree, MetricFinder metricFinder,
+    EventPersister eventPersister, ProjectTree projectTree, MetricFinder metricFinder,
     ResourceKeyMigration migration, MeasureCache measureCache) {
     this.resourceCache = resourceCache;
     this.dependencyPersister = dependencyPersister;
-    this.linkPersister = linkPersister;
     this.eventPersister = eventPersister;
     this.projectTree = projectTree;
     this.metricFinder = metricFinder;
@@ -117,7 +115,6 @@ public class DefaultIndex extends SonarIndex {
   public DefaultIndex(ResourceCache resourceCache, DependencyPersister dependencyPersister, ProjectTree projectTree, MetricFinder metricFinder, MeasureCache measureCache) {
     this.resourceCache = resourceCache;
     this.dependencyPersister = dependencyPersister;
-    this.linkPersister = null;
     this.eventPersister = null;
     this.projectTree = projectTree;
     this.metricFinder = metricFinder;
@@ -410,28 +407,6 @@ public class DefaultIndex extends SonarIndex {
     moduleIssues.initAndAddViolation(violation);
   }
 
-  //
-  //
-  //
-  // LINKS
-  //
-  //
-  //
-
-  @Override
-  public void addLink(ProjectLink link) {
-    if (linkPersister != null) {
-      linkPersister.saveLink(currentProject, link);
-    }
-  }
-
-  @Override
-  public void deleteLink(String key) {
-    if (linkPersister != null) {
-      linkPersister.deleteLink(currentProject, key);
-    }
-  }
-
   //
   //
   //
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/LinkPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/LinkPersister.java
deleted file mode 100644 (file)
index 3ab6491..0000000
+++ /dev/null
@@ -1,66 +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.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.ResourceModel;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-
-public final class LinkPersister {
-  private DatabaseSession session;
-  private ResourceCache resourceCache;
-
-  public LinkPersister(DatabaseSession session, ResourceCache resourcePersister) {
-    this.session = session;
-    this.resourceCache = resourcePersister;
-  }
-
-  public void saveLink(Project project, ProjectLink link) {
-    BatchResource batchResource = resourceCache.get(project.getEffectiveKey());
-    ResourceModel projectDao = session.reattach(ResourceModel.class, batchResource.resource().getId());
-    ProjectLink dbLink = projectDao.getProjectLink(link.getKey());
-    if (dbLink == null) {
-      link.setResource(projectDao);
-      projectDao.getProjectLinks().add(link);
-      session.save(link);
-
-    } else {
-      dbLink.copyFieldsFrom(link);
-      session.save(dbLink);
-    }
-    session.commit();
-
-  }
-
-  public void deleteLink(Project project, String linkKey) {
-    BatchResource batchResource = resourceCache.get(project.getEffectiveKey());
-    if (batchResource != null) {
-      ResourceModel model = session.reattach(ResourceModel.class, batchResource.resource().getId());
-      ProjectLink dbLink = model.getProjectLink(linkKey);
-      if (dbLink != null) {
-        session.remove(dbLink);
-        model.getProjectLinks().remove(dbLink);
-        session.commit();
-      }
-
-    }
-  }
-}
index d075a9a6300e828489421458dfbcbb7047e01012..181f38b71e5e3129848869a9195d05081b0137ea 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.batch.report;
 
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Resource;
@@ -26,8 +29,10 @@ import org.sonar.api.resources.ResourceUtils;
 import org.sonar.batch.index.BatchResource;
 import org.sonar.batch.index.ResourceCache;
 import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.protocol.Constants.ComponentLinkType;
 import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.ComponentLink;
+import org.sonar.batch.protocol.output.BatchReportWriter;
 
 import javax.annotation.CheckForNull;
 
@@ -86,6 +91,16 @@ public class ComponentsPublisher implements ReportPublisher {
     for (BatchResource child : batchResource.children()) {
       builder.addChildRefs(child.batchId());
     }
+    if (ResourceUtils.isProject(r)) {
+      ProjectDefinition def = reactor.getProject(r.getEffectiveKey());
+      ComponentLink.Builder linkBuilder = ComponentLink.newBuilder();
+
+      writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_HOME_PAGE, ComponentLinkType.HOME);
+      writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_CI, ComponentLinkType.CI);
+      writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_ISSUE_TRACKER, ComponentLinkType.ISSUE);
+      writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_SOURCES, ComponentLinkType.SCM);
+      writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_SOURCES_DEV, ComponentLinkType.SCM_DEV);
+    }
     writer.writeComponent(builder.build());
 
     for (BatchResource child : batchResource.children()) {
@@ -93,6 +108,17 @@ public class ComponentsPublisher implements ReportPublisher {
     }
   }
 
+  private void writeProjectLink(BatchReport.Component.Builder componentBuilder, ProjectDefinition def, ComponentLink.Builder linkBuilder, String linkProp,
+    ComponentLinkType linkType) {
+    String link = def.properties().get(linkProp);
+    if (StringUtils.isNotBlank(link)) {
+      linkBuilder.setType(linkType);
+      linkBuilder.setHref(link);
+      componentBuilder.addLinks(linkBuilder.build());
+      linkBuilder.clear();
+    }
+  }
+
   @CheckForNull
   private String getLanguageKey(Resource r) {
     Language language = r.getLanguage();
index 0f457c735d9962247f1cc498007b82a391bc0f19..2e7a68eb8da3b94c7cc1e6c62d01b998dd2d8712 100644 (file)
@@ -30,17 +30,9 @@ import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.FileExclusions;
 import org.sonar.batch.ProjectTree;
-import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-import org.sonar.batch.bootstrap.ExtensionInstaller;
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-import org.sonar.batch.bootstrap.ExtensionUtils;
+import org.sonar.batch.bootstrap.*;
 import org.sonar.batch.components.TimeMachineConfiguration;
-import org.sonar.batch.debt.DebtDecorator;
-import org.sonar.batch.debt.IssueChangelogDebtCalculator;
-import org.sonar.batch.debt.NewDebtDecorator;
-import org.sonar.batch.debt.SqaleRatingDecorator;
-import org.sonar.batch.debt.SqaleRatingSettings;
+import org.sonar.batch.debt.*;
 import org.sonar.batch.deprecated.DeprecatedSensorContext;
 import org.sonar.batch.deprecated.ResourceFilters;
 import org.sonar.batch.deprecated.components.DefaultProjectClasspath;
@@ -60,41 +52,15 @@ import org.sonar.batch.issue.tracking.InitialOpenIssuesSensor;
 import org.sonar.batch.issue.tracking.IssueHandlers;
 import org.sonar.batch.issue.tracking.IssueTrackingDecorator;
 import org.sonar.batch.language.LanguageDistributionDecorator;
-import org.sonar.batch.phases.DatabaseLessPhaseExecutor;
-import org.sonar.batch.phases.DatabaseModePhaseExecutor;
-import org.sonar.batch.phases.DecoratorsExecutor;
-import org.sonar.batch.phases.InitializersExecutor;
-import org.sonar.batch.phases.PhaseExecutor;
-import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.phases.PostJobsExecutor;
-import org.sonar.batch.phases.ProjectInitializer;
-import org.sonar.batch.phases.SensorsExecutor;
+import org.sonar.batch.phases.*;
 import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
 import org.sonar.batch.qualitygate.QualityGateProvider;
 import org.sonar.batch.qualitygate.QualityGateVerifier;
 import org.sonar.batch.report.ComponentsPublisher;
 import org.sonar.batch.report.IssuesPublisher;
 import org.sonar.batch.report.PublishReportJob;
-import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileDecorator;
-import org.sonar.batch.rule.QProfileEventsDecorator;
-import org.sonar.batch.rule.QProfileSensor;
-import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.rule.RuleFinderCompatibility;
-import org.sonar.batch.rule.RulesProfileProvider;
-import org.sonar.batch.scan.filesystem.ComponentIndexer;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
-import org.sonar.batch.scan.filesystem.ExclusionFilters;
-import org.sonar.batch.scan.filesystem.FileIndexer;
-import org.sonar.batch.scan.filesystem.FileMetadata;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.filesystem.InputFileBuilderFactory;
-import org.sonar.batch.scan.filesystem.LanguageDetectionFactory;
-import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
-import org.sonar.batch.scan.filesystem.ModuleInputFileCache;
-import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter;
-import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
+import org.sonar.batch.rule.*;
+import org.sonar.batch.scan.filesystem.*;
 import org.sonar.batch.scan.report.IssuesReports;
 import org.sonar.batch.sensor.AnalyzerOptimizer;
 import org.sonar.batch.sensor.DefaultSensorContext;
index eeb15214e81e49deca567f9252fd60ea7309e037..89b5aed9596c466b476ee690473529a81a02cb27 100644 (file)
@@ -185,7 +185,6 @@ public class ProjectScanContainer extends ComponentContainer {
   private void addDataBaseComponents() {
     add(
       EventPersister.class,
-      LinkPersister.class,
       MeasurePersister.class,
       DuplicationPersister.class,
       ResourcePersister.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/ProjectLinksSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/ProjectLinksSensor.java
deleted file mode 100644 (file)
index c04d0f5..0000000
+++ /dev/null
@@ -1,79 +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.scan.sensor;
-
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-import org.sonar.core.i18n.DefaultI18n;
-
-import java.util.Locale;
-
-public class ProjectLinksSensor implements Sensor {
-
-  private Settings settings;
-  private DefaultI18n defaultI18n;
-  private AnalysisMode analysisMode;
-
-  public ProjectLinksSensor(Settings settings, DefaultI18n defaultI18n, AnalysisMode analysisMode) {
-    this.settings = settings;
-    this.defaultI18n = defaultI18n;
-    this.analysisMode = analysisMode;
-  }
-
-  @Override
-  public boolean shouldExecuteOnProject(Project project) {
-    return !analysisMode.isPreview();
-  }
-
-  @Override
-  public void analyse(Project project, SensorContext context) {
-    handleLink(context, CoreProperties.LINKS_HOME_PAGE);
-    handleLink(context, CoreProperties.LINKS_CI);
-    handleLink(context, CoreProperties.LINKS_ISSUE_TRACKER);
-    handleLink(context, CoreProperties.LINKS_SOURCES);
-    handleLink(context, CoreProperties.LINKS_SOURCES_DEV);
-  }
-
-  private void handleLink(SensorContext context, String linkProperty) {
-    String home = settings.getString(linkProperty);
-    String linkType = StringUtils.substringAfterLast(linkProperty, ".");
-    String name = defaultI18n.message(Locale.getDefault(), "project_links." + linkType, linkProperty);
-    updateLink(context, linkType, name, home);
-  }
-
-  private void updateLink(SensorContext context, String key, String name, String url) {
-    if (StringUtils.isBlank(url)) {
-      context.deleteLink(key);
-    } else {
-      context.saveLink(new ProjectLink(key, name, url));
-    }
-  }
-
-  @Override
-  public String toString() {
-    return getClass().getSimpleName();
-  }
-}
index fe541281e0534ec4fd759310d3642e9576ac77cc..0c62cc64ac4b5548c47df3fe2e285f776f13f710 100644 (file)
@@ -29,13 +29,7 @@ import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilters;
 import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Java;
-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.*;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.batch.ProjectTree;
@@ -71,7 +65,7 @@ public class DefaultIndexTest {
 
     ProjectTree projectTree = mock(ProjectTree.class);
     ResourceCache resourceCache = new ResourceCache();
-    index = new DefaultIndex(resourceCache, null, null, null, projectTree, metricFinder,
+    index = new DefaultIndex(resourceCache, null, null, projectTree, metricFinder,
       mock(ResourceKeyMigration.class),
       mock(MeasureCache.class));
 
index fee743895f07ac0135af6dfe09bf5fe63684b68a..92299c87f20c949dead953a4a65d7c344bb9ee32 100644 (file)
@@ -30,11 +30,7 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.config.Settings;
 import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Library;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.*;
 import org.sonar.api.security.ResourcePermissions;
 import org.sonar.batch.ProjectTree;
 import org.sonar.batch.scan.measure.MeasureCache;
@@ -225,7 +221,7 @@ public class ResourcePersisterTest extends AbstractDbUnitTestCase {
     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(resourceCache, null, null, null, projectTree, mock(MetricFinder.class),
+    DefaultIndex index = new DefaultIndex(resourceCache, null, null, projectTree, mock(MetricFinder.class),
       mock(ResourceKeyMigration.class),
       mock(MeasureCache.class));
 
index 5bcc75aa6db999718ab25436a2c3dca0ac51b061..d309dd35013cfcee160774486912a8934b0cdca6 100644 (file)
  */
 package org.sonar.batch.report;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.database.model.Snapshot;
@@ -30,9 +32,14 @@ import org.sonar.api.resources.Java;
 import org.sonar.api.resources.Project;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.Constants.ComponentLinkType;
+import org.sonar.batch.protocol.output.BatchReport.Component;
+import org.sonar.batch.protocol.output.BatchReportReader;
 import org.sonar.batch.protocol.output.BatchReportWriter;
 import org.sonar.batch.protocol.output.FileStructure;
 
+import java.io.File;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class ComponentsPublisherTest {
@@ -40,9 +47,16 @@ public class ComponentsPublisherTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
-  ResourceCache resourceCache = new ResourceCache();
-  ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache);
+  private ProjectReactor reactor;
+  private ResourceCache resourceCache;
+  private ComponentsPublisher publisher;
+
+  @Before
+  public void prepare() {
+    reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
+    resourceCache = new ResourceCache();
+    publisher = new ComponentsPublisher(reactor, resourceCache);
+  }
 
   @Test
   public void add_components_to_report() throws Exception {
@@ -56,6 +70,7 @@ public class ComponentsPublisherTest {
     module1.setParent(root);
     module1.setId(2).setUuid("MODULE_UUID");
     resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
+    reactor.getRoot().addSubProject(ProjectDefinition.create().setKey("module1"));
 
     Directory dir = Directory.create("src");
     dir.setEffectiveKey("foo:src");
@@ -77,7 +92,8 @@ public class ComponentsPublisherTest {
     testFile.setId(6).setUuid("TEST_FILE_UUID");
     resourceCache.add(testFile, dir).setSnapshot(new Snapshot().setId(16));
 
-    BatchReportWriter writer = new BatchReportWriter(temp.newFolder());
+    File outputDir = temp.newFolder();
+    BatchReportWriter writer = new BatchReportWriter(outputDir);
     publisher.publish(writer);
 
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue();
@@ -89,5 +105,53 @@ public class ComponentsPublisherTest {
 
     // no such reference
     assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse();
+
+    BatchReportReader reader = new BatchReportReader(outputDir);
+    Component rootProtobuf = reader.readComponent(1);
+    assertThat(rootProtobuf.getLinksCount()).isEqualTo(0);
+
+  }
+
+  @Test
+  public void add_components_with_links() throws Exception {
+    // inputs
+    Project root = new Project("foo").setName("Root project")
+      .setAnalysisDate(DateUtils.parseDate(("2012-12-12")));
+    root.setId(1).setUuid("PROJECT_UUID");
+    resourceCache.add(root, null).setSnapshot(new Snapshot().setId(11));
+    reactor.getRoot().properties().put(CoreProperties.LINKS_HOME_PAGE, "http://home");
+
+    Project module1 = new Project("module1").setName("Module1");
+    module1.setParent(root);
+    module1.setId(2).setUuid("MODULE_UUID");
+    resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
+    ProjectDefinition moduleDef = ProjectDefinition.create().setKey("module1");
+    moduleDef.properties().put(CoreProperties.LINKS_CI, "http://ci");
+    reactor.getRoot().addSubProject(moduleDef);
+
+    Directory dir = Directory.create("src");
+    dir.setEffectiveKey("foo:src");
+    dir.setId(3).setUuid("DIR_UUID");
+    resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13));
+
+    org.sonar.api.resources.File file = org.sonar.api.resources.File.create("src/Foo.java", Java.INSTANCE, false);
+    file.setEffectiveKey("foo:src/Foo.java");
+    file.setId(4).setUuid("FILE_UUID");
+    resourceCache.add(file, dir).setSnapshot(new Snapshot().setId(14));
+
+    File outputDir = temp.newFolder();
+    BatchReportWriter writer = new BatchReportWriter(outputDir);
+    publisher.publish(writer);
+
+    BatchReportReader reader = new BatchReportReader(outputDir);
+    Component rootProtobuf = reader.readComponent(1);
+    assertThat(rootProtobuf.getLinksCount()).isEqualTo(1);
+    assertThat(rootProtobuf.getLinks(0).getType()).isEqualTo(ComponentLinkType.HOME);
+    assertThat(rootProtobuf.getLinks(0).getHref()).isEqualTo("http://home");
+
+    Component module1Protobuf = reader.readComponent(2);
+    assertThat(module1Protobuf.getLinksCount()).isEqualTo(1);
+    assertThat(module1Protobuf.getLinks(0).getType()).isEqualTo(ComponentLinkType.CI);
+    assertThat(module1Protobuf.getLinks(0).getHref()).isEqualTo("http://ci");
   }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/sensor/ProjectLinksSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/sensor/ProjectLinksSensorTest.java
deleted file mode 100644 (file)
index 6e44bc5..0000000
+++ /dev/null
@@ -1,105 +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.scan.sensor;
-
-import org.sonar.batch.scan.sensor.ProjectLinksSensor;
-
-import org.apache.commons.lang.StringUtils;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-import org.sonar.core.i18n.DefaultI18n;
-
-import java.util.Locale;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ProjectLinksSensorTest {
-
-  @Test
-  public void testToString() {
-    assertThat(new ProjectLinksSensor(null, null, null).toString()).isEqualTo("ProjectLinksSensor");
-  }
-
-  @Test
-  public void shouldNotExecuteInPreview() {
-    Project project = mock(Project.class);
-    AnalysisMode analysisMode = mock(AnalysisMode.class);
-    assertThat(new ProjectLinksSensor(null, null, analysisMode).shouldExecuteOnProject(project)).isTrue();
-    when(analysisMode.isPreview()).thenReturn(true);
-    assertThat(new ProjectLinksSensor(null, null, analysisMode).shouldExecuteOnProject(project)).isFalse();
-  }
-
-  @Test
-  public void shouldSaveLinks() {
-    Settings settings = new Settings();
-    settings.setProperty(CoreProperties.LINKS_HOME_PAGE, "http://home");
-    DefaultI18n defaultI18n = mock(DefaultI18n.class);
-    when(defaultI18n.message(Locale.getDefault(), "project_links.homepage", CoreProperties.LINKS_HOME_PAGE)).thenReturn("HOME");
-    Project project = mock(Project.class);
-    SensorContext context = mock(SensorContext.class);
-
-    new ProjectLinksSensor(settings, defaultI18n, null).analyse(project, context);
-
-    verify(context).saveLink(argThat(new MatchLink("homepage", "HOME", "http://home")));
-  }
-
-  @Test
-  public void shouldDeleteLink() {
-    Settings settings = new Settings();
-    settings.setProperty(CoreProperties.LINKS_HOME_PAGE, "");
-    DefaultI18n defaultI18n = mock(DefaultI18n.class);
-    when(defaultI18n.message(Locale.getDefault(), "project_links.homepage", CoreProperties.LINKS_HOME_PAGE)).thenReturn("HOME");
-    Project project = mock(Project.class);
-    SensorContext context = mock(SensorContext.class);
-
-    new ProjectLinksSensor(settings, defaultI18n, null).analyse(project, context);
-
-    verify(context).deleteLink("homepage");
-  }
-
-  private class MatchLink extends ArgumentMatcher<ProjectLink> {
-    private String key;
-    private String name;
-    private String url;
-
-    private MatchLink(String key, String name, String url) {
-      this.key = key;
-      this.name = name;
-      this.url = url;
-    }
-
-    @Override
-    public boolean matches(Object o) {
-      ProjectLink link = (ProjectLink) o;
-      return StringUtils.equals(link.getHref(), url) && StringUtils.equals(link.getKey(), key) && StringUtils.equals(link.getName(), name);
-    }
-  }
-
-}
index 099bd1c8c9e36c1868c858a8c551c6677f1e0848..016767d84fbfe4b7f95894b72168514efbcf4c59 100644 (file)
@@ -17,7 +17,6 @@
     <class>org.sonar.api.database.model.ResourceModel</class>
     <class>org.sonar.api.rules.Rule</class>
     <class>org.sonar.api.rules.RuleParam</class>
-    <class>org.sonar.api.resources.ProjectLink</class>
     <class>org.sonar.api.batch.Event</class>
 
     <exclude-unlisted-classes>true</exclude-unlisted-classes>
index a9eb25628783a4520a709b497106355105d7564e..25a7521cdd70257837a218500aa20beb46a21682 100644 (file)
@@ -25,7 +25,6 @@ import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.ProjectLink;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Violation;
 
@@ -227,19 +226,6 @@ public interface SensorContext extends org.sonar.api.batch.sensor.SensorContext
   @Deprecated
   void saveSource(Resource reference, String source);
 
-  // ----------- LINKS --------------
-
-  /**
-   * add a link to an external page like project homepage, sources (subversion, ...), continuous integration server... Example :
-   * context.addLink(new ProjectLink("maven_site, "Maven site", "http://my.maven.com)
-   */
-  void saveLink(ProjectLink link);
-
-  /**
-   * remove a link. It does not fail if key is unknown.
-   */
-  void deleteLink(String key);
-
   // ----------- EVENTS --------------
 
   /**
index 6714ed9c1bb0cd2979f8dea1ef4a3b18e1887d09..a9d32eb7595d6a245e4e7872d24df470a56b7095 100644 (file)
@@ -24,7 +24,6 @@ import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Violation;
 import org.sonar.graph.DirectedGraphAccessor;
@@ -148,10 +147,6 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
 
   public abstract Set<Dependency> getDependencies();
 
-  public abstract void addLink(ProjectLink link);
-
-  public abstract void deleteLink(String key);
-
   public abstract List<Event> getEvents(Resource resource);
 
   public abstract void deleteEvent(Event event);
index 3f0f2469cbbd93daad7aa316ed66fff7a6ace440..d8b080cdab4775cdc4f1e8cf2b3a8a3f5ec5ea0d 100644 (file)
@@ -23,18 +23,14 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.commons.lang.builder.ToStringBuilder;
-import org.hibernate.annotations.BatchSize;
 import org.sonar.api.database.BaseIdentifiable;
 import org.sonar.api.resources.Language;
-import org.sonar.api.resources.ProjectLink;
 import org.sonar.api.resources.Resource;
 
 import javax.annotation.Nullable;
 import javax.persistence.*;
 
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
 
 /**
  * Class to map resource with hibernate model
@@ -94,11 +90,6 @@ public class ResourceModel extends BaseIdentifiable implements Cloneable {
   @Column(name = "created_at", updatable = true, nullable = true)
   private Date createdAt;
 
-  @OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
-  @JoinColumn(name = "component_uuid")
-  @BatchSize(size = 8)
-  private List<ProjectLink> projectLinks = new ArrayList<ProjectLink>();
-
   @Column(name = "uuid", updatable = false, nullable = true, length = 50)
   private String uuid;
 
@@ -143,29 +134,6 @@ public class ResourceModel extends BaseIdentifiable implements Cloneable {
     this.qualifier = qualifier;
   }
 
-  /**
-   * Only available at project level.
-   */
-  public List<ProjectLink> getProjectLinks() {
-    return projectLinks;
-  }
-
-  public void setProjectLinks(List<ProjectLink> projectLinks) {
-    this.projectLinks = projectLinks;
-  }
-
-  /**
-   * @return a project link given its key if exists, null otherwise
-   */
-  public ProjectLink getProjectLink(String key) {
-    for (ProjectLink projectLink : projectLinks) {
-      if (key.equals(projectLink.getKey())) {
-        return projectLink;
-      }
-    }
-    return null;
-  }
-
   /**
    * Only available at project level.
    */
@@ -405,7 +373,6 @@ public class ResourceModel extends BaseIdentifiable implements Cloneable {
     clone.setDescription(getDescription());
     clone.setDeprecatedKey(getDeprecatedKey());
     clone.setEnabled(getEnabled());
-    clone.setProjectLinks(getProjectLinks());
     clone.setLanguageKey(getLanguageKey());
     clone.setCopyResourceId(getCopyResourceId());
     clone.setLongName(getLongName());
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ProjectLink.java
deleted file mode 100644 (file)
index 3e4f276..0000000
+++ /dev/null
@@ -1,130 +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.api.resources;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.database.BaseIdentifiable;
-import org.sonar.api.database.model.ResourceModel;
-
-import javax.persistence.*;
-
-/**
- * @since 1.10
- */
-@Entity(name = "ProjectLink")
-@Table(name = "project_links")
-public class ProjectLink extends BaseIdentifiable {
-
-  public static final int NAME_COLUMN_SIZE = 128;
-  public static final int HREF_COLUMN_SIZE = 2048;
-
-  @ManyToOne(fetch = FetchType.LAZY)
-  @JoinColumn(name = "component_uuid", referencedColumnName = "uuid", updatable = false, nullable = false)
-  private ResourceModel resource;
-
-  @Column(name = "link_type", updatable = true, nullable = true, length = 20)
-  private String key;
-
-  @Column(name = "name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE)
-  private String name;
-
-  @Column(name = "href", updatable = true, nullable = false, length = HREF_COLUMN_SIZE)
-  private String href;
-
-  public ProjectLink() {
-  }
-
-  public ProjectLink(String key, String name, String href) {
-    this.key = key;
-    setName(name);
-    setHref(href);
-  }
-
-  public ResourceModel getResource() {
-    return resource;
-  }
-
-  public void setResource(ResourceModel resource) {
-    this.resource = resource;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public final void setName(String name) {
-    this.name = StringUtils.abbreviate(name, NAME_COLUMN_SIZE);
-  }
-
-  public String getHref() {
-    return href;
-  }
-
-  public final void setHref(String href) {
-    if (href == null) {
-      throw new IllegalArgumentException("ProjectLink.href can not be null");
-    }
-    this.href = StringUtils.abbreviate(href, HREF_COLUMN_SIZE);
-  }
-
-  public String getKey() {
-    return key;
-  }
-
-  public void setKey(String key) {
-    this.key = key;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    ProjectLink that = (ProjectLink) o;
-    if (!key.equals(that.key)) {
-      return false;
-    }
-    return resource.equals(that.resource);
-
-  }
-
-  @Override
-  public int hashCode() {
-    int result = resource != null ? resource.hashCode() : 0;
-    result = 31 * result + key.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
-  }
-
-  public void copyFieldsFrom(ProjectLink link) {
-    this.name = link.getName();
-    this.href = link.getHref();
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/resources/ProjectLinkTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/resources/ProjectLinkTest.java
deleted file mode 100644 (file)
index b193513..0000000
+++ /dev/null
@@ -1,63 +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.api.resources;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class ProjectLinkTest {
-
-  ProjectLink link = new ProjectLink();
-
-  @Test
-  public void testSetName() {
-    link.setName(overFillString(ProjectLink.NAME_COLUMN_SIZE));
-    assertAbbreviated(ProjectLink.NAME_COLUMN_SIZE, link.getName());
-  }
-
-  @Test
-  public void testSetHref() {
-    link.setHref(overFillString(ProjectLink.HREF_COLUMN_SIZE));
-    assertAbbreviated(ProjectLink.HREF_COLUMN_SIZE, link.getHref());
-  }
-
-  @Test
-  public void testConstructor() {
-    link = new ProjectLink("home",
-      overFillString(ProjectLink.NAME_COLUMN_SIZE),
-      overFillString(ProjectLink.HREF_COLUMN_SIZE));
-    assertAbbreviated(ProjectLink.NAME_COLUMN_SIZE, link.getName());
-    assertAbbreviated(ProjectLink.HREF_COLUMN_SIZE, link.getHref());
-  }
-
-  private String overFillString(int maxSize) {
-    StringBuilder overFilled = new StringBuilder();
-    for (int i = 0; i < 50 + maxSize; i++) {
-      overFilled.append("x");
-    }
-    return overFilled.toString();
-  }
-
-  private void assertAbbreviated(int maxSize, String value) {
-    assertEquals(maxSize, value.length());
-    assertEquals('.', value.charAt(maxSize - 1));
-  }
-}