Java tutorial
/* * Copyright (c) 2002 Cunningham & Cunningham, Inc. * Copyright (c) 2009-2015 by Jochen Wierum & Cologne Intelligence * * This file is part of FitGoodies. * * FitGoodies is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FitGoodies is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FitGoodies. If not, see <http://www.gnu.org/licenses/>. */ package de.cologneintelligence.fitgoodies.maven; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; @Mojo(name = "integration-test", defaultPhase = LifecyclePhase.INTEGRATION_TEST, requiresDependencyResolution = ResolutionScope.TEST) public class FitIntegrationTestMojo extends AbstractMojo { public static final String FIT_MOJO_RESULT_FAILURE = "fit.mojo.result.failure"; public static final String MAIN_CLASS = "de.cologneintelligence.fitgoodies.runners.FitRunner"; @Parameter(defaultValue = "target/fit", property = "outputDir", required = true) private File outputDirectory; @Parameter(defaultValue = "src/test/fixtures", property = "fixturesDir", required = true) private File fixturesDirectory; @Parameter(property = "limits", required = false) private String[] limits = new String[0]; @Parameter(property = "additionalClasspathElements", required = false) private File[] additionalClasspathElements = new File[0]; @Parameter(property = "jvmArgs", required = false) private String[] jvmArgs = new String[0]; @Parameter(defaultValue = "UTF-8", property = "project.build.sourceEncoding", required = false) private String encoding; @Parameter(defaultValue = "${project}", required = true, readonly = true) private MavenProject project; public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Copy static resources into output directory"); copyNonTestFiles(fixturesDirectory, outputDirectory); getLog().info("Running Tests"); URL[] classpath = createClasspath(); runFit(classpath); } private void copyNonTestFiles(File sourceDir, File targetDir) throws MojoExecutionException { File[] files = sourceDir.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory()) { File newTarget = new File(targetDir, file.getName()); //noinspection ResultOfMethodCallIgnored newTarget.mkdirs(); copyNonTestFiles(file, newTarget); } else if (isNonTestFile(file.getName())) { try { FileUtils.copyFile(file, new File(targetDir, file.getName())); } catch (IOException e) { throw new MojoExecutionException("Could not copy file: " + file.getAbsolutePath(), e); } } } } } private boolean isNonTestFile(String name) { return !name.matches("(?i).*\\.html?$"); } private URL[] createClasspath() throws MojoExecutionException { List<String> classpathElements = getClasspath(); classpathElements.add(project.getBuild().getOutputDirectory()); classpathElements.add(project.getBuild().getTestOutputDirectory()); URL[] urls = new URL[classpathElements.size()]; for (int i = 0; i < classpathElements.size(); i++) { File file = new File(classpathElements.get(i)); try { urls[i] = file.toURI().toURL(); } catch (MalformedURLException e) { throw new MojoExecutionException("Could not build classpath with '" + file + "'", e); } } return urls; } private List<String> getClasspath() throws MojoExecutionException { try { @SuppressWarnings("unchecked") final List<String> temp = project.getTestClasspathElements(); return temp; } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Could not determine runtime classpath", e); } } private void saveResult(boolean result) { @SuppressWarnings("unchecked") Map<String, Object> context = (Map<String, Object>) this.getPluginContext(); context.put(FIT_MOJO_RESULT_FAILURE, result); } private void runFit(URL[] classpath) throws MojoExecutionException, MojoFailureException { File bootJar; try { bootJar = writeBootJar(createClassPathString(classpath)); } catch (IOException e) { throw new MojoExecutionException("Could not write boot jar", e); } try { ProcessBuilder builder = prepareProcess(bootJar); startProcess(builder); } finally { bootJar.delete(); } } private void startProcess(ProcessBuilder builder) throws MojoExecutionException { try { Process process = builder.start(); new StreamLogger(process.getErrorStream(), true, getLog()).start(); new StreamLogger(process.getInputStream(), false, getLog()).start(); int result = process.waitFor(); boolean success = result == 0; saveResult(success); if (!success) { getLog().info("One or more fit test(s) failed with return code " + result + ". Will fail in verify phase!"); } } catch (Exception e) { throw new MojoExecutionException("Error while running fit", e); } } private ProcessBuilder prepareProcess(File bootJar) throws MojoExecutionException { try { String executable = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; List<String> args = createJavaArgs(executable, bootJar); getLog().debug("Running process: " + args.toString()); return new ProcessBuilder(args).directory(project.getBasedir()); } catch (Exception e) { throw new MojoExecutionException("Error while preparing java process", e); } } private List<String> createJavaArgs(String executable, File bootJar) throws URISyntaxException { List<String> args = new LinkedList<>(); args.add(executable); args.add("-cp"); args.add(bootJar.getAbsolutePath()); args.addAll(Arrays.asList(jvmArgs)); args.add(MAIN_CLASS); args.add("-d"); args.add(outputDirectory.getPath()); args.add("-e"); args.add(encoding); args.add("-s"); args.add(fixturesDirectory.getPath()); for (String limit : limits) { args.add("-o"); args.add(limit); } return args; } private String createClassPathString(URL[] classpath) { StringBuilder classPathBuilder = new StringBuilder(); for (URL url : classpath) { appendToClasspath(url, classPathBuilder); } for (File element : additionalClasspathElements) { try { appendToClasspath(element.toURI().toURL(), classPathBuilder); } catch (MalformedURLException e) { throw new RuntimeException("Cannot convert file to url: " + element, e); } } return classPathBuilder.toString(); } private void appendToClasspath(URL url, StringBuilder classPathBuilder) { if (classPathBuilder.length() > 0) { classPathBuilder.append(' '); } classPathBuilder.append(url.toString()); } public File writeBootJar(String classpath) throws IOException { File bootJar = new File(outputDirectory, "boot.jar"); Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); manifest.getMainAttributes().put(Attributes.Name.CLASS_PATH, classpath); JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(bootJar), manifest); jarOutputStream.close(); return bootJar; } }