| /******************************************************************************* |
| * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Brock Janiczak - initial API and implementation |
| * |
| *******************************************************************************/ |
| package org.jacoco.ant; |
| |
| import static java.lang.String.format; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.Iterator; |
| |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Task; |
| import org.apache.tools.ant.types.Resource; |
| import org.apache.tools.ant.types.ResourceCollection; |
| import org.apache.tools.ant.types.resources.Union; |
| import org.apache.tools.ant.util.FileUtils; |
| import org.jacoco.core.instr.Instrumenter; |
| import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator; |
| |
| /** |
| * Task for offline instrumentation of class files. |
| */ |
| public class InstrumentTask extends Task { |
| |
| private File destdir; |
| |
| private final Union files = new Union(); |
| |
| private boolean removesignatures = true; |
| |
| /** |
| * Sets the location of the instrumented classes. |
| * |
| * @param destdir |
| * destination folder for instrumented classes |
| */ |
| public void setDestdir(final File destdir) { |
| this.destdir = destdir; |
| } |
| |
| /** |
| * Sets whether signatures should be removed from JAR files. |
| * |
| * @param removesignatures |
| * <code>true</code> if signatures should be removed |
| */ |
| public void setRemovesignatures(final boolean removesignatures) { |
| this.removesignatures = removesignatures; |
| } |
| |
| /** |
| * This task accepts any number of class file resources. |
| * |
| * @param resources |
| * Execution data resources |
| */ |
| public void addConfigured(final ResourceCollection resources) { |
| files.add(resources); |
| } |
| |
| @Override |
| public void execute() throws BuildException { |
| if (destdir == null) { |
| throw new BuildException("Destination directory must be supplied", |
| getLocation()); |
| } |
| int total = 0; |
| final Instrumenter instrumenter = new Instrumenter( |
| new OfflineInstrumentationAccessGenerator()); |
| instrumenter.setRemoveSignatures(removesignatures); |
| final Iterator<?> resourceIterator = files.iterator(); |
| while (resourceIterator.hasNext()) { |
| final Resource resource = (Resource) resourceIterator.next(); |
| if (resource.isDirectory()) { |
| continue; |
| } |
| total += instrument(instrumenter, resource); |
| } |
| log(format("Instrumented %s classes to %s", Integer.valueOf(total), |
| destdir.getAbsolutePath())); |
| } |
| |
| private int instrument(final Instrumenter instrumenter, |
| final Resource resource) { |
| final File file = new File(destdir, resource.getName()); |
| file.getParentFile().mkdirs(); |
| try { |
| InputStream input = null; |
| OutputStream output = null; |
| try { |
| input = resource.getInputStream(); |
| output = new FileOutputStream(file); |
| return instrumenter.instrumentAll(input, output, |
| resource.getName()); |
| } finally { |
| FileUtils.close(input); |
| FileUtils.close(output); |
| } |
| } catch (final Exception e) { |
| file.delete(); |
| throw new BuildException(format("Error while instrumenting %s", |
| resource), e, getLocation()); |
| } |
| } |
| } |