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 *******************************************************************************/
12package org.jacoco.agent.rt;
13
14import java.lang.instrument.Instrumentation;
15import java.net.InetAddress;
16import java.net.UnknownHostException;
17import java.util.Random;
18
19import org.jacoco.agent.rt.controller.IAgentController;
20import org.jacoco.agent.rt.controller.LocalController;
21import org.jacoco.agent.rt.controller.TcpClientController;
22import org.jacoco.agent.rt.controller.TcpServerController;
23import org.jacoco.core.runtime.AgentOptions;
24import org.jacoco.core.runtime.IRuntime;
25import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
26import org.jacoco.core.runtime.AgentOptions.OutputMode;
27
28/**
29 * The agent which is referred as the <code>Premain-Class</code>.
30 *
31 * @author Marc R. Hoffmann
32 * @version 0.4.1.20101007204400
33 */
34public class JacocoAgent {
35
36 private final AgentOptions options;
37
38 private final IExceptionLogger logger;
39
40 private IRuntime runtime;
41
42 private IAgentController controller;
43
44 /**
45 * Creates a new agent with the given agent options.
46 *
47 * @param options
48 * agent options
49 * @param logger
50 * logger used by this agent
51 */
52 public JacocoAgent(final AgentOptions options, final IExceptionLogger logger) {
53 this.options = options;
54 this.logger = logger;
55 }
56
57 /**
58 * Creates a new agent with the given agent options string.
59 *
60 * @param options
61 * agent options as text string
62 */
63 public JacocoAgent(String options, IExceptionLogger logger) {
64 this(new AgentOptions(options), logger);
65 }
66
67 /**
68 * Initializes this agent.
69 *
70 * @param inst
71 * instrumentation services
72 * @throws Exception
73 * internal startup problem
74 */
75 public void init(final Instrumentation inst) throws Exception {
76 runtime = createRuntime(inst);
77 String sessionId = options.getSessionId();
78 if (sessionId == null) {
79 sessionId = createSessionId();
80 }
81 runtime.setSessionId(sessionId);
82 runtime.startup();
83 inst.addTransformer(new CoverageTransformer(runtime, options, logger));
84 controller = createAgentController();
85 controller.startup(options, runtime);
86 }
87
88 private IAgentController createAgentController() {
89 OutputMode controllerType = options.getOutput();
90 switch (controllerType) {
91 case file:
92 return new LocalController();
93 case tcpserver:
94 return new TcpServerController(logger);
95 case tcpclient:
96 return new TcpClientController(logger);
97 default:
98 throw new AssertionError(controllerType);
99 }
100 }
101
102 private String createSessionId() {
103 String host;
104 try {
105 host = InetAddress.getLocalHost().getHostName();
106 } catch (UnknownHostException e) {
107 host = "unknownhost";
108 }
109 return host + "-" + Integer.toHexString(new Random().nextInt());
110 }
111
112 /**
113 * Creates the specific coverage runtime implementation.
114 *
115 * @param inst
116 * instrumentation services
117 * @return coverage runtime instance
118 * @throws Exception
119 * creation problem
120 */
121 protected IRuntime createRuntime(final Instrumentation inst)
122 throws Exception {
123 return ModifiedSystemClassRuntime.createFor(inst, "java/sql/Types");
124 }
125
126 /**
127 * Shutdown the agent again.
128 */
129 public void shutdown() {
130 try {
131 if (options.getDumpOnExit()) {
132 controller.writeExecutionData();
133 }
134 controller.shutdown();
135 } catch (Exception e) {
136 logger.logExeption(e);
137 }
138 }
139
140 /**
141 * This method is called by the JVM to initialize Java agents.
142 *
143 * @param options
144 * agent options
145 * @param inst
146 * instrumentation callback provided by the JVM
147 */
148 public static void premain(final String options, final Instrumentation inst)
149 throws Exception {
150
151 final JacocoAgent agent = new JacocoAgent(options,
152 new IExceptionLogger() {
153 public void logExeption(Exception ex) {
154 ex.printStackTrace();
155 }
156 });
157
158 agent.init(inst);
159
160 Runtime.getRuntime().addShutdownHook(new Thread() {
161 @Override
162 public void run() {
163 agent.shutdown();
164 }
165 });
166 }
167
168}