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 options
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 protected void writeExecutionData() {
98 try {
99 File execFile = new File(options.getDestfile()).getAbsoluteFile();
100 File folder = execFile.getParentFile();
101 if (folder != null) {
102 folder.mkdirs();
103 }
104 OutputStream output = new BufferedOutputStream(
105 new FileOutputStream(execFile, options.getAppend()));
106 ExecutionDataWriter writer = new ExecutionDataWriter(output);
107 writer.writeHeader();
108 runtime.collect(writer, false);
109 output.close();
110 } catch (IOException e) {
111 e.printStackTrace();
112 }
113 }
114
115 /**
116 * This method is called by the JVM to initialize Java agents.
117 *
118 * @param options
119 * agent options
120 * @param inst
121 * intrumentation callback provided by the JVM
122 */
123 public static void premain(final String options, final Instrumentation inst)
124 throws Exception {
125 final JacocoAgent agent = new JacocoAgent(options);
126 agent.init(inst);
127
128 Runtime.getRuntime().addShutdownHook(new Thread() {
129 @Override
130 public void run() {
131 agent.shutdown();
132 }
133 });
134 }
135
136}