aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
blob: deb2dab13910617e0d091ab6bb96d7ffd8804d24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*******************************************************************************
 * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
 * This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    Marc R. Hoffmann - initial API and implementation
 *
 *******************************************************************************/
package org.jacoco.agent;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

/**
 * API to access the agent JAR file as a resource. While the agent is a JAR file
 * it is considered as a plain resource that must be configured for the
 * application under test (target JVM). The agent JAR does not provide any
 * public Java API.
 */
public final class AgentJar {

	/**
	 * Name of the agent JAR file resource within this bundle.
	 */
	private static final String RESOURCE = "/jacocoagent.jar";

	private AgentJar() {
	}

	/**
	 * Returns a URL pointing to the JAR file.
	 *
	 * @return URL of the JAR file
	 */
	public static URL getResource() {
		final URL url = AgentJar.class.getResource(RESOURCE);
		if (url == null) {
			throw new AssertionError(ERRORMSG);
		}
		return url;
	}

	/**
	 * Returns the content of the JAR file as a stream.
	 *
	 * @return content of the JAR file
	 */
	public static InputStream getResourceAsStream() {
		final InputStream stream = AgentJar.class.getResourceAsStream(RESOURCE);
		if (stream == null) {
			throw new AssertionError(ERRORMSG);
		}
		return stream;
	}

	/**
	 * Extract the JaCoCo agent JAR and put it into a temporary location. This
	 * file should be deleted on exit, but may not if the VM is terminated
	 *
	 * @return Location of the Agent Jar file in the local file system. The file
	 *         should exist and be readable.
	 * @throws IOException
	 *             Unable to unpack agent jar
	 */
	public static File extractToTempLocation() throws IOException {
		final File agentJar = File.createTempFile("jacocoagent", ".jar");
		agentJar.deleteOnExit();

		extractTo(agentJar);

		return agentJar;
	}

	/**
	 * Extract the JaCoCo agent JAR and put it into the specified location.
	 *
	 * @param destination
	 *            Location to write JaCoCo Agent Jar to. Must be writeable
	 * @throws IOException
	 *             Unable to unpack agent jar
	 */
	public static void extractTo(File destination) throws IOException {
		InputStream inputJarStream = getResourceAsStream();
		OutputStream outputJarStream = null;

		try {

			outputJarStream = new FileOutputStream(destination);

			final byte[] buffer = new byte[8192];

			int bytesRead;
			while ((bytesRead = inputJarStream.read(buffer)) != -1) {
				outputJarStream.write(buffer, 0, bytesRead);
			}
		} finally {
			safeClose(inputJarStream);
			safeClose(outputJarStream);
		}
	}

	/**
	 * Close a stream ignoring any error
	 *
	 * @param closeable
	 *            stream to be closed
	 */
	private static void safeClose(Closeable closeable) {
		try {
			if (closeable != null) {
				closeable.close();
			}
		} catch (IOException e) {
		}
	}

	private static final String ERRORMSG = String
			.format("The resource %s has not been found. Please see "
					+ "/org.jacoco.agent/README.TXT for details.", RESOURCE);

}