1 /******************************************************************************* 2 * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors 3 * This program and the accompanying materials are made available under 4 * the terms of the Eclipse Public License 2.0 which is available at 5 * http://www.eclipse.org/legal/epl-2.0 6 * 7 * SPDX-License-Identifier: EPL-2.0 8 * 9 * Contributors: 10 * Marc R. Hoffmann - initial API and implementation 11 * 12 *******************************************************************************/ 13 package org.jacoco.agent; 14 15 import java.io.Closeable; 16 import java.io.File; 17 import java.io.FileOutputStream; 18 import java.io.IOException; 19 import java.io.InputStream; 20 import java.io.OutputStream; 21 import java.net.URL; 22 23 /** 24 * API to access the agent JAR file as a resource. While the agent is a JAR file 25 * it is considered as a plain resource that must be configured for the 26 * application under test (target JVM). The agent JAR does not provide any 27 * public Java API. 28 */ 29 public final class AgentJar { 30 31 /** 32 * Name of the agent JAR file resource within this bundle. 33 */ 34 private static final String RESOURCE = "/jacocoagent.jar"; 35 AgentJar()36 private AgentJar() { 37 } 38 39 /** 40 * Returns a URL pointing to the JAR file. 41 * 42 * @return URL of the JAR file 43 */ getResource()44 public static URL getResource() { 45 final URL url = AgentJar.class.getResource(RESOURCE); 46 if (url == null) { 47 throw new AssertionError(ERRORMSG); 48 } 49 return url; 50 } 51 52 /** 53 * Returns the content of the JAR file as a stream. 54 * 55 * @return content of the JAR file 56 */ getResourceAsStream()57 public static InputStream getResourceAsStream() { 58 final InputStream stream = AgentJar.class.getResourceAsStream(RESOURCE); 59 if (stream == null) { 60 throw new AssertionError(ERRORMSG); 61 } 62 return stream; 63 } 64 65 /** 66 * Extract the JaCoCo agent JAR and put it into a temporary location. This 67 * file should be deleted on exit, but may not if the VM is terminated 68 * 69 * @return Location of the Agent Jar file in the local file system. The file 70 * should exist and be readable. 71 * @throws IOException 72 * Unable to unpack agent jar 73 */ extractToTempLocation()74 public static File extractToTempLocation() throws IOException { 75 final File agentJar = File.createTempFile("jacocoagent", ".jar"); 76 agentJar.deleteOnExit(); 77 78 extractTo(agentJar); 79 80 return agentJar; 81 } 82 83 /** 84 * Extract the JaCoCo agent JAR and put it into the specified location. 85 * 86 * @param destination 87 * Location to write JaCoCo Agent Jar to. Must be writeable 88 * @throws IOException 89 * Unable to unpack agent jar 90 */ extractTo(File destination)91 public static void extractTo(File destination) throws IOException { 92 InputStream inputJarStream = getResourceAsStream(); 93 OutputStream outputJarStream = null; 94 95 try { 96 97 outputJarStream = new FileOutputStream(destination); 98 99 final byte[] buffer = new byte[8192]; 100 101 int bytesRead; 102 while ((bytesRead = inputJarStream.read(buffer)) != -1) { 103 outputJarStream.write(buffer, 0, bytesRead); 104 } 105 } finally { 106 safeClose(inputJarStream); 107 safeClose(outputJarStream); 108 } 109 } 110 111 /** 112 * Close a stream ignoring any error 113 * 114 * @param closeable 115 * stream to be closed 116 */ safeClose(Closeable closeable)117 private static void safeClose(Closeable closeable) { 118 try { 119 if (closeable != null) { 120 closeable.close(); 121 } 122 } catch (IOException e) { 123 } 124 } 125 126 private static final String ERRORMSG = String 127 .format("The resource %s has not been found. Please see " 128 + "/org.jacoco.agent/README.TXT for details.", RESOURCE); 129 130 } 131