Java tutorial
/** * Copyright 2012 Alex Jones * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 uk.co.unclealex.executable.generator; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.co.unclealex.executable.Executable; import uk.co.unclealex.executable.generator.model.ExecutableAnnotationInformation; import uk.co.unclealex.executable.generator.scan.AllClassNamesCollector; import uk.co.unclealex.executable.generator.scan.ExecutableAnnotationInformationFinder; import uk.co.unclealex.executable.generator.scan.exception.ExecutableScanException; import uk.co.unclealex.executable.generator.writer.GeneratedClassWriter; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; /** * The default implementation of {@link CodeGenerator}. * * @author alex * */ public class CodeGeneratorImpl implements CodeGenerator { /** The Constant log. */ private static final Logger log = LoggerFactory.getLogger(CodeGeneratorImpl.class); /** * The {@link AllClassNamesCollector} used to find all the class names in the * source directory. */ private final AllClassNamesCollector allClassNamesCollector; /** * The {@link ExecutableAnnotationInformationFinder} used to find all * {@link Executable} annotations. */ private final ExecutableAnnotationInformationFinder executableAnnotationInformationFinder; /** * The {@link GeneratedClassWriter} used to write the generated classes to * disk. */ private final GeneratedClassWriter generatedClassWriter; /** * Instantiates a new code generator impl. * * @param allClassNamesCollector * the all class names collector * @param executableAnnotationInformationFinder * the executable annotation information finder * @param generatedClassWriter * the generated class writer */ @Inject public CodeGeneratorImpl(AllClassNamesCollector allClassNamesCollector, ExecutableAnnotationInformationFinder executableAnnotationInformationFinder, GeneratedClassWriter generatedClassWriter) { super(); this.allClassNamesCollector = allClassNamesCollector; this.executableAnnotationInformationFinder = executableAnnotationInformationFinder; this.generatedClassWriter = generatedClassWriter; } /** * {@inheritDoc} */ @Override public void generate(ClassLoader classLoader, Path sourceDirectory, Path targetDirectory) throws IOException, ExecutableScanException { ClassLoader generatedClassLoader = new URLClassLoader(new URL[] { sourceDirectory.toUri().toURL() }, classLoader); List<String> allClassNames = getAllClassNamesCollector().listAllClassNames(sourceDirectory); List<Class<?>> allClasses = Lists .newArrayList(Iterables.transform(allClassNames, new ClassFunction(generatedClassLoader))); List<ExecutableAnnotationInformation> executableAnnotationInformations = getExecutableAnnotationInformationFinder() .findExecutableAnnotationInformation(allClasses); log.info("Found the following scripts: " + Joiner.on(", ").join( Sets.newTreeSet(Iterables.transform(executableAnnotationInformations, new ScriptNameFunction())))); GeneratedClassWriter generatedClassWriter = getGeneratedClassWriter(); Map<String, String> commandRunnerClassNamesByScriptName = Maps.newTreeMap(); for (ExecutableAnnotationInformation executableAnnotationInformation : executableAnnotationInformations) { String commandRunnerClassName = generatedClassWriter .writeClass(executableAnnotationInformation, generatedClassLoader, targetDirectory) .getClassName(); String scriptName = executableAnnotationInformation.getScriptName(); commandRunnerClassNamesByScriptName.put(scriptName, commandRunnerClassName); log.info("Written class " + commandRunnerClassName + " for script " + scriptName); } generatedClassWriter.writeEntryPointClass(targetDirectory, commandRunnerClassNamesByScriptName); } /** * The Class ScriptNameFunction. */ static class ScriptNameFunction implements Function<ExecutableAnnotationInformation, String> { /** * {@inheritDoc} */ @Override public String apply(ExecutableAnnotationInformation executableAnnotationInformation) { return executableAnnotationInformation.getScriptName(); } } /** * The Class ClassFunction. */ static class ClassFunction implements Function<String, Class<?>> { /** The class loader. */ private final ClassLoader classLoader; /** * Instantiates a new class function. * * @param classLoader * the class loader */ public ClassFunction(ClassLoader classLoader) { super(); this.classLoader = classLoader; } /** * {@inheritDoc} */ @Override public Class<?> apply(String className) { try { return getClassLoader().loadClass(className); } catch (ClassNotFoundException e) { throw new IllegalStateException("Cannot find class " + className, e); } } /** * Gets the class loader. * * @return the class loader */ public ClassLoader getClassLoader() { return classLoader; } } /** * Gets the {@link AllClassNamesCollector} used to find all the class names in * the source directory. * * @return the {@link AllClassNamesCollector} used to find all the class names * in the source directory */ public AllClassNamesCollector getAllClassNamesCollector() { return allClassNamesCollector; } /** * Gets the {@link ExecutableAnnotationInformationFinder} used to find all * {@link Executable} annotations. * * @return the {@link ExecutableAnnotationInformationFinder} used to find all * {@link Executable} annotations */ public ExecutableAnnotationInformationFinder getExecutableAnnotationInformationFinder() { return executableAnnotationInformationFinder; } /** * Gets the {@link GeneratedClassWriter} used to write the generated classes * to disk. * * @return the {@link GeneratedClassWriter} used to write the generated * classes to disk */ public GeneratedClassWriter getGeneratedClassWriter() { return generatedClassWriter; } }