1d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann/******************************************************************************* 2d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors 3d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * All rights reserved. This program and the accompanying materials 4d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * are made available under the terms of the Eclipse Public License v1.0 5d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * which accompanies this distribution, and is available at 6d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * http://www.eclipse.org/legal/epl-v10.html 7d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * 8d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * Contributors: 9d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * John Keeping - initial implementation 10d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * Marc R. Hoffmann - rework 11d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * 12d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann *******************************************************************************/ 13d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannpackage org.jacoco.cli.internal.commands; 14d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 15d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.File; 16d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.FileInputStream; 17d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.FileOutputStream; 18d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.IOException; 19d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.InputStream; 20d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.OutputStream; 21d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.io.PrintWriter; 22d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.util.ArrayList; 23d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport java.util.List; 24d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 25d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport org.jacoco.cli.internal.Command; 26d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport org.jacoco.core.instr.Instrumenter; 27d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator; 28d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport org.kohsuke.args4j.Argument; 29d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannimport org.kohsuke.args4j.Option; 30d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 31d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann/** 32d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann * The <code>instrument</code> command. 33d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann */ 34d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmannpublic class Instrument extends Command { 35d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 365653302c6febde3d8f507bcf8b1778fe1b6bbebcMarc R. Hoffmann @Option(name = "-dest", usage = "path to write instrumented Java classes to", metaVar = "<dir>", required = true) 375653302c6febde3d8f507bcf8b1778fe1b6bbebcMarc R. Hoffmann File dest; 38d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 39d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann @Argument(usage = "list of folder or files to instrument recusively", metaVar = "<sourcefiles>") 40d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann List<File> source = new ArrayList<File>(); 41d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 42d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann private Instrumenter instrumenter; 43d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 44d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann @Override 45d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann public String description() { 46d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann return "Off-line instrumentation of Java class files and JAR files."; 47d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 48d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 49d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann @Override 50d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann public int execute(final PrintWriter out, final PrintWriter err) 51d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann throws IOException { 52d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann instrumenter = new Instrumenter( 53d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann new OfflineInstrumentationAccessGenerator()); 54d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann int total = 0; 55d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann for (final File s : source) { 565653302c6febde3d8f507bcf8b1778fe1b6bbebcMarc R. Hoffmann total += instrumentRecursive(s, dest); 57d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 58d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann out.printf("[INFO] %s classes instrumented to %s.%n", 595653302c6febde3d8f507bcf8b1778fe1b6bbebcMarc R. Hoffmann Integer.valueOf(total), dest.getAbsolutePath()); 60d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann return 0; 61d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 62d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 63d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann private int instrumentRecursive(final File src, final File dest) 64d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann throws IOException { 65d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann int total = 0; 66d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann if (src.isDirectory()) { 67d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann for (final File child : src.listFiles()) { 68d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann total += instrumentRecursive(child, 69d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann new File(dest, child.getName())); 70d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 71d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } else { 72d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann total += instrument(src, dest); 73d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 74d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann return total; 75d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 76d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 77d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann private int instrument(final File src, final File dest) throws IOException { 78d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann dest.getParentFile().mkdirs(); 79d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann final InputStream input = new FileInputStream(src); 80d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann try { 81d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann final OutputStream output = new FileOutputStream(dest); 82d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann try { 83d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann return instrumenter.instrumentAll(input, output, 84d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann src.getAbsolutePath()); 85d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } finally { 86d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann output.close(); 87d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 88d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } catch (final IOException e) { 89d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann dest.delete(); 90d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann throw e; 91d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } finally { 92d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann input.close(); 93d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 94d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann } 95d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann 96d850ed49b22d2a0c84a3b317acec8df7e7159016Marc R. Hoffmann} 97