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 *******************************************************************************/
   12package org.jacoco.ant;
   13
   14import java.io.BufferedOutputStream;
   15import java.io.File;
   16import java.io.FileOutputStream;
   17import java.io.IOException;
   18import java.io.InputStream;
   19import java.io.OutputStream;
   20import java.util.Iterator;
   21
   22import org.apache.tools.ant.BuildException;
   23import org.apache.tools.ant.Project;
   24import org.apache.tools.ant.Task;
   25import org.apache.tools.ant.types.Resource;
   26import org.apache.tools.ant.types.ResourceCollection;
   27import org.apache.tools.ant.types.resources.Union;
   28import org.apache.tools.ant.util.FileUtils;
   29import org.jacoco.core.data.ExecutionDataReader;
   30import org.jacoco.core.data.ExecutionDataStore;
   31import org.jacoco.core.data.ExecutionDataWriter;
   32import org.jacoco.core.data.SessionInfoStore;
   33
   34/**
   35 * Task for merging a set of execution data store files into a single file
   36 * 
   37 * @author Brock Janiczak
   38 * @version 0.4.1.20101007204400
   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 SessionInfoStore infoStore = new SessionInfoStore();
   77        final ExecutionDataStore dataStore = new ExecutionDataStore();
   78
   79        loadSourceFiles(infoStore, dataStore);
   80
   81        OutputStream outputStream = null;
   82        try {
   83            FileUtils.getFileUtils().createNewFile(destfile, true);
   84
   85            outputStream = new BufferedOutputStream(new FileOutputStream(
   86                    destfile));
   87            final ExecutionDataWriter dataWriter = new ExecutionDataWriter(
   88                    outputStream);
   89            infoStore.accept(dataWriter);
   90            dataStore.accept(dataWriter);
   91        } catch (final IOException e) {
   92            throw new BuildException(String.format(
   93                    "Unable to write merged file %s", destfile.getName()), e);
   94        } finally {
   95            FileUtils.close(outputStream);
   96        }
   97
   98    }
   99
  100    private void loadSourceFiles(final SessionInfoStore infoStore,
  101            final ExecutionDataStore dataStore) {
  102        int numFilesMerged = 0;
  103
  104        final Iterator<?> resourceIterator = files.iterator();
  105        while (resourceIterator.hasNext()) {
  106            final Resource resource = (Resource) resourceIterator.next();
  107
  108            if (resource.isDirectory()) {
  109                continue;
  110            }
  111
  112            log(String.format("Merging %s", resource.getName()),
  113                    Project.MSG_DEBUG);
  114
  115            InputStream resourceStream = null;
  116            try {
  117                resourceStream = resource.getInputStream();
  118                final ExecutionDataReader reader = new ExecutionDataReader(
  119                        resourceStream);
  120                reader.setSessionInfoVisitor(infoStore);
  121                reader.setExecutionDataVisitor(dataStore);
  122                reader.read();
  123
  124                numFilesMerged++;
  125            } catch (final IOException e) {
  126                throw new BuildException(String.format("Unable to read %s",
  127                        resource.getName()), e);
  128            } finally {
  129                FileUtils.close(resourceStream);
  130            }
  131        }
  132
  133        log(String.format("%d files merged", Integer.valueOf(numFilesMerged)),
  134                Project.MSG_INFO);
  135    }
  136
  137}