MergeTask.java

    1/*******************************************************************************
    2 * Copyright (c) 2009, 2010 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 *    Brock Janiczak - initial API and implementation
   10 *    
   11 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.ant;
   14
   15import java.io.BufferedOutputStream;
   16import java.io.File;
   17import java.io.FileOutputStream;
   18import java.io.IOException;
   19import java.io.InputStream;
   20import java.io.OutputStream;
   21import java.util.Iterator;
   22
   23import org.apache.tools.ant.BuildException;
   24import org.apache.tools.ant.Project;
   25import org.apache.tools.ant.Task;
   26import org.apache.tools.ant.types.Resource;
   27import org.apache.tools.ant.types.ResourceCollection;
   28import org.apache.tools.ant.types.resources.Union;
   29import org.apache.tools.ant.util.FileUtils;
   30import org.jacoco.core.data.ExecutionDataReader;
   31import org.jacoco.core.data.ExecutionDataStore;
   32import org.jacoco.core.data.ExecutionDataWriter;
   33
   34/**
   35 * Task for merging a set of execution data store files into a single file
   36 * 
   37 * @author Brock Janiczak
   38 * @version $Revision: $
   39 */
   40public class MergeTask extends Task {
   41
   42    private File destfile;
   43
   44    private final Union files = new Union();
   45
   46    /**
   47     * Sets the location of the merged data store
   48     * 
   49     * @param destfile
   50     *            Destination data store location
   51     */
   52    public void setDestfile(final File destfile) {
   53        this.destfile = destfile;
   54    }
   55
   56    /**
   57     * This task accepts any number of execution data resources.
   58     * 
   59     * @param resources
   60     *            Execution data resources
   61     */
   62    public void addConfigured(final ResourceCollection resources) {
   63        files.add(resources);
   64    }
   65
   66    @Override
   67    public void execute() throws BuildException {
   68        if (destfile == null) {
   69            throw new BuildException("Destination file must be supplied");
   70        }
   71
   72        if (destfile.exists() && (!destfile.canWrite() || !destfile.isFile())) {
   73            throw new BuildException("Unable to write to destination file");
   74        }
   75
   76        final ExecutionDataStore dataStore = new ExecutionDataStore();
   77
   78        int numFilesMerged = 0;
   79
   80        final Iterator<?> resourceIterator = files.iterator();
   81        while (resourceIterator.hasNext()) {
   82            final Resource resource = (Resource) resourceIterator.next();
   83
   84            if (resource.isDirectory()) {
   85                continue;
   86            }
   87
   88            log(String.format("Merging %s", resource.getName()),
   89                    Project.MSG_DEBUG);
   90
   91            InputStream resourceStream = null;
   92            try {
   93                resourceStream = resource.getInputStream();
   94                final ExecutionDataReader reader = new ExecutionDataReader(
   95                        resourceStream);
   96                reader.setExecutionDataVisitor(dataStore);
   97                reader.read();
   98
   99                numFilesMerged++;
  100            } catch (final IOException e) {
  101                throw new BuildException(String.format("Unable to read %s",
  102                        resource.getName()), e);
  103            } finally {
  104                FileUtils.close(resourceStream);
  105            }
  106        }
  107
  108        log(String.format("%d files merged", Integer.valueOf(numFilesMerged)),
  109                Project.MSG_INFO);
  110
  111        OutputStream outputStream = null;
  112        try {
  113            destfile.getParentFile().mkdirs();
  114            destfile.createNewFile();
  115            outputStream = new BufferedOutputStream(new FileOutputStream(
  116                    destfile));
  117            final ExecutionDataWriter dataWriter = new ExecutionDataWriter(
  118                    outputStream);
  119            dataStore.accept(dataWriter);
  120        } catch (final IOException e) {
  121            throw new BuildException(String.format(
  122                    "Unable to write merged file %s", destfile.getName()), e);
  123        } finally {
  124            FileUtils.close(outputStream);
  125        }
  126
  127    }
  128}