Package org.sonar.batch.scan

Source Code of org.sonar.batch.scan.SensorContextAdapter

/*
* 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;

import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.Issue.Severity;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.test.TestCaseCoverage;
import org.sonar.api.batch.sensor.test.TestCaseExecution;
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.design.Dependency;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.measures.Formula;
import org.sonar.api.measures.MetricFinder;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.measures.SumChildDistributionFormula;
import org.sonar.api.resources.Directory;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.Scopes;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.test.MutableTestCase;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.api.test.MutableTestable;
import org.sonar.api.test.Testable;
import org.sonar.batch.duplication.BlockCache;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.scan2.BaseSensorContext;
import org.sonar.core.component.ComponentKeys;

/**
* Implements {@link SensorContext} but forward everything to {@link org.sonar.api.batch.SensorContext} for backward compatibility.
* Will be dropped once old {@link Sensor} API is dropped.
*
*/
public class SensorContextAdapter extends BaseSensorContext {

  private static final String USES = "USES";
  private final org.sonar.api.batch.SensorContext sensorContext;
  private final MetricFinder metricFinder;
  private final Project project;
  private final ResourcePerspectives perspectives;
  private final SonarIndex sonarIndex;

  public SensorContextAdapter(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives,
    Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
    DuplicationCache duplicationCache, SonarIndex sonarIndex) {
    super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
    this.sensorContext = sensorContext;
    this.metricFinder = metricFinder;
    this.project = project;
    this.perspectives = perspectives;
    this.sonarIndex = sonarIndex;
  }

  private org.sonar.api.measures.Metric findMetricOrFail(String metricKey) {
    org.sonar.api.measures.Metric m = metricFinder.findByKey(metricKey);
    if (m == null) {
      throw new IllegalStateException("Unknow metric with key: " + metricKey);
    }
    return m;
  }

  @Override
  public void store(Measure newMeasure) {
    DefaultMeasure measure = (DefaultMeasure) newMeasure;
    org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
    org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
    setValueAccordingToMetricType(newMeasure, m, measureToSave);
    measureToSave.setFromCore(measure.isFromCore());
    if (newMeasure.inputFile() != null) {
      Formula formula = newMeasure.metric() instanceof org.sonar.api.measures.Metric ?
        ((org.sonar.api.measures.Metric) newMeasure.metric()).getFormula() : null;
      if (formula instanceof SumChildDistributionFormula
        && !Scopes.isHigherThanOrEquals(Scopes.FILE, ((SumChildDistributionFormula) formula).getMinimumScopeToPersist())) {
        measureToSave.setPersistenceMode(PersistenceMode.MEMORY);
      }
      sensorContext.saveMeasure(newMeasure.inputFile(), measureToSave);
    } else {
      sensorContext.saveMeasure(measureToSave);
    }
  }

  private void setValueAccordingToMetricType(Measure<?> measure, org.sonar.api.measures.Metric<?> m, org.sonar.api.measures.Measure measureToSave) {
    switch (m.getType()) {
      case BOOL:
        measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
        break;
      case INT:
      case MILLISEC:
        measureToSave.setValue(Double.valueOf((Integer) measure.value()));
        break;
      case FLOAT:
      case PERCENT:
      case RATING:
        measureToSave.setValue((Double) measure.value());
        break;
      case STRING:
      case LEVEL:
      case DATA:
      case DISTRIB:
        measureToSave.setData((String) measure.value());
        break;
      case WORK_DUR:
        measureToSave.setValue(Double.valueOf((Long) measure.value()));
        break;
      default:
        throw new UnsupportedOperationException("Unsupported type :" + m.getType());
    }
  }

  @Override
  public void store(Issue issue) {
    Resource r;
    InputPath inputPath = issue.inputPath();
    if (inputPath != null) {
      if (inputPath instanceof InputDir) {
        r = Directory.create(inputPath.relativePath());
      } else {
        r = File.create(inputPath.relativePath());
      }
    } else {
      r = project;
    }
    Issuable issuable = perspectives.as(Issuable.class, r);
    if (issuable == null) {
      return;
    }
    issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
  }

  public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
    Severity overridenSeverity = issue.overridenSeverity();
    return new org.sonar.core.issue.DefaultIssueBuilder()
      .componentKey(componentKey)
      .projectKey(projectKey)
      .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
      .effortToFix(issue.effortToFix())
      .line(issue.line())
      .message(issue.message())
      .severity(overridenSeverity != null ? overridenSeverity.name() : null)
      .build();
  }

  @Override
  public void store(TestCaseExecution testCase) {
    File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile());
    MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
    if (testPlan != null) {
      testPlan
        .addTestCase(testCase.name())
        .setDurationInMs(testCase.durationInMs())
        .setType(testCase.type().name())
        .setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name()))
        .setMessage(testCase.message())
        .setStackTrace(testCase.stackTrace());
    }
  }

  @Override
  public void store(TestCaseCoverage testCaseCoverage) {
    File testRes = getTestResource(testCaseCoverage.testFile());
    File mainRes = getMainResource(testCaseCoverage.coveredFile());
    Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes);
    if (testAbleFile != null) {
      MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
      if (testPlan != null) {
        for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) {
          mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines());
        }
      } else {
        throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes);
      }
    } else {
      throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes);
    }
  }

  private File getTestResource(InputFile testFile) {
    File testRes = File.create(testFile.relativePath());
    testRes.setQualifier(Qualifiers.UNIT_TEST_FILE);
    // Reload
    testRes = sensorContext.getResource(testRes);
    if (testRes == null) {
      throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile);
    }
    return testRes;
  }

  private File getMainResource(InputFile mainFile) {
    File mainRes = File.create(mainFile.relativePath());
    // Reload
    mainRes = sensorContext.getResource(mainRes);
    if (mainRes == null) {
      throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes);
    }
    return mainRes;
  }

  private File getFile(InputFile file) {
    if (file.type() == InputFile.Type.MAIN) {
      return getMainResource(file);
    } else {
      return getTestResource(file);
    }
  }

  @Override
  public void store(org.sonar.api.batch.sensor.dependency.Dependency dep) {
    File fromResource = getFile(dep.from());
    File toResource = getFile(dep.to());
    if (sonarIndex.getEdge(fromResource, toResource) != null) {
      throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
    }
    Directory fromParent = fromResource.getParent();
    Directory toParent = toResource.getParent();
    Dependency parentDep = null;
    if (!fromParent.equals(toParent)) {
      parentDep = sonarIndex.getEdge(fromParent, toParent);
      if (parentDep != null) {
        parentDep.setWeight(parentDep.getWeight() + 1);
      } else {
        parentDep = new Dependency(fromParent, toParent).setUsage(USES).setWeight(1);
        parentDep = sensorContext.saveDependency(parentDep);
      }
    }
    sensorContext.saveDependency(new Dependency(fromResource, toResource)
      .setUsage(USES)
      .setWeight(dep.weight())
      .setParent(parentDep));
  }

}
TOP

Related Classes of org.sonar.batch.scan.SensorContextAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.