001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar 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     * Sonar 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
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.plugins.checkstyle;
021    
022    import com.puppycrawl.tools.checkstyle.api.AuditEvent;
023    import com.puppycrawl.tools.checkstyle.api.AuditListener;
024    import org.apache.commons.lang.StringUtils;
025    import org.sonar.api.BatchExtension;
026    import org.sonar.api.batch.SensorContext;
027    import org.sonar.api.resources.JavaFile;
028    import org.sonar.api.resources.Project;
029    import org.sonar.api.resources.Resource;
030    import org.sonar.api.rules.Rule;
031    import org.sonar.api.rules.RuleFinder;
032    import org.sonar.api.rules.Violation;
033    
034    /**
035     * @since 2.3
036     */
037    public class CheckstyleAuditListener implements AuditListener, BatchExtension {
038    
039      private final SensorContext context;
040      private final Project project;
041      private final RuleFinder ruleFinder;
042      private Resource currentResource = null;
043    
044      public CheckstyleAuditListener(SensorContext context, Project project, RuleFinder ruleFinder) {
045        this.context = context;
046        this.project = project;
047        this.ruleFinder = ruleFinder;
048      }
049    
050      public void auditStarted(AuditEvent event) {
051    
052      }
053    
054      public void auditFinished(AuditEvent event) {
055    
056      }
057    
058      public void fileStarted(AuditEvent event) {
059    
060      }
061    
062      public void fileFinished(AuditEvent event) {
063        currentResource = null;
064      }
065    
066      public void addError(AuditEvent event) {
067        String ruleKey = getRuleKey(event);
068        if (ruleKey != null) {
069          Rule rule = ruleFinder.findByKey(CheckstyleConstants.REPOSITORY_KEY, ruleKey);
070          if (rule != null) {
071            initResource(event);
072            Violation violation = Violation.create(rule, currentResource)
073                .setLineId(getLineId(event))
074                .setMessage(getMessage(event));
075            context.saveViolation(violation);
076          }
077        }
078      }
079    
080      private void initResource(AuditEvent event) {
081        if (currentResource == null) {
082          String absoluteFilename = event.getFileName();
083          currentResource = JavaFile.fromAbsolutePath(absoluteFilename, project.getFileSystem().getSourceDirs(), false);
084        }
085      }
086    
087      static String getRuleKey(AuditEvent event) {
088        String key = null;
089        try {
090          key = event.getModuleId();
091        } catch (Exception e) {
092          // checkstyle throws a NullPointer if the message is not set
093        }
094        if (StringUtils.isBlank(key)) {
095          try {
096            key = event.getSourceName();
097          } catch (Exception e) {
098            // checkstyle can throw a NullPointer if the message is not set
099          }
100        }
101        return key;
102      }
103    
104      static String getMessage(AuditEvent event) {
105        try {
106          return event.getMessage();
107    
108        } catch (Exception e) {
109          // checkstyle can throw a NullPointer if the message is not set
110          return null;
111        }
112      }
113    
114      static Integer getLineId(AuditEvent event) {
115        try {
116          int line = event.getLine();
117          // checkstyle returns 0 if there is no relation to a file content, but we use null
118          return line == 0 ? null : line;
119    
120        } catch (Exception e) {
121          // checkstyle can throw a NullPointerException if the message is not set
122          return null;
123        }
124      }
125    
126      public void addException(AuditEvent event, Throwable throwable) {
127        // TODO waiting for sonar technical events ?
128      }
129    
130      Resource getCurrentResource() {
131        return currentResource;
132      }
133    }