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. * * @author unclealex72 * */ package uk.co.unclealex.executable.generator; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermissions; import java.util.List; import javax.inject.Inject; import uk.co.unclealex.executable.Executable; import uk.co.unclealex.executable.ExecutableEntryPoint; import uk.co.unclealex.executable.generator.jar.JarService; import uk.co.unclealex.executable.generator.scan.exception.ExecutableScanException; import uk.co.unclealex.executable.generator.script.KnownLengthInputSupplier; import uk.co.unclealex.executable.generator.script.KnownLengthInputSupplierFactory; import uk.co.unclealex.executable.generator.script.ScriptGenerator; import uk.co.unclealex.executable.generator.script.ScriptGeneratorFactory; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * The default implementation of {@link Scripter}. * * @author alex * */ public class ScripterImpl implements Scripter { private final JarService jarService; private final CodeGenerator codeGenerator; private final ScriptGeneratorFactory scriptGeneratorFactory; private final KnownLengthInputSupplierFactory knownLengthInputSupplierFactory; @Inject public ScripterImpl(JarService jarService, CodeGenerator codeGenerator, ScriptGeneratorFactory scriptGeneratorFactory, KnownLengthInputSupplierFactory knownLengthInputSupplierFactory) { super(); this.jarService = jarService; this.codeGenerator = codeGenerator; this.scriptGeneratorFactory = scriptGeneratorFactory; this.knownLengthInputSupplierFactory = knownLengthInputSupplierFactory; } /** * {@inheritDoc} */ @Override public void generate(Path targetPath, Path classesDirectory, String homeExpression, String version, Path workDirectory, Iterable<Path> dependencyJarFiles) throws IOException, ExecutableScanException { Path executableJarFileOrDirectory = jarService.findJarFileOrDirectoryDefiningClass( ExecutableEntryPoint.class.getClassLoader(), ExecutableEntryPoint.class.getName()); List<Path> allJarFilesOrDirectories = Lists.newArrayList(); allJarFilesOrDirectories.add(executableJarFileOrDirectory); allJarFilesOrDirectories.add(classesDirectory); allJarFilesOrDirectories.add(generateCodeJar(classesDirectory, workDirectory, dependencyJarFiles)); Iterables.addAll(allJarFilesOrDirectories, dependencyJarFiles); JarService jarService = getJarService(); List<KnownLengthInputSupplier> jarInputSuppliers = Lists.newLinkedList(); KnownLengthInputSupplierFactory knownLengthInputSupplierFactory = getKnownLengthInputSupplierFactory(); for (Path jarFileOrDirectory : allJarFilesOrDirectories) { Path jarFile; if (Files.isDirectory(jarFileOrDirectory)) { Path temp = Files.createTempFile(workDirectory, "generated-", ".jar"); jarService.generateJar(jarFileOrDirectory, temp); jarFile = temp; } else { jarFile = jarFileOrDirectory; } jarInputSuppliers.add(knownLengthInputSupplierFactory.createPathKnownLengthInputSupplier(jarFile)); } KnownLengthInputSupplier executableJarInputSupplier = jarInputSuppliers.remove(0); ScriptGenerator scriptGenerator = getScriptGeneratorFactory().createScriptGenerator(); try (OutputStream out = Files.newOutputStream(targetPath)) { scriptGenerator.generateScript(executableJarInputSupplier, jarInputSuppliers, homeExpression, version, out); } Files.setPosixFilePermissions(targetPath, PosixFilePermissions.fromString("rwxr--r--")); } /** * Generate the executable jar in the case that the dependency for the * executable classpath classes is not a jar file. * * @param workDirectory * The directory in which the jar file will be created. * @param executableDirectory * The directory containing the executable classpath classes. * @return The generated jar file. * @throws IOException */ protected Path generateExecutableJarFileFromDirectory(Path workDirectory, Path executableDirectory) throws IOException { Files.createDirectories(workDirectory); Path executableJarFile = workDirectory.resolve("executable.jar"); getJarService().generateJar(executableDirectory, executableJarFile); return executableJarFile; } /** * Generate all the classes required by the scripting framework. * * @param sourceDirectory * The directory containing the classes to be scanned for * {@link Executable} annotations. * @param workDirectory * The directory in which the jar file will be stored. * @return A jar file containing all generated sources. * @throws IOException * @throws ExecutableScanException */ protected Path generateCodeJar(Path sourceDirectory, Path workDirectory, Iterable<Path> dependencyJarFiles) throws IOException, ExecutableScanException { Path targetDirectory = workDirectory.resolve("generated-classes"); Files.createDirectories(targetDirectory); URL[] urls = new URL[Iterables.size(dependencyJarFiles)]; int idx = 0; for (Path dependencyJarFile : dependencyJarFiles) { urls[idx++] = dependencyJarFile.toUri().toURL(); } ClassLoader classLoader = new URLClassLoader(urls, getClass().getClassLoader()); getCodeGenerator().generate(classLoader, sourceDirectory, targetDirectory); Path jarFile = workDirectory.resolve("generated.jar"); getJarService().generateJar(targetDirectory, jarFile); return jarFile; } public JarService getJarService() { return jarService; } public CodeGenerator getCodeGenerator() { return codeGenerator; } public ScriptGeneratorFactory getScriptGeneratorFactory() { return scriptGeneratorFactory; } public KnownLengthInputSupplierFactory getKnownLengthInputSupplierFactory() { return knownLengthInputSupplierFactory; } }