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