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.xoo.lang; 021 022 import com.google.common.annotations.VisibleForTesting; 023 import com.google.common.base.Charsets; 024 import org.apache.commons.io.FileUtils; 025 import org.apache.commons.lang.StringUtils; 026 import org.slf4j.Logger; 027 import org.slf4j.LoggerFactory; 028 import org.sonar.api.batch.fs.FileSystem; 029 import org.sonar.api.batch.fs.InputFile; 030 import org.sonar.api.batch.sensor.Sensor; 031 import org.sonar.api.batch.sensor.SensorContext; 032 import org.sonar.api.batch.sensor.SensorDescriptor; 033 import org.sonar.api.measures.CoreMetrics; 034 import org.sonar.api.measures.FileLinesContext; 035 import org.sonar.api.measures.FileLinesContextFactory; 036 import org.sonar.api.utils.DateUtils; 037 import org.sonar.xoo.Xoo; 038 039 import java.io.File; 040 import java.io.IOException; 041 import java.util.Date; 042 import java.util.List; 043 044 public class ScmActivitySensor implements Sensor { 045 046 private static final Logger LOG = LoggerFactory.getLogger(ScmActivitySensor.class); 047 048 private static final String SCM_EXTENSION = ".scm"; 049 050 private final FileSystem fs; 051 private final FileLinesContextFactory fileLinesContextFactory; 052 053 public ScmActivitySensor(FileLinesContextFactory fileLinesContextFactory, FileSystem fileSystem) { 054 this.fs = fileSystem; 055 this.fileLinesContextFactory = fileLinesContextFactory; 056 } 057 058 @Override 059 public void describe(SensorDescriptor descriptor) { 060 descriptor 061 .name(this.getClass().getSimpleName()) 062 .provides(CoreMetrics.SCM_AUTHORS_BY_LINE, 063 CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, 064 CoreMetrics.SCM_REVISIONS_BY_LINE) 065 .workOnLanguages(Xoo.KEY); 066 } 067 068 @Override 069 public void execute(SensorContext context) { 070 for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(Xoo.KEY))) { 071 processFile(inputFile); 072 } 073 074 } 075 076 @VisibleForTesting 077 protected void processFile(InputFile inputFile) { 078 File ioFile = inputFile.file(); 079 File scmDataFile = new java.io.File(ioFile.getParentFile(), ioFile.getName() + SCM_EXTENSION); 080 if (!scmDataFile.exists()) { 081 LOG.debug("Skipping SCM data injection for " + inputFile.relativePath()); 082 return; 083 } 084 085 FileLinesContext fileLinesContext = fileLinesContextFactory.createFor(inputFile); 086 try { 087 List<String> lines = FileUtils.readLines(scmDataFile, Charsets.UTF_8.name()); 088 int lineNumber = 0; 089 for (String line : lines) { 090 lineNumber++; 091 if (StringUtils.isNotBlank(line)) { 092 // revision,author,dateTime 093 String[] fields = StringUtils.split(line, ','); 094 if (fields.length < 3) { 095 throw new IllegalStateException("Not enough fields on line " + lineNumber); 096 } 097 String revision = fields[0]; 098 String author = fields[1]; 099 // Will throw an exception, when date is not in format "yyyy-MM-dd" 100 Date date = DateUtils.parseDate(fields[2]); 101 102 fileLinesContext.setStringValue(CoreMetrics.SCM_REVISIONS_BY_LINE_KEY, lineNumber, revision); 103 fileLinesContext.setStringValue(CoreMetrics.SCM_AUTHORS_BY_LINE_KEY, lineNumber, author); 104 fileLinesContext.setStringValue(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, lineNumber, DateUtils.formatDateTime(date)); 105 } 106 } 107 } catch (IOException e) { 108 throw new IllegalStateException(e); 109 } 110 fileLinesContext.save(); 111 } 112 }