1/*******************************************************************************
2 * Copyright (c) 2009, 2018 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.File;
15import java.io.IOException;
16
17import org.apache.tools.ant.BuildException;
18import org.apache.tools.ant.Task;
19import org.jacoco.agent.AgentJar;
20import org.jacoco.core.runtime.AgentOptions;
21import org.jacoco.core.runtime.AgentOptions.OutputMode;
22
23/**
24 * Base class for all coverage tasks that require agent options
25 */
26public class AbstractCoverageTask extends Task {
27
28	private final AgentOptions agentOptions;
29
30	private File destfile;
31
32	private boolean enabled;
33
34	/**
35	 * Create default agent options
36	 */
37	protected AbstractCoverageTask() {
38		super();
39		agentOptions = new AgentOptions();
40		destfile = new File(AgentOptions.DEFAULT_DESTFILE);
41		enabled = true;
42	}
43
44	/**
45	 * @return Whether or not the current task is enabled
46	 */
47	public boolean isEnabled() {
48		return enabled;
49	}
50
51	/**
52	 * Sets whether or not the current task is enabled
53	 *
54	 * @param enabled
55	 *            Enablement state of the task
56	 */
57	public void setEnabled(final boolean enabled) {
58		this.enabled = enabled;
59	}
60
61	/**
62	 * Sets the location to write coverage execution data to. Default is
63	 * <code>jacoco.exec</code>.
64	 *
65	 * @param file
66	 *            Location to write coverage execution data to
67	 */
68	public void setDestfile(final File file) {
69		destfile = file;
70	}
71
72	/**
73	 * Append execution coverage data if a coverage file is already present.
74	 * Default is <code>true</code>
75	 *
76	 * @param append
77	 *            <code>true</code> to append execution data to an existing file
78	 */
79	public void setAppend(final boolean append) {
80		agentOptions.setAppend(append);
81	}
82
83	/**
84	 * List of wildcard patterns classes to include for instrumentation. Default
85	 * is <code>*</code>
86	 *
87	 * @param includes
88	 *            Wildcard pattern of included classes
89	 */
90	public void setIncludes(final String includes) {
91		agentOptions.setIncludes(includes);
92	}
93
94	/**
95	 * List of wildcard patterns classes to exclude from instrumentation.
96	 * Default is the empty string, no classes excluded
97	 *
98	 * @param excludes
99	 *            Wildcard pattern of excluded classes
100	 */
101	public void setExcludes(final String excludes) {
102		agentOptions.setExcludes(excludes);
103	}
104
105	/**
106	 * List of wildcard patterns for classloaders that JaCoCo will not
107	 * instrument classes from. Default is
108	 * <code>sun.reflect.DelegatingClassLoader</code>
109	 *
110	 * @param exclClassLoader
111	 *            Wildcard pattern of class loaders to exclude
112	 */
113	public void setExclClassLoader(final String exclClassLoader) {
114		agentOptions.setExclClassloader(exclClassLoader);
115	}
116
117	/**
118	 * Sets whether classes from the bootstrap classloader should be
119	 * instrumented.
120	 *
121	 * @param include
122	 *            <code>true</code> if bootstrap classes should be instrumented
123	 */
124	public void setInclBootstrapClasses(final boolean include) {
125		agentOptions.setInclBootstrapClasses(include);
126	}
127
128	/**
129	 * Sets whether classes without source location should be instrumented.
130	 *
131	 * @param include
132	 *            <code>true</code> if classes without source location should be
133	 *            instrumented
134	 */
135	public void setInclNoLocationClasses(final boolean include) {
136		agentOptions.setInclNoLocationClasses(include);
137	}
138
139	/**
140	 * Sets the session identifier. Default is a auto-generated id
141	 *
142	 * @param id
143	 *            session identifier
144	 */
145	public void setSessionId(final String id) {
146		agentOptions.setSessionId(id);
147	}
148
149	/**
150	 * Dump coverage data on VM termination. Default is <code>true</code>
151	 *
152	 * @param dumpOnExit
153	 *            <code>true</code> to write coverage data on VM termination
154	 */
155	public void setDumpOnExit(final boolean dumpOnExit) {
156		agentOptions.setDumpOnExit(dumpOnExit);
157	}
158
159	/**
160	 * Sets the output method. Default is <code>file</code>
161	 *
162	 * @param output
163	 *            Output method
164	 */
165	public void setOutput(final String output) {
166		agentOptions.setOutput(output);
167	}
168
169	/**
170	 * Sets the IP address or hostname to bind to when output method is tcp
171	 * server or connect to when the output method is tcp client. Default is
172	 * <code>localhost</code>
173	 *
174	 * @param address
175	 *            Address to bind or connect to
176	 */
177	public void setAddress(final String address) {
178		agentOptions.setAddress(address);
179	}
180
181	/**
182	 * Sets the Port to bind to when the output method is tcp server or connect
183	 * to when the output method is tcp client. Default is <code>6300</code>
184	 *
185	 * @param port
186	 *            port to bind to or connect to
187	 */
188	public void setPort(final int port) {
189		agentOptions.setPort(port);
190	}
191
192	/**
193	 * Sets the directory where all class files seen by the agent should be
194	 * dumped to.
195	 *
196	 * @param dir
197	 *            dump output location
198	 */
199	public void setClassdumpdir(final File dir) {
200		agentOptions.setClassDumpDir(dir.getAbsolutePath());
201	}
202
203	/**
204	 * Sets whether the agent should expose functionality via JMX.
205	 *
206	 * @param jmx
207	 *            <code>true</code> if JMX should be enabled
208	 */
209	public void setJmx(final boolean jmx) {
210		agentOptions.setJmx(jmx);
211	}
212
213	/**
214	 * Creates JVM argument to launch with the specified JaCoCo agent jar and
215	 * the current options
216	 *
217	 * @return JVM Argument to pass to new VM
218	 */
219	protected String getLaunchingArgument() {
220		return prepareAgentOptions().getVMArgument(getAgentFile());
221	}
222
223	private AgentOptions prepareAgentOptions() {
224		if (OutputMode.file.equals(agentOptions.getOutput())) {
225			agentOptions.setDestfile(destfile.getAbsolutePath());
226		}
227		return agentOptions;
228	}
229
230	private File getAgentFile() {
231		try {
232			File agentFile = null;
233			final String agentFileLocation = getProject().getProperty(
234					"_jacoco.agentFile");
235			if (agentFileLocation != null) {
236				agentFile = new File(agentFileLocation);
237			} else {
238				agentFile = AgentJar.extractToTempLocation();
239				getProject().setProperty("_jacoco.agentFile",
240						agentFile.toString());
241			}
242
243			return agentFile;
244		} catch (final IOException e) {
245			throw new BuildException("Unable to extract agent jar", e,
246					getLocation());
247		}
248	}
249
250}
251