Added API to extract Agent Jar and create VM option from AgentOptions
Used in Ant, Eclipse and Maven
diff --git a/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java b/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
index da978fd..c7a30e2 100644
--- a/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
+++ b/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
@@ -12,8 +12,12 @@
*******************************************************************************/
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.net.URL;
+import java.io.OutputStream;
/**
* API to access the agent JAR file as a resource.
@@ -24,24 +28,59 @@
public class AgentJar {
/**
- * Name of the agent JAR file resource within this bunde.
+ * Name of the agent JAR file resource within this bundle.
*/
- public static final String RESOURCE = "/jacocoagent.jar";
+ private static final String RESOURCE = "/jacocoagent.jar";
private AgentJar() {
}
/**
- * Returns a URL pointing to the JAR file.
+ * Extract the JaCoCo agent jar from the classpath and put it into a
+ * temporary location. This file should be deleted on exit, but may not if
+ * the VM is terminated
*
- * @return URL of the JAR file
+ * @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 URL getResource() {
- final URL url = AgentJar.class.getResource(RESOURCE);
- if (url == null) {
- throw new RuntimeException(ERRORMSG);
+ public static File extractToTempLocation() throws IOException {
+ final File agentJar = File.createTempFile("jacocoagent", ".jar");
+ agentJar.deleteOnExit();
+
+ extractTo(agentJar);
+
+ return agentJar;
+ }
+
+ /**
+ * Extract the JaCoCo agent jar from the classpath 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);
}
- return url;
}
/**
@@ -49,14 +88,29 @@
*
* @return content of the JAR file
*/
- public static InputStream getResourceAsStream() {
+ private static InputStream getResourceAsStream() throws IOException {
final InputStream stream = AgentJar.class.getResourceAsStream(RESOURCE);
if (stream == null) {
- throw new RuntimeException(ERRORMSG);
+ throw new IOException(ERRORMSG);
}
return stream;
}
+ /**
+ * 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);
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
index 371f467..66fadcb 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
@@ -13,7 +13,9 @@
package org.jacoco.ant;
import java.io.File;
+import java.io.IOException;
+import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.jacoco.core.runtime.AgentOptions;
@@ -99,4 +101,18 @@
agentOptions.setExclClassloader(exclClassLoader);
}
+ /**
+ * Creates JVM argument to launch with the specified JaCoCo agent jar and
+ * the current options
+ *
+ * @return JVM Argument to pass to new VM
+ */
+ protected String getLaunchingArgument() {
+ try {
+ return getAgentOptions().getVMArgument(JaCoCoState.getAgentFile());
+ } catch (final IOException e) {
+ throw new BuildException("Unable to extract agent jar", e);
+ }
+ }
+
}
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java b/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
index bfc9085..c114f6f 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
@@ -57,8 +57,6 @@
if (property == null || property.length() == 0) {
throw new BuildException("Property is mandatory");
}
- final JvmArgumentHelper jvmArgumentHelper = new JvmArgumentHelper();
- getProject().setNewProperty(property,
- jvmArgumentHelper.createJavaAgentParam(getAgentOptions()));
+ getProject().setNewProperty(property, getLaunchingArgument());
}
}
diff --git a/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
index 2a7d464..4cd9cb9 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
@@ -125,17 +125,14 @@
}
public void addJvmArgs(final UnknownElement task) {
- final JvmArgumentHelper jvmArgumentHelper = new JvmArgumentHelper();
- final String agentParam = jvmArgumentHelper
- .createJavaAgentParam(getAgentOptions());
-
final UnknownElement el = new UnknownElement("jvmarg");
el.setTaskName("jvmarg");
el.setQName("jvmarg");
final RuntimeConfigurable runtimeConfigurableWrapper = el
.getRuntimeConfigurableWrapper();
- runtimeConfigurableWrapper.setAttribute("value", agentParam);
+ runtimeConfigurableWrapper.setAttribute("value",
+ getLaunchingArgument());
task.getRuntimeConfigurableWrapper().addChild(
runtimeConfigurableWrapper);
diff --git a/org.jacoco.ant/src/org/jacoco/ant/JaCoCoState.java b/org.jacoco.ant/src/org/jacoco/ant/JaCoCoState.java
new file mode 100644
index 0000000..9109396
--- /dev/null
+++ b/org.jacoco.ant/src/org/jacoco/ant/JaCoCoState.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Brock Janiczak - initial API and implementation
+ *
+ * $Id: $
+ *******************************************************************************/
+package org.jacoco.ant;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.jacoco.agent.AgentJar;
+
+/**
+ * Static class for holding the state of the JaCoCo agent
+ *
+ * @author Brock Janiczak
+ * @version $Revision: $
+ */
+public class JaCoCoState {
+ private static File agentFile;
+
+ /**
+ * Gets the current location of the JaCoCo agent jar file. The agent jar may
+ * be extracted to a temporary location
+ *
+ * @return Physical location of the JaCoCo Agent Jar
+ * @throws IOException
+ * Unable to extract the agent jar file
+ */
+ public static synchronized File getAgentFile() throws IOException {
+ if (agentFile == null) {
+ agentFile = AgentJar.extractToTempLocation();
+ }
+
+ return agentFile;
+ }
+}
diff --git a/org.jacoco.ant/src/org/jacoco/ant/JvmArgumentHelper.java b/org.jacoco.ant/src/org/jacoco/ant/JvmArgumentHelper.java
deleted file mode 100644
index 5561883..0000000
--- a/org.jacoco.ant/src/org/jacoco/ant/JvmArgumentHelper.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Brock Janiczak - initial API and implementation
- *
- * $Id: $
- *******************************************************************************/
-package org.jacoco.ant;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.util.FileUtils;
-import org.jacoco.agent.AgentJar;
-import org.jacoco.core.runtime.AgentOptions;
-
-/**
- * Helper class to generate the JVM argument required to start a new JVM with a
- * code coverage agent
- *
- * @author Brock Janiczak
- * @version $Revision: $
- */
-class JvmArgumentHelper {
- private final File agentJar;
-
- JvmArgumentHelper() {
- final InputStream inputStream = AgentJar.getResourceAsStream();
- try {
- agentJar = extractAgentJar(inputStream);
- } finally {
- FileUtils.close(inputStream);
- }
- }
-
- /**
- * Extract the JaCoCo agent jar from the classpath and put it into a
- * temporary location.
- *
- * @param inputJarStream
- * Open stream pointing to the JaCoCo jar
- * @return Local physical location of the JaCoCo agent jar. This file will
- * be removed once the task has been executed
- */
- private File extractAgentJar(final InputStream inputJarStream) {
-
- if (inputJarStream == null) {
- throw new BuildException("Unable to locate Agent Jar");
- }
-
- OutputStream outputJarStream = null;
- try {
- final File agentJar = File.createTempFile("jacocoagent", ".jar");
- agentJar.deleteOnExit();
-
- outputJarStream = new FileOutputStream(agentJar);
-
- final byte[] buffer = new byte[8192];
-
- int bytesRead;
- while ((bytesRead = inputJarStream.read(buffer)) != -1) {
- outputJarStream.write(buffer, 0, bytesRead);
- }
-
- return agentJar;
- } catch (final IOException e) {
- throw new BuildException("Unable to unpack Agent Jar", e);
- } finally {
- FileUtils.close(outputJarStream);
- }
- }
-
- /**
- * Generate required JVM argument string based on current configuration and
- * agent jar location
- *
- * @return Argument to pass to create new VM with coverage enabled
- */
- String createJavaAgentParam(final AgentOptions agentOptions) {
- final StringBuilder param = new StringBuilder();
- param.append("-javaagent:");
- param.append(agentJar.getAbsolutePath());
- param.append("=");
- param.append(agentOptions.toString());
-
- return param.toString();
- }
-}
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
index d30ee94..8e6dc69 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
@@ -14,6 +14,7 @@
import static java.lang.String.format;
+import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -223,6 +224,26 @@
}
/**
+ * Generate required JVM argument string based on current configuration and
+ * supplied agent jar location
+ *
+ * @param agentJarFile
+ * location of the JaCoCo Agent Jar
+ * @return Argument to pass to create new VM with coverage enabled
+ */
+ public String getVMArgument(final File agentJarFile) {
+ final StringBuilder param = new StringBuilder();
+ param.append('"');
+ param.append("-javaagent:");
+ param.append(agentJarFile.toString());
+ param.append("=");
+ param.append(this.toString());
+ param.append('"');
+
+ return param.toString();
+ }
+
+ /**
* Creates a string representation that can be passed to the agent via the
* command line. Might be the empty string, if no options are set.
*/