// // Copyright (C) 2011 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.util.json; import java.lang.reflect.Constructor; import java.util.HashMap; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPFException; import gov.nasa.jpf.vm.BooleanChoiceGenerator; import gov.nasa.jpf.vm.ChoiceGenerator; import gov.nasa.jpf.vm.VM; import gov.nasa.jpf.vm.choice.DoubleChoiceFromList; import gov.nasa.jpf.vm.choice.DoubleThresholdGenerator; import gov.nasa.jpf.vm.choice.IntChoiceFromSet; import gov.nasa.jpf.vm.choice.IntIntervalGenerator; import gov.nasa.jpf.vm.choice.RandomIntIntervalGenerator; /** * Singleton factory for creating CGCreators. * @author Ivan Mushketik */ public class CGCreatorFactory { private static CGCreatorFactory factory; ClassLoader loader = CGCreatorFactory.class.getClassLoader(); // Hash where key is a name that user can use in JSON document to set a // ChoiceGenerator and value is creator of ChoiceGenerator that uses Values[] // from JSON to creat CG @SuppressWarnings("serial") private HashMap<String, CGCreator> cgTable = new HashMap<String, CGCreator>() {{ put("TrueFalse", new BoolCGCreator()); put("IntSet", new IntFromSetCGCreator()); put("IntInterval", new IntIntervalCGCreator()); put("DoubleSet", new DoubleFromSetCGCreator()); put("DoubleThreshold", new DoubleThresholdGeneratorCGCreator()); put("RandomIntInerval", new RandomIntIntervalGeneratorCGCreator()); }}; private CGCreatorFactory() { Config config = VM.getVM().getConfig(); String[] cgCreators = config.getStringArray("cg-creators"); // If user specified names for additional CG creators, lets add them if (cgCreators != null) { for (String creator : cgCreators) { String[] nameClassPair = creator.split(":"); String cgName = nameClassPair[0]; String cgCreatorClassName = nameClassPair[1]; CGCreator cgCreator = createCGCreator(cgCreatorClassName); addCGCreator(cgName, cgCreator); } } } public static CGCreatorFactory getFactory() { if (factory == null) { factory = new CGCreatorFactory(); } else { // workaround for CGCreatorFactoryTest, because the specified CGCreator is not added // is another thers already initialized CGCreatorFactory // might depend on the order of tests Config config = VM.getVM().getConfig(); String[] cgCreators = config.getStringArray("cg-creators"); if (cgCreators != null) { factory = new CGCreatorFactory(); } } return factory; } public CGCreator getCGCreator(String key) { return cgTable.get(key); } public void addCGCreator(String cgName, CGCreator cgCreator) { if (cgTable.containsKey(cgName)) { throw new JPFException("CGCreator with name '" + cgName + "' already exists"); } cgTable.put(cgName, cgCreator); } private CGCreator createCGCreator(String cgCreatorClassName) { try { Class<?> cgCreatorClass = loader.loadClass(cgCreatorClassName); // We search for a constructor with no parameters Constructor<?> ctor = cgCreatorClass.getDeclaredConstructor(); ctor.setAccessible(true); return (CGCreator) ctor.newInstance(); } catch (Exception ex) { throw new JPFException(ex); } } } /** * CGCreator that creates instance of BooleanChoiceGenerator */ class BoolCGCreator implements CGCreator { public ChoiceGenerator<?> createCG(String id, Value[] params) { return new BooleanChoiceGenerator(id); } } /** * CGCreator that creates IntChoiceFromSet CG */ class IntFromSetCGCreator implements CGCreator { // <2do> add support from ctor with no params public ChoiceGenerator<?> createCG(String id, Value[] params) { int[] intSet = new int[params.length]; for (int i = 0; i < intSet.length; i++) { intSet[i] = params[i].getDouble().intValue(); } return new IntChoiceFromSet(id, intSet); } } class IntIntervalCGCreator implements CGCreator { public ChoiceGenerator<?> createCG(String id, Value[] params) { int min = params[0].getDouble().intValue(); int max = params[1].getDouble().intValue(); if (params.length == 2) { return new IntIntervalGenerator(id, min, max); } else if (params.length == 3) { int delta = params[2].getDouble().intValue(); return new IntIntervalGenerator(id, min, max, delta); } throw new JPFException("Can't create IntIntevalChoiceGenerator with id " + id); } } class DoubleFromSetCGCreator implements CGCreator { public ChoiceGenerator<?> createCG(String id, Value[] params) { double[] doubleSet = new double[params.length]; for (int i = 0; i < doubleSet.length; i++) { doubleSet[i] = params[i].getDouble().doubleValue(); } return new DoubleChoiceFromList(id, doubleSet); } } class DoubleThresholdGeneratorCGCreator implements CGCreator { public ChoiceGenerator<?> createCG(String id, Value[] params) { if (params.length != 0) { throw new JPFException("Double threshold generator requires empty parameters list"); } Config config = VM.getVM().getConfig(); return new DoubleThresholdGenerator(config, id); } } class RandomIntIntervalGeneratorCGCreator implements CGCreator { public ChoiceGenerator<?> createCG(String id, Value[] params) { int min = params[0].getDouble().intValue(); int max = params[1].getDouble().intValue(); int nChoices = params[2].getDouble().intValue(); if (params.length == 3) { return new RandomIntIntervalGenerator(id, min, max, nChoices); } else if (params.length == 4) { long seed = params[3].getDouble().longValue(); return new RandomIntIntervalGenerator(id, min, max, nChoices, seed); } throw new JPFException("Unexpected length of parameters list " + params.length); } }