293ac848fba937fa79d40113f871344f8bec7595
[lttng-ust.git] / liblttng-ust-java-agent / java / org / lttng / ust / agent / LTTngAgent.java
1 /*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 package org.lttng.ust.agent;
19
20 import org.lttng.ust.agent.jul.LTTngJUL;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.BufferedReader;
25 import java.io.FileReader;
26 import java.util.concurrent.Semaphore;
27 import java.util.concurrent.TimeUnit;
28 import java.util.Enumeration;
29 import java.lang.reflect.InvocationTargetException;
30
31 import java.util.logging.Logger;
32 import java.util.logging.SimpleFormatter;
33
34 public class LTTngAgent {
35 /* Domains */
36 static enum Domain {
37 JUL(3), LOG4J(4);
38 private int value;
39
40 private Domain(int value) {
41 this.value = value;
42 }
43
44 public int value() {
45 return value;
46 }
47 }
48
49 private static LogFramework julUser;
50 private static LogFramework julRoot;
51 private static LogFramework log4jUser;
52 private static LogFramework log4jRoot;
53
54 /* Sessiond clients */
55 private static LTTngTCPSessiondClient julUserClient;
56 private static LTTngTCPSessiondClient julRootClient;
57 private static LTTngTCPSessiondClient log4jUserClient;
58 private static LTTngTCPSessiondClient log4jRootClient;
59
60 private static Thread sessiondThreadJULUser;
61 private static Thread sessiondThreadJULRoot;
62 private static Thread sessiondThreadLog4jUser;
63 private static Thread sessiondThreadLog4jRoot;
64
65 private boolean useJUL = false;
66 private boolean useLog4j = false;
67
68 /* Singleton agent object */
69 private static LTTngAgent curAgent = null;
70
71 /* Indicate if this object has been initialized. */
72 private static boolean initialized = false;
73
74 private static Semaphore registerSem;
75 private final static int semTimeout = 3; /* Seconds */
76
77 /*
78 * Constructor is private. This is a singleton and a reference should be
79 * acquired using getLTTngAgent().
80 */
81 private LTTngAgent() throws IOException {
82 initAgentJULClasses();
83
84 /* Since Log4j is a 3rd party JAR, we need to check if we can load any of its classes */
85 Boolean log4jLoaded = loadLog4jClasses();
86 if (log4jLoaded) {
87 initAgentLog4jClasses();
88 }
89
90 this.registerSem = new Semaphore(0, true);
91 }
92
93 private Boolean loadLog4jClasses() {
94 Class<?> logging;
95
96 try {
97 ClassLoader loader = ClassLoader.getSystemClassLoader();
98 logging = loader.loadClass("org.apache.log4j.spi.LoggingEvent");
99 } catch (ClassNotFoundException e) {
100 /* Log4j classes not found, no need to create the relevant objects */
101 return false;
102 }
103
104 /*
105 * Detect capabilities of the log4j library. We only
106 * support log4j >= 1.2.15. The getTimeStamp() method
107 * was introduced in log4j 1.2.15, so verify that it
108 * is available.
109 *
110 * We can't rely on the getPackage().getImplementationVersion()
111 * call that would retrieves information from the manifest file
112 * found in the JAR since the manifest file shipped
113 * from upstream is known to be broken in several
114 * versions of the library.
115 *
116 * More info:
117 * https://issues.apache.org/bugzilla/show_bug.cgi?id=44370
118 */
119
120 try {
121 logging.getDeclaredMethod("getTimeStamp");
122 } catch (NoSuchMethodException e) {
123 return false;
124 } catch (NullPointerException e) {
125 /* Should never happen */
126 return false;
127 } catch (SecurityException e) {
128 return false;
129 }
130
131 return true;
132 }
133
134 private void initAgentJULClasses() {
135 try {
136 ClassLoader loader = ClassLoader.getSystemClassLoader();
137 Class<?> lttngJUL = loader.loadClass("org.lttng.ust.agent.jul.LTTngJUL");
138 this.julUser = (LogFramework)lttngJUL.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(false);
139 this.julRoot = (LogFramework)lttngJUL.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(true);
140 this.useJUL = true;
141 } catch (ClassNotFoundException e) {
142 /* LTTng JUL classes not found, no need to create the relevant objects */
143 this.useJUL = false;
144 } catch (InstantiationException e) {
145 this.useJUL = false;
146 } catch (NoSuchMethodException e) {
147 this.useJUL = false;
148 } catch (IllegalAccessException e) {
149 this.useJUL = false;
150 } catch (InvocationTargetException e) {
151 this.useJUL = false;
152 }
153 }
154
155 private void initAgentLog4jClasses() {
156 try {
157 ClassLoader loader = ClassLoader.getSystemClassLoader();
158 Class<?> lttngLog4j = loader.loadClass("org.lttng.ust.agent.log4j.LTTngLog4j");
159 this.log4jUser = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(false);
160 this.log4jRoot = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(true);
161 this.useLog4j = true;
162 } catch (ClassNotFoundException e) {
163 /* LTTng Log4j classes not found, no need to create the relevant objects */
164 this.useLog4j = false;
165 } catch (InstantiationException e) {
166 this.useLog4j = false;
167 } catch (NoSuchMethodException e) {
168 this.useLog4j = false;
169 } catch (IllegalAccessException e) {
170 this.useLog4j = false;
171 } catch (InvocationTargetException e) {
172 this.useLog4j = false;
173 }
174 }
175
176 /*
177 * Public getter to acquire a reference to this singleton object.
178 */
179 public static synchronized LTTngAgent getLTTngAgent() throws IOException {
180 if (curAgent == null) {
181 curAgent = new LTTngAgent();
182 curAgent.init();
183 }
184
185 return curAgent;
186 }
187
188 private synchronized void init() throws SecurityException, IOException {
189 if (this.initialized) {
190 return;
191 }
192
193 Integer numJULThreads = 0;
194 Integer numLog4jThreads = 0;
195
196 if (this.useJUL) {
197 numJULThreads = initJULClientThreads();
198 }
199
200 if (this.useLog4j) {
201 numLog4jThreads = initLog4jClientThreads();
202 }
203
204 Integer numThreads = numJULThreads + numLog4jThreads;
205
206 /* Wait for each registration to end. */
207 try {
208 this.registerSem.tryAcquire(numThreads,
209 semTimeout,
210 TimeUnit.SECONDS);
211 } catch (InterruptedException e) {
212 e.printStackTrace();
213 }
214
215 this.initialized = true;
216 }
217
218 private synchronized Integer initJULClientThreads() {
219 Integer numThreads = 2;
220
221 /* Handle user session daemon if any. */
222 this.julUserClient = new LTTngTCPSessiondClient(Domain.JUL,
223 this.julUser,
224 this.registerSem);
225
226 String userThreadName = "LTTng UST agent JUL user thread";
227 this.sessiondThreadJULUser = new Thread(julUserClient, userThreadName);
228 this.sessiondThreadJULUser.setDaemon(true);
229 this.sessiondThreadJULUser.start();
230
231 /* Handle root session daemon. */
232 this.julRootClient = new LTTngTCPSessiondClient(Domain.JUL,
233 this.julRoot,
234 this.registerSem);
235
236 String rootThreadName = "LTTng UST agent JUL root thread";
237 this.sessiondThreadJULRoot = new Thread(julRootClient, rootThreadName);
238 this.sessiondThreadJULRoot.setDaemon(true);
239 this.sessiondThreadJULRoot.start();
240
241 return numThreads;
242 }
243
244 private synchronized Integer initLog4jClientThreads() {
245 Integer numThreads = 2;
246
247 this.log4jUserClient = new LTTngTCPSessiondClient(Domain.LOG4J,
248 this.log4jUser,
249 this.registerSem);
250
251 String userThreadName = "LTTng UST agent Log4j user thread";
252 this.sessiondThreadLog4jUser = new Thread(log4jUserClient, userThreadName);
253 this.sessiondThreadLog4jUser.setDaemon(true);
254 this.sessiondThreadLog4jUser.start();
255
256 this.log4jRootClient = new LTTngTCPSessiondClient(Domain.LOG4J,
257 this.log4jRoot,
258 this.registerSem);
259
260 String rootThreadName = "LTTng UST agent Log4j root thread";
261 this.sessiondThreadLog4jRoot = new Thread(log4jRootClient,rootThreadName);
262 this.sessiondThreadLog4jRoot.setDaemon(true);
263 this.sessiondThreadLog4jRoot.start();
264
265 return numThreads;
266 }
267
268
269 public void dispose() throws IOException {
270 if (this.useJUL) {
271 this.julUserClient.destroy();
272 this.julRootClient.destroy();
273 this.julUser.reset();
274 this.julRoot.reset();
275 }
276
277 if (this.useLog4j) {
278 this.log4jUserClient.destroy();
279 this.log4jRootClient.destroy();
280 this.log4jUser.reset();
281 this.log4jRoot.reset();
282 }
283
284 try {
285 if (this.useJUL) {
286 this.sessiondThreadJULUser.join();
287 this.sessiondThreadJULRoot.join();
288 }
289
290 if (this.useLog4j) {
291 this.sessiondThreadLog4jUser.join();
292 this.sessiondThreadLog4jRoot.join();
293 }
294
295 } catch (InterruptedException e) {
296 e.printStackTrace();
297 }
298 }
299 }
This page took 0.034511 seconds and 3 git commands to generate.