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}