1 /*******************************************************************************
2  * Copyright (c) 2009, 2015 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  *    Mads Mohr Christensen - implementation of MergeMojo
10  *
11  *******************************************************************************/
12 package org.jacoco.maven;
13 
14 import java.io.File;
15 import java.io.IOException;
16 import java.util.List;
17 
18 import org.apache.maven.plugin.MojoExecutionException;
19 import org.apache.maven.plugin.MojoFailureException;
20 import org.apache.maven.shared.model.fileset.FileSet;
21 import org.apache.maven.shared.model.fileset.util.FileSetManager;
22 import org.jacoco.core.tools.ExecFileLoader;
23 
24 /**
25  * Mojo for merging a set of execution data files (*.exec) into a single file
26  *
27  * @phase generate-resources
28  * @goal merge
29  * @requiresProject true
30  * @threadSafe
31  * @since 0.6.4
32  */
33 public class MergeMojo extends AbstractJacocoMojo {
34 
35 	private static final String MSG_SKIPPING = "Skipping JaCoCo merge execution due to missing execution data files";
36 
37 	/**
38 	 * Path to the output file for execution data.
39 	 *
40 	 * @parameter property="jacoco.destFile"
41 	 *            default-value="${project.build.directory}/jacoco.exec"
42 	 */
43 	private File destFile;
44 
45 	/**
46 	 * This mojo accepts any number of execution data file sets.
47 	 *
48 	 * Note that you need an <tt>implementation</tt> hint on <tt>fileset</tt>
49 	 * with Maven 2 (not needed with Maven 3):
50 	 *
51 	 * <pre>
52 	 * <code>
53 	 * &lt;fileSets&gt;
54 	 *   &lt;fileSet implementation="org.apache.maven.shared.model.fileset.FileSet"&gt;
55 	 *     &lt;directory&gt;${project.parent.build.directory}&lt;/directory&gt;
56 	 *     &lt;includes&gt;
57 	 *       &lt;include&gt;*.exec&lt;/include&gt;
58 	 *     &lt;/includes&gt;
59 	 *   &lt;/fileSet&gt;
60 	 * &lt;/fileSets&gt;
61 	 * </code>
62 	 * </pre>
63 	 *
64 	 * @parameter property="jacoco.fileSets"
65 	 * @required
66 	 */
67 	private List<FileSet> fileSets;
68 
69 	@Override
executeMojo()70 	protected void executeMojo() throws MojoExecutionException,
71 			MojoFailureException {
72 		if (!canMergeReports()) {
73 			return;
74 		}
75 		executeMerge();
76 	}
77 
canMergeReports()78 	private boolean canMergeReports() {
79 		if (fileSets == null || fileSets.isEmpty()) {
80 			getLog().info(MSG_SKIPPING);
81 			return false;
82 		}
83 		return true;
84 	}
85 
executeMerge()86 	private void executeMerge() throws MojoExecutionException {
87 		final ExecFileLoader loader = new ExecFileLoader();
88 
89 		load(loader);
90 		save(loader);
91 	}
92 
load(final ExecFileLoader loader)93 	private void load(final ExecFileLoader loader)
94 			throws MojoExecutionException {
95 		final FileSetManager fileSetManager = new FileSetManager(getLog());
96 		for (final FileSet fileSet : fileSets) {
97 			for (final String includedFilename : fileSetManager
98 					.getIncludedFiles(fileSet)) {
99 				final File inputFile = new File(fileSet.getDirectory(),
100 						includedFilename);
101 				if (inputFile.isDirectory()) {
102 					continue;
103 				}
104 				try {
105 					getLog().info(
106 							"Loading execution data file "
107 									+ inputFile.getAbsolutePath());
108 					loader.load(inputFile);
109 				} catch (final IOException e) {
110 					throw new MojoExecutionException("Unable to read "
111 							+ inputFile.getAbsolutePath(), e);
112 				}
113 			}
114 		}
115 	}
116 
save(final ExecFileLoader loader)117 	private void save(final ExecFileLoader loader)
118 			throws MojoExecutionException {
119 		if (loader.getExecutionDataStore().getContents().isEmpty()) {
120 			getLog().info(MSG_SKIPPING);
121 			return;
122 		}
123 		getLog().info(
124 				"Writing merged execution data to "
125 						+ destFile.getAbsolutePath());
126 		try {
127 			loader.save(destFile, false);
128 		} catch (final IOException e) {
129 			throw new MojoExecutionException("Unable to write merged file "
130 					+ destFile.getAbsolutePath(), e);
131 		}
132 	}
133 
134 }
135