Newer
Older
/*
* Copyright 2020 ETSI
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import fr.mines_stetienne.ci.saref.SAREFPipelineException;
import fr.mines_stetienne.ci.saref.managers.RepositoryManager;
/**
* Checks TS 103 673 Clause 9.2: Structure of the SAREF project version directory
*
*/
public class Clause_9_2_Checker extends AbstractClauseChecker {
private static enum MESSAGE {
requirements, ontology, tests, examples, documentation, readme_missing, gitignore_missing, gitignore_incomplete, gitignore_ioexception,
license_missing, license_firstline, license_year, license_line, license_overcomplete,
license_incomplete, license_ioexception, securityexception;
}
private static final Set<String> gitignoreLines = new HashSet<>(
Arrays.asList("target", "*~", ".DS_Store", "catalog-v001.xml", "saref-pipeline.jar"));
public Clause_9_2_Checker(RepositoryManager repositoryManager) {
super(repositoryManager, Clause_9_2_Checker.class);
}
@Override
public void checkClause() throws SAREFPipelineException {
checkReadme();
checkGitignore();
checkLICENSE();
checkDirectory("requirements", MESSAGE.requirements);
checkDirectory("ontology", MESSAGE.ontology);
checkDirectory("tests", MESSAGE.tests);
checkDirectory("examples", MESSAGE.examples);
checkDirectory("documentation", MESSAGE.documentation);
}
private void checkReadme() {
final File file = new File(repository.getDirectory(), "README.md");
if (file.isFile()) {
return;
}
logError(getMessage(MESSAGE.readme_missing));
}
private void checkGitignore() throws SAREFPipelineException {
final File file = new File(repository.getDirectory(), ".gitignore");
if (!file.isFile()) {
logError(getMessage(MESSAGE.gitignore_missing));
return;
}
try (BufferedReader br = Files.newBufferedReader(file.toPath())) {
for (String line = br.readLine(); line != null; line = br.readLine()) {
gitignoreLines.remove(line);
}
if (!gitignoreLines.isEmpty()) {
logError(getMessage(MESSAGE.gitignore_incomplete, gitignoreLines.toString()));
logError(getMessage(MESSAGE.gitignore_ioexception, ex));
}
}
private void checkLICENSE() throws SAREFPipelineException {
final File licenseFile = new File(repository.getDirectory(), "LICENSE");
if (!licenseFile.exists()) {
logError(getMessage(MESSAGE.license_missing));
return;
}
InputStream licenseModelFile = Clause_9_2_Checker.class.getClassLoader()
.getResourceAsStream("LICENSE_MODEL");
try (BufferedReader licenseModelFileReader = new BufferedReader(new InputStreamReader(licenseModelFile));
BufferedReader licenseFileReader = new BufferedReader(new FileReader(licenseFile));) {
// first line
String modelLine = licenseModelFileReader.readLine();
String licenseLine = licenseFileReader.readLine();
String regex = modelLine.replaceFirst("YYYY", "(?<year>\\\\d{4})");
Pattern pattern = Pattern.compile(String.format("^%s$", regex));
Matcher regexMatcher = pattern.matcher(licenseLine);
if (!regexMatcher.find()) {
logError(getMessage(MESSAGE.license_firstline, licenseLine, modelLine));
return;
}
int year = Integer.parseInt(regexMatcher.group("year"));
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
if (year < 2015 || year > currentYear) {
logWarning(getMessage(MESSAGE.license_year, 2015, currentYear));
return;
}
int i = 1;
modelLine = licenseModelFileReader.readLine();
licenseLine = licenseFileReader.readLine();
while (modelLine != null && licenseLine != null) {
i++;
if (!modelLine.equals(licenseLine)) {
logError(getMessage(MESSAGE.license_line, i, modelLine));
return;
}
modelLine = licenseModelFileReader.readLine();
licenseLine = licenseFileReader.readLine();
}
if (modelLine == null && licenseLine != null) {
logError(getMessage(MESSAGE.license_overcomplete, i, modelLine));
return;
}
if (modelLine != null && licenseLine == null) {
logError(getMessage(MESSAGE.license_incomplete, i));
logError(getMessage(MESSAGE.license_ioexception, ex));
}
}
private void checkDirectory(String dirName, MESSAGE message) throws SAREFPipelineException {
final File dir = new File(repository.getDirectory(), dirName);
try {
if (!dir.isDirectory()) {
String msg = getMessage(message, dirName);
logError(getMessage(MESSAGE.securityexception, ex));