JacocoAgent.java
1/*******************************************************************************
2 * Copyright (c) 2009, 2010 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 * Marc R. Hoffmann - initial API and implementation
10 *
11 * $Id: $
12 *******************************************************************************/
13package org.jacoco.agent.rt;
14
15import java.io.BufferedOutputStream;
16import java.io.File;
17import java.io.FileOutputStream;
18import java.io.IOException;
19import java.io.OutputStream;
20import java.lang.instrument.Instrumentation;
21
22import org.jacoco.core.data.ExecutionDataWriter;
23import org.jacoco.core.runtime.AgentOptions;
24import org.jacoco.core.runtime.IRuntime;
25import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
26
27/**
28 * The agent which is referred as the <code>Premain-Class</code>.
29 *
30 * @author Marc R. Hoffmann
31 * @version $Revision: $
32 */
33public class JacocoAgent {
34
35 private final AgentOptions options;
36
37 private IRuntime runtime;
38
39 /**
40 * Creates a new agent with the given agent options.
41 *
42 * @param options
43 * agent options
44 */
45 public JacocoAgent(AgentOptions options) {
46 this.options = options;
47 }
48
49 /**
50 * Creates a new agent with the given agent options string.
51 *
52 * @param agentArgs
53 * agent options as text string
54 */
55 public JacocoAgent(String options) {
56 this(new AgentOptions(options));
57 }
58
59 /**
60 * Initializes this agent.
61 *
62 * @param inst
63 * instrumentation services
64 * @throws Exception
65 * internal startup problem
66 */
67 public void init(final Instrumentation inst) throws Exception {
68 runtime = createRuntime(inst);
69 runtime.startup();
70 inst.addTransformer(new CoverageTransformer(runtime, options));
71 }
72
73 /**
74 * Creates the specific coverage runtime implementation.
75 *
76 * @param inst
77 * instrumentation services
78 * @return coverage runtime instance
79 * @throws Exception
80 * creation problem
81 */
82 protected IRuntime createRuntime(final Instrumentation inst)
83 throws Exception {
84 return ModifiedSystemClassRuntime.createFor(inst, "java/sql/Types");
85 }
86
87 /**
88 * Shutdown the agent again.
89 */
90 public void shutdown() {
91 writeExecutionData();
92 }
93
94 /**
95 * Writes the collected execution data to the specified file.
96 *
97 * @param runtime
98 * runtime containing the execution data
99 */
100 protected void writeExecutionData() {
101 try {
102 File execFile = new File(options.getDestfile()).getAbsoluteFile();
103 File folder = execFile.getParentFile();
104 if (folder != null) {
105 folder.mkdirs();
106 }
107 OutputStream output = new BufferedOutputStream(
108 new FileOutputStream(execFile, options.getAppend()));
109 ExecutionDataWriter writer = new ExecutionDataWriter(output);
110 writer.writeHeader();
111 runtime.collect(writer, false);
112 output.close();
113 } catch (IOException e) {
114 e.printStackTrace();
115 }
116 }
117
118 /**
119 * This method is called by the JVM to initialize Java agents.
120 *
121 * @param options
122 * agent options
123 * @param inst
124 * intrumentation callback provided by the JVM
125 */
126 public static void premain(final String options, final Instrumentation inst)
127 throws Exception {
128 final JacocoAgent agent = new JacocoAgent(options);
129 agent.init(inst);
130
131 Runtime.getRuntime().addShutdownHook(new Thread() {
132 @Override
133 public void run() {
134 agent.shutdown();
135 }
136 });
137 }
138
139}