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 *    Brock Janiczak - initial API and implementation
10 *
11 *******************************************************************************/
12package org.jacoco.ant;
13
14import static java.lang.String.format;
15
16import java.io.File;
17import java.io.IOException;
18import java.net.InetAddress;
19
20import org.apache.tools.ant.BuildException;
21import org.apache.tools.ant.Task;
22import org.jacoco.core.runtime.AgentOptions;
23import org.jacoco.core.tools.ExecDumpClient;
24import org.jacoco.core.tools.ExecFileLoader;
25
26/**
27 * Ant task for remotely controlling an application that is running with the
28 * tcpserver output mode
29 */
30public class DumpTask extends Task {
31
32	private boolean dump = true;
33	private boolean reset = false;
34	private File destfile = null;
35	private String address = AgentOptions.DEFAULT_ADDRESS;
36	private int port = AgentOptions.DEFAULT_PORT;
37	private int retryCount = 10;
38	private boolean append = true;
39
40	/**
41	 * Sets the location of the execution data file to write. This parameter is
42	 * required when dump is <code>true</code>. Default is
43	 * <code>jacoco.exec</code>
44	 *
45	 * @param destfile
46	 *            Location to write execution data to
47	 */
48	public void setDestfile(final File destfile) {
49		this.destfile = destfile;
50	}
51
52	/**
53	 * IP Address or hostname to connect to. Defaults to <code>localhost</code>
54	 *
55	 * @param address
56	 *            IP Address or hostname to connect to
57	 */
58	public void setAddress(final String address) {
59		this.address = address;
60	}
61
62	/**
63	 * Port number to connect to. Default is <code>6300</code>
64	 *
65	 * @param port
66	 *            Port to connect to
67	 */
68	public void setPort(final int port) {
69		this.port = port;
70	}
71
72	/**
73	 * Number of retries which the goal will attempt to establish a connection.
74	 * This can be used to wait until the target JVM is successfully launched.
75	 *
76	 * @param retryCount
77	 *            number of retries
78	 */
79	public void setRetryCount(final int retryCount) {
80		this.retryCount = retryCount;
81	}
82
83	/**
84	 * <code>true</code> if the destination file it to be appended to.
85	 * <code>false</code> if the file is to be overwritten
86	 *
87	 * @param append
88	 *            <code>true</code> if the destination file should be appended
89	 *            to
90	 */
91	public void setAppend(final boolean append) {
92		this.append = append;
93	}
94
95	/**
96	 * Sets whether execution data should be downloaded from the remote host.
97	 * Defaults to <code>true</code>
98	 *
99	 * @param dump
100	 *            <code>true</code> to download execution data
101	 */
102	public void setDump(final boolean dump) {
103		this.dump = dump;
104	}
105
106	/**
107	 * Sets whether a reset command should be sent after the execution data has
108	 * been dumped. Defaults to <code>false</code>
109	 *
110	 * @param reset
111	 *            <code>true</code> to reset execution data
112	 */
113	public void setReset(final boolean reset) {
114		this.reset = reset;
115	}
116
117	@Override
118	public void execute() throws BuildException {
119
120		if (port <= 0) {
121			throw new BuildException("Invalid port value", getLocation());
122		}
123		if (dump && destfile == null) {
124			throw new BuildException(
125					"Destination file is required when dumping execution data",
126					getLocation());
127		}
128
129		final ExecDumpClient client = new ExecDumpClient() {
130			@Override
131			protected void onConnecting(final InetAddress address,
132					final int port) {
133				log(format("Connecting to %s:%s", address,
134						Integer.valueOf(port)));
135			}
136
137			@Override
138			protected void onConnectionFailure(final IOException exception) {
139				log(exception.getMessage());
140			}
141		};
142		client.setDump(dump);
143		client.setReset(reset);
144		client.setRetryCount(retryCount);
145
146		try {
147			final ExecFileLoader loader = client.dump(address, port);
148			if (dump) {
149				log(format("Dumping execution data to %s",
150						destfile.getAbsolutePath()));
151				loader.save(destfile, append);
152			}
153		} catch (final IOException e) {
154			throw new BuildException("Unable to dump coverage data", e,
155					getLocation());
156		}
157	}
158
159}
160