//
// Copyright (C) 2012 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.conformanceChecker;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.JPF;
import gov.nasa.jpf.conformanceChecker.checkers.Checker;
import gov.nasa.jpf.conformanceChecker.providers.ModelClassProvider;
import gov.nasa.jpf.conformanceChecker.providers.ProviderFactory;
import gov.nasa.jpf.conformanceChecker.reporters.Reporter;
import gov.nasa.jpf.jvm.ClassInfo;
import gov.nasa.jpf.util.MethodSpec;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
/**
* This is the main class that performs all the checking work and
* reports it. It uses classes coming from the checkers package
* and classes from the reporters package.
*
* Configuration properties
* ------------------------
*
* The following properties should be given in the configuration file
*
* - {@value #CHECKERS_PROP} the list of checkers to use
* - {@value #REPORTERS_PROP} the list of reporters to use.
*
* @author Matteo Ceccarello <matteo.ceccarello AT gmail.com>
*
*/
public class ConformanceChecker {
public static final String CHECKERS_PROP = "conformance-checker.checkers";
public static final String REPORTERS_PROP = "conformance-checker.reporters";
public static final String CLASSES = "conformance-checker.classes";
private static Logger logger = JPF.getLogger(ConformanceChecker.class.getName());
public static void main(String[] args) {
Config conf = JPF.createConfig(args);
ProviderFactory.init(conf);
ModelClassProvider modelProvider = ProviderFactory.getModelProvider();
List<Reporter> reporters = buildReportersList(conf);
List<Checker> checkers = buildCheckersList(conf, reporters);
Collection<MethodSpec> specs = getSpecs(conf);
for (ClassInfo model : modelProvider.loadClassInfos(specs)) {
checkModelClass(model, checkers);
}
for (Reporter reporter : reporters) {
reporter.close();
}
}
/**
* Checks a model class with all configured checkers
* @param cls the class to check
* @param checkers the checkers to use
*/
public static void checkModelClass(ClassInfo cls, List<Checker> checkers) {
for (Checker checker : checkers) {
checker.check(cls);
}
}
public static Collection<MethodSpec> getSpecs(Config conf) {
LinkedList<MethodSpec> specs = new LinkedList<MethodSpec>();
String[] specsArray = conf.getStringArray(CLASSES);
if(specsArray == null)
return specs;
for (String spec : specsArray) {
specs.add(MethodSpec.createMethodSpec(spec));
}
return specs;
}
/**
* Builds a list of {@link Checker} instances from the property {@link #CHECKERS_PROP}.
* @param conf the {@link Config} object containing the configuration in use
* @param reporters the reporters to be used by checkers.
* @return the list of checkers that are going to be used.
*/
public static List<Checker> buildCheckersList(Config conf, List<Reporter> reporters) {
List<Checker> checkers = conf.getInstances(CHECKERS_PROP, Checker.class,
new Class[]{List.class},
new Object[]{reporters});
if(checkers == null || checkers.size() == 0){
logger.warning("No checkers are configured, hence no checking will be performed.\n" +
"Please configure at least one checker using the property \n" +
"\t"+CHECKERS_PROP+"\n" +
"in your configuration file");
return new LinkedList<Checker>();
}
String info = "";
for (Checker checker : checkers) {
info += "\n\t" + checker.getClass().getSimpleName();
}
logger.info("Loaded the following checkers" + info);
return checkers;
}
/**
* Builds the list o reporters that have to be used, based on values
* found in the given {@link Config} object.
* @param conf the configuration to use
* @return the list of checkers that are going to be used.
*/
public static List<Reporter> buildReportersList(Config conf) {
List<Reporter> reporters = conf.getInstances(REPORTERS_PROP, Reporter.class,
new Class[]{Config.class},
new Object[]{conf});
if(reporters == null || reporters.size() == 0){
logger.warning("No reporters are configured, hence no reporting of the check\n" +
"run will be generated.\n" +
"Please configure at least one reporter using the property \n" +
"\t"+REPORTERS_PROP+"\n" +
"in your configuration file");
return new LinkedList<Reporter>();
}
String info = "";
for (Reporter reporter : reporters) {
info += "\n\t" + reporter.getClass().getSimpleName();
}
logger.info("Loaded the following reporters" + info);
return reporters;
}
}