Java tutorial
/* * SETTE - Symbolic Execution based Test Tool Evaluator * * SETTE is a tool to help the evaluation and comparison of symbolic execution * based test input generator tools. * * Budapest University of Technology and Economics (BME) * * Authors: Lajos Cseppent <lajos.cseppento@inf.mit.bme.hu>, Zoltn Micskei * <micskeiz@mit.bme.hu> * * Copyright 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package hu.bme.mit.sette.common.model.snippet; import hu.bme.mit.sette.common.util.SetteAnnotationUtils; import hu.bme.mit.sette.common.validator.AbstractValidator; import hu.bme.mit.sette.common.validator.GeneralValidator; import hu.bme.mit.sette.common.validator.exceptions.ValidatorException; import hu.bme.mit.sette.common.validator.reflection.ClassType; import hu.bme.mit.sette.common.validator.reflection.ClassValidator; import hu.bme.mit.sette.common.validator.reflection.ConstructorValidator; import hu.bme.mit.sette.common.validator.reflection.FieldValidator; import hu.bme.mit.sette.common.validator.reflection.MethodValidator; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.Validate; /** * Represents a snippet input factory container (which is a Java class). */ public final class SnippetInputFactoryContainer implements Comparable<SnippetInputFactoryContainer> { /** The Java class of snippet input container. */ private final Class<?> javaClass; /** The snippet input factories. */ private final Map<String, SnippetInputFactory> inputFactories; /** The corresponding snippet container. */ private final SnippetContainer snippetContainer; /** * Instantiates a new snippet input factory container. * * @param pSnippetContainer * the snippet container * @param pJavaClass * the java class * @param classLoader * the class loader for loading snippet project classes * @throws ValidatorException * if validation has failed */ SnippetInputFactoryContainer(final SnippetContainer pSnippetContainer, final Class<?> pJavaClass, final ClassLoader classLoader) throws ValidatorException { Validate.notNull(pSnippetContainer, "The snippet container must not be null"); Validate.notNull(pJavaClass, "The Java class must not be null"); snippetContainer = pSnippetContainer; javaClass = pJavaClass; // start validation GeneralValidator validator = new GeneralValidator(SnippetInputFactoryContainer.class); // validate class validateClass(validator); // validate fields validateFields(validator); // validate constructor validateConstructor(validator); // validate methods and get factory methods Map<String, Method> factoryMethods = validateMethods(validator); // save data to fields inputFactories = new HashMap<>(); // add factory methods for (Method method : factoryMethods.values()) { try { SnippetInputFactory inputFactory = new SnippetInputFactory(this, method, classLoader); inputFactories.put(method.getName(), inputFactory); } catch (ValidatorException e) { validator.addChild(e.getValidator()); } } // check that there is no snippet method without factory method for (Snippet snippet : pSnippetContainer.getSnippets().values()) { if (snippet.getInputFactory() == null) { MethodValidator v = new MethodValidator(snippet.getMethod()); v.addException("The corresponting input factory was not found"); validator.addChildIfInvalid(v); } } validator.validate(); } /** * Validates the class and its annotations. * * @param validator * a validator */ private void validateClass(final AbstractValidator<?> validator) { // check: "public final class", no superclass, interface, declared // class, exactly one constructor ClassValidator v = new ClassValidator(javaClass); v.type(ClassType.REGULAR_CLASS); v.withModifiers(Modifier.PUBLIC | Modifier.FINAL); v.withoutModifiers(Modifier.ABSTRACT); v.synthetic(false); v.superclass(Object.class).interfaceCount(0).memberClassCount(0); v.declaredConstructorCount(1); // check: no SETTE annotations if (!SetteAnnotationUtils.getSetteAnnotations(javaClass).isEmpty()) { v.addException("The class must not have any SETTE annotations"); } validator.addChildIfInvalid(v); } /** * Validates the fields of the class. * * @param validator * a validator */ private void validateFields(final AbstractValidator<?> validator) { // check: no declared fields for (Field field : javaClass.getDeclaredFields()) { if (field.isSynthetic()) { // skip for synthetic fields (e.g. switch for enum generates // synthetic methods and fields) continue; } FieldValidator v = new FieldValidator(field); v.addException("The class must not declare fields"); validator.addChildIfInvalid(v); } } /** * Validates the constructor of the class. * * @param validator * a validator */ private void validateConstructor(final AbstractValidator<?> validator) { if (javaClass.getDeclaredConstructors().length != 1) { // constructor count is validated with the class return; } Constructor<?> constructor = javaClass.getDeclaredConstructors()[0]; ConstructorValidator v = new ConstructorValidator(constructor); v.withModifiers(Modifier.PRIVATE).parameterCount(0); v.synthetic(false); // check: constructor throws new // UnsupportedOperationException("Static class") Throwable exception = null; try { // call the private ctor constructor.setAccessible(true); constructor.newInstance(); } catch (Exception e) { exception = e.getCause(); } finally { // restore visibility constructor.setAccessible(false); } if (exception == null || !exception.getClass().equals(UnsupportedOperationException.class) || !exception.getMessage().equals("Static class")) { v.addException("The constructor must throw an " + "UnsupportedOperationException with the message " + "\"Static class\""); } validator.addChildIfInvalid(v); } /** * Validates methods of the class. * * @param validator * a validator * @return a map containing the input factory methods by their name */ private Map<String, Method> validateMethods(final AbstractValidator<?> validator) { // check: only "public static" or synthetic methods Map<String, Method> factoryMethods = new HashMap<String, Method>(); for (Method method : javaClass.getDeclaredMethods()) { if (method.isSynthetic()) { // skip synthetic methods continue; } MethodValidator v = new MethodValidator(method); if (factoryMethods.get(method.getName()) != null) { v.addException("The method must have a unique name"); } v.withModifiers(Modifier.PUBLIC | Modifier.STATIC); v.withoutModifiers(Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE | Modifier.SYNCHRONIZED); factoryMethods.put(method.getName(), method); validator.addChildIfInvalid(v); } return factoryMethods; } /** * Gets the Java class of snippet input container. * * @return the Java class of snippet input container */ public Class<?> getJavaClass() { return javaClass; } /** * Gets the snippet input factories. * * @return the snippet input factories */ public Map<String, SnippetInputFactory> getInputFactories() { return Collections.unmodifiableMap(inputFactories); } /** * Gets the corresponding snippet container. * * @return the corresponding snippet container */ public SnippetContainer getSnippetContainer() { return snippetContainer; } /** The {@link Comparator} for the class. */ public static final Comparator<SnippetInputFactoryContainer> COMPARATOR; static { COMPARATOR = new Comparator<SnippetInputFactoryContainer>() { @Override public int compare(final SnippetInputFactoryContainer o1, final SnippetInputFactoryContainer o2) { if (o1 == null) { return -1; } else if (o2 == null) { return 1; } else { return o1.javaClass.getName().compareTo(o2.javaClass.getName()); } } }; } /* * (non-Javadoc) * * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(final SnippetInputFactoryContainer o) { return SnippetInputFactoryContainer.COMPARATOR.compare(this, o); } }