001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * SonarQube is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.batch.scan2;
021    
022    import com.google.common.base.Strings;
023    import org.sonar.api.batch.bootstrap.ProjectDefinition;
024    import org.sonar.api.batch.fs.FileSystem;
025    import org.sonar.api.batch.fs.InputFile;
026    import org.sonar.api.batch.measure.Metric;
027    import org.sonar.api.batch.rule.ActiveRules;
028    import org.sonar.api.batch.rule.internal.DefaultActiveRule;
029    import org.sonar.api.batch.sensor.issue.Issue;
030    import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
031    import org.sonar.api.batch.sensor.measure.Measure;
032    import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
033    import org.sonar.api.config.Settings;
034    import org.sonar.api.rule.RuleKey;
035    import org.sonar.api.utils.MessageException;
036    import org.sonar.batch.duplication.BlockCache;
037    import org.sonar.batch.duplication.DuplicationCache;
038    import org.sonar.batch.index.ComponentDataCache;
039    import org.sonar.batch.issue.IssueFilters;
040    import org.sonar.batch.scan.SensorContextAdaptor;
041    import org.sonar.core.component.ComponentKeys;
042    
043    import java.io.Serializable;
044    
045    public class DefaultSensorContext extends BaseSensorContext {
046    
047      private final AnalyzerMeasureCache measureCache;
048      private final AnalyzerIssueCache issueCache;
049      private final ProjectDefinition def;
050      private final ActiveRules activeRules;
051      private final IssueFilters issueFilters;
052    
053      public DefaultSensorContext(ProjectDefinition def, AnalyzerMeasureCache measureCache, AnalyzerIssueCache issueCache,
054        Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache,
055        BlockCache blockCache, DuplicationCache duplicationCache) {
056        super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
057        this.def = def;
058        this.measureCache = measureCache;
059        this.issueCache = issueCache;
060        this.activeRules = activeRules;
061        this.issueFilters = issueFilters;
062      }
063    
064      @Override
065      public Measure getMeasure(String metricKey) {
066        return measureCache.byMetric(def.getKey(), def.getKey(), metricKey);
067      }
068    
069      @Override
070      public <G extends Serializable> Measure<G> getMeasure(Metric<G> metric) {
071        return (Measure<G>) measureCache.byMetric(def.getKey(), def.getKey(), metric.key());
072      }
073    
074      @Override
075      public Measure getMeasure(InputFile file, String metricKey) {
076        return measureCache.byMetric(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), file), metricKey);
077      }
078    
079      @Override
080      public <G extends Serializable> Measure<G> getMeasure(InputFile file, Metric<G> metric) {
081        return (Measure<G>) measureCache.byMetric(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), file), metric.key());
082      }
083    
084      @Override
085      public void addMeasure(Measure<?> measure) {
086        InputFile inputFile = measure.inputFile();
087        if (inputFile != null) {
088          measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), inputFile), (DefaultMeasure) measure);
089        } else {
090          measureCache.put(def.getKey(), def.getKey(), (DefaultMeasure) measure);
091        }
092      }
093    
094      @Override
095      public boolean addIssue(Issue issue) {
096        String resourceKey;
097        if (issue.inputPath() != null) {
098          resourceKey = ComponentKeys.createEffectiveKey(def.getKey(), issue.inputPath());
099        } else {
100          resourceKey = def.getKey();
101        }
102        RuleKey ruleKey = issue.ruleKey();
103        DefaultActiveRule activeRule = (DefaultActiveRule) activeRules.find(ruleKey);
104        if (activeRule == null) {
105          // rule does not exist or is not enabled -> ignore the issue
106          return false;
107        }
108        if (Strings.isNullOrEmpty(activeRule.name()) && Strings.isNullOrEmpty(issue.message())) {
109          throw MessageException.of(String.format("The rule '%s' has no name and the related issue has no message.", ruleKey));
110        }
111    
112        updateIssue((DefaultIssue) issue, activeRule);
113    
114        if (issueFilters.accept(SensorContextAdaptor.toDefaultIssue(def.getKey(), resourceKey, issue), null)) {
115          issueCache.put(def.getKey(), resourceKey, (DefaultIssue) issue);
116          return true;
117        }
118    
119        return false;
120      }
121    
122      private void updateIssue(DefaultIssue issue, DefaultActiveRule activeRule) {
123        if (Strings.isNullOrEmpty(issue.message())) {
124          issue.setMessage(activeRule.name());
125        }
126    
127        if (issue.severity() == null) {
128          issue.setSeverity(activeRule.severity());
129        }
130      }
131    
132    }