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.annotations.SetteSnippetContainer; import hu.bme.mit.sette.common.descriptors.java.JavaSourceFile; import hu.bme.mit.sette.common.exceptions.SetteConfigurationException; import hu.bme.mit.sette.common.util.JavaFileUtils; import hu.bme.mit.sette.common.util.reflection.ReflectionUtils; import hu.bme.mit.sette.common.validator.FileType; import hu.bme.mit.sette.common.validator.FileValidator; import hu.bme.mit.sette.common.validator.GeneralValidator; import hu.bme.mit.sette.common.validator.exceptions.ValidatorException; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.Validate; /** * Represents a snippet code project. */ public final class SnippetProject { /** * Represents the state of a {@link SnippetProject} object. */ public static enum State { /** The project object has created. */ CREATED, /** The parsing has been started. */ PARSE_STARTED, /** The parsing has been finished. */ PARSED, /** An error occurred during parsing. */ PARSE_ERROR }; /** The state of the {@link SnippetProject} object. */ private State state; /** The settings for the snippet project. */ private final SnippetProjectSettings settings; /** The files of the snippet project. */ private Files files; /** The Java source files of the snippet project. */ private JavaSourceFiles javaSourceFiles; /** The model of the snippet project. */ private Model model; /** * The class loader for loading snippet project classes. The class loader * has all the specified binary directories and JAR libraries on its path. */ private ClassLoader classLoader = null; /** * Instantiates a new snippet project. * * @param pSettings * the settings */ public SnippetProject(final SnippetProjectSettings pSettings) { Validate.notNull(pSettings, "The settings must not be null"); state = State.CREATED; settings = pSettings; } /** * Parses the snippet project. The procedure is the following: * * <ol> * <li>Collect the snippet project files (sources, optional inputs and * libraries, see {@link #getFiles()}).</li> * <li>Creates a class loader for loading snippet project classes (see * {@link #getClassLoader()})</li> * <li>Parse the Java source files (see {@link #getJavaSourceFiles()}).</li> * <li>Parse and build the model of the snippet project (see * {@link #getModel()}). Also performs classloading.</li> * </ol> * * @throws SetteConfigurationException * if there was a configurational error * @throws ValidatorException * if validation has failed */ public void parse() throws SetteConfigurationException, ValidatorException { // validate preconditions validateState(State.CREATED); // TODO validation??? // settings.validateExists(); // start parsing state = State.PARSE_STARTED; // create containers files = new Files(); javaSourceFiles = new JavaSourceFiles(); model = new Model(); // parse collectFiles(); // may throw ValidatorException createClassLoader(); // may throw SetteConfigurationException parseJavaSourceFiles(); // may throw SetteConfigurationException parseModel(); // may throw ValidatorException // successful state = State.PARSED; } /** * Collects the snippet project files (sources, optional inputs and * libraries). * * @throws ValidatorException * if validation has failed */ private void collectFiles() throws ValidatorException { GeneralValidator validator = new GeneralValidator(this); // source files files.snippetSourceFiles.addAll(FileUtils.listFiles(settings.getSnippetSourceDirectory(), null, true)); for (File file : files.snippetSourceFiles) { FileValidator v = new FileValidator(file); v.type(FileType.REGULAR_FILE).readable(true); v.extension(JavaFileUtils.JAVA_SOURCE_EXTENSION); validator.addChildIfInvalid(v); } // input files files.inputSourceFiles.addAll(FileUtils.listFiles(settings.getInputSourceDirectory(), null, true)); for (File file : files.inputSourceFiles) { FileValidator v = new FileValidator(file); v.type(FileType.REGULAR_FILE).readable(true); v.extension(JavaFileUtils.JAVA_SOURCE_EXTENSION); validator.addChildIfInvalid(v); } // library files if (settings.getLibraryDirectory().exists()) { files.libraryFiles.addAll(FileUtils.listFiles(settings.getLibraryDirectory(), null, true)); for (File file : files.libraryFiles) { FileValidator v = new FileValidator(file); v.type(FileType.REGULAR_FILE).readable(true); v.extension(JavaFileUtils.JAVA_JAR_EXTENSION); validator.addChildIfInvalid(v); } } validator.validate(); } /** * Creates a class loader for loading snippet project classes. The class * loader will have all the specified binary directories and JAR libraries * on its path. * * @throws SetteConfigurationException * if there was a configurational error */ private void createClassLoader() throws SetteConfigurationException { try { // collect all bytecode resources List<URL> urls = new ArrayList<>(); urls.add(settings.getSnippetBinaryDirectory().toURI().toURL()); urls.add(settings.getInputBinaryDirectory().toURI().toURL()); if (files != null && files.libraryFiles != null) { for (File libraryFile : files.libraryFiles) { urls.add(libraryFile.toURI().toURL()); } } // instantiate class loader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()])); } catch (MalformedURLException e) { throw new SetteConfigurationException("At least one directory/file cannot be converted to an URL", e); } } /** * Parses the Java source files. * * @throws SetteConfigurationException * if there was a configurational error * @throws IOException */ private void parseJavaSourceFiles() throws SetteConfigurationException { // source Java files for (File file : files.snippetSourceFiles) { JavaSourceFile jsf = JavaSourceFile.fromFile(settings.getSnippetSourceDirectory(), file, classLoader); javaSourceFiles.snippetSources.put(jsf.getJavaClass(), jsf); } // input Java files for (File file : files.inputSourceFiles) { JavaSourceFile jsf = JavaSourceFile.fromFile(settings.getInputSourceDirectory(), file, classLoader); javaSourceFiles.inputSources.put(jsf.getJavaClass(), jsf); } } /** * Parses and builds the model of the snippet project. Also performs * classloading. * * @throws ValidatorException * if validation has failed */ private void parseModel() throws ValidatorException { GeneralValidator validator = new GeneralValidator(this); for (JavaSourceFile jsf : javaSourceFiles.snippetSources.values()) { Class<?> javaClass = jsf.getJavaClass(); try { if (javaClass.getAnnotation(SetteSnippetContainer.class) != null) { // create and add snippet container object SnippetContainer sc = new SnippetContainer(javaClass, classLoader); model.containers.add(sc); // add input factory container if (sc.getInputFactoryContainer() != null) { model.inputFactoryContainers.add(sc.getInputFactoryContainer()); } } else { // create and add dependency object SnippetDependency dep = new SnippetDependency(javaClass, classLoader); model.dependencies.add(dep); } } catch (ValidatorException e) { validator.addChild(e.getValidator()); } } validator.validate(); } /** * Gets the state of the {@link SnippetProject} object. * * @return the state of the {@link SnippetProject} object */ public State getState() { return state; } /** * Gets the settings for the snippet project. * * @return the settings for the snippet project */ public SnippetProjectSettings getSettings() { return settings; } /** * Gets the files (sources, optional inputs and libraries) of the snippet * project. * * @return the files (sources, optional inputs and libraries) of the snippet * project */ public Files getFiles() { validateState(State.PARSED); return files; } /** * Gets the Java source files of the snippet project. * * @return the Java source files of the snippet project */ public JavaSourceFiles getJavaSourceFiles() { validateState(State.PARSED); return javaSourceFiles; } /** * Gets the model of the snippet project. * * @return the model of the snippet project */ public Model getModel() { validateState(State.PARSED); return model; } /** * Gets the class loader for loading snippet project classes. The class * loader has all the specified binary directories and JAR libraries on its * path. * * @return the class loader for loading snippet project classes */ public ClassLoader getClassLoader() { Validate.validState(classLoader != null, "Invalid state: the class loader has not benn created yet"); return classLoader; } /** * Validates the state. * * @param required * the required state */ private void validateState(final State required) { Validate.validState(state.equals(required), "Invalid state (state: [%s], required: [%s])", state, required); } /** * Container class for {@link File}s in the snippet project. */ public final class Files { /** The snippet files (Java source files). */ private final SortedSet<File> snippetSourceFiles; /** The snippet input files (Java source files). */ private final SortedSet<File> inputSourceFiles; /** The referenced libraries (JAR files). */ private final SortedSet<File> libraryFiles; /** * Instantiates a new object. */ public Files() { snippetSourceFiles = new TreeSet<>(); inputSourceFiles = new TreeSet<>(); libraryFiles = new TreeSet<>(); } /** * Gets the snippet files (Java source files). * * @return the snippet files (Java source files) */ public SortedSet<File> getSnippetSourceFiles() { return Collections.unmodifiableSortedSet(snippetSourceFiles); } /** * Gets the snippet input files (Java source files). * * @return the snippet input files (Java source files) */ public SortedSet<File> getInputSourceFiles() { return Collections.unmodifiableSortedSet(inputSourceFiles); } /** * Gets the referenced libraries (JAR files). * * @return the referenced libraries (JAR files) */ public SortedSet<File> getLibraryFiles() { return Collections.unmodifiableSortedSet(libraryFiles); } } /** * Container class for {@link JavaSourceFile}s in the snippet project. */ public final class JavaSourceFiles { /** The snippet sources. */ private final SortedMap<Class<?>, JavaSourceFile> snippetSources; /** The snippet input sources. */ private final SortedMap<Class<?>, JavaSourceFile> inputSources; /** * Instantiates a new object. */ private JavaSourceFiles() { snippetSources = new TreeMap<>(ReflectionUtils.CLASS_COMPARATOR); inputSources = new TreeMap<>(ReflectionUtils.CLASS_COMPARATOR); } /** * Gets the snippet sources. * * @return the snippet sources */ public SortedMap<Class<?>, JavaSourceFile> getSnippetSources() { return Collections.unmodifiableSortedMap(snippetSources); } /** * Gets the snippet input sources. * * @return the snippet input sources */ public SortedMap<Class<?>, JavaSourceFile> getInputSources() { return Collections.unmodifiableSortedMap(inputSources); } } /** * Container class for the whole snippet model. */ public final class Model { /** The snippet containers. */ private final SortedSet<SnippetContainer> containers; /** The snippet dependencies. */ private final SortedSet<SnippetDependency> dependencies; /** The input factory containers. */ private final SortedSet<SnippetInputFactoryContainer> inputFactoryContainers; /** * Instantiates a new model. */ public Model() { containers = new TreeSet<>(); dependencies = new TreeSet<>(); inputFactoryContainers = new TreeSet<>(); } /** * Gets the snippet containers. * * @return the snippet containers */ public SortedSet<SnippetContainer> getContainers() { return Collections.unmodifiableSortedSet(containers); } /** * Gets the snippet dependencies. * * @return the snippet dependencies */ public SortedSet<SnippetDependency> getDependencies() { return Collections.unmodifiableSortedSet(dependencies); } /** * Gets the input factory containers. * * @return the input factory containers */ public SortedSet<SnippetInputFactoryContainer> getInputFactoryContainers() { return Collections.unmodifiableSortedSet(inputFactoryContainers); } } }