Cleanup: Add Javadoc to all public methods and members
[lttng-ust.git] / liblttng-ust-java-agent / java / lttng-ust-agent-common / 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 java.io.IOException;
21 import java.lang.reflect.InvocationTargetException;
22 import java.util.concurrent.Semaphore;
23 import java.util.concurrent.TimeUnit;
24
25 /**
26 * The central agent managing the JUL and Log4j handlers.
27 *
28 * @author David Goulet
29 */
30 public class LTTngAgent {
31
32 /* Domains */
33 static enum Domain {
34 JUL(3), LOG4J(4);
35 private int value;
36
37 private Domain(int value) {
38 this.value = value;
39 }
40
41 public int value() {
42 return value;
43 }
44 }
45
46 private static final int SEM_TIMEOUT = 3; /* Seconds */
47
48 private static LogFramework julUser;
49 private static LogFramework julRoot;
50 private static LogFramework log4jUser;
51 private static LogFramework log4jRoot;
52
53 /* Sessiond clients */
54 private static LTTngTCPSessiondClient julUserClient;
55 private static LTTngTCPSessiondClient julRootClient;
56 private static LTTngTCPSessiondClient log4jUserClient;
57 private static LTTngTCPSessiondClient log4jRootClient;
58
59 private static Thread sessiondThreadJULUser;
60 private static Thread sessiondThreadJULRoot;
61 private static Thread sessiondThreadLog4jUser;
62 private static Thread sessiondThreadLog4jRoot;
63
64 private boolean useJUL = false;
65 private boolean useLog4j = false;
66
67 /* Singleton agent object */
68 private static LTTngAgent curAgent = null;
69
70 /* Indicate if this object has been initialized. */
71 private static boolean initialized = false;
72
73 private static Semaphore registerSem;
74
75 /*
76 * Constructor is private. This is a singleton and a reference should be
77 * acquired using getLTTngAgent().
78 */
79 private LTTngAgent() {
80 initAgentJULClasses();
81
82 /* Since Log4j is a 3rd party JAR, we need to check if we can load any of its classes */
83 Boolean log4jLoaded = loadLog4jClasses();
84 if (log4jLoaded) {
85 initAgentLog4jClasses();
86 }
87
88 registerSem = new Semaphore(0, true);
89 }
90
91 private static Boolean loadLog4jClasses() {
92 Class<?> logging;
93
94 try {
95 logging = loadClass("org.apache.log4j.spi.LoggingEvent");
96 } catch (ClassNotFoundException e) {
97 /* Log4j classes not found, no need to create the relevant objects */
98 return false;
99 }
100
101 /*
102 * Detect capabilities of the log4j library. We only
103 * support log4j >= 1.2.15. The getTimeStamp() method
104 * was introduced in log4j 1.2.15, so verify that it
105 * is available.
106 *
107 * We can't rely on the getPackage().getImplementationVersion()
108 * call that would retrieves information from the manifest file
109 * found in the JAR since the manifest file shipped
110 * from upstream is known to be broken in several
111 * versions of the library.
112 *
113 * More info:
114 * https://issues.apache.org/bugzilla/show_bug.cgi?id=44370
115 */
116
117 try {
118 logging.getDeclaredMethod("getTimeStamp");
119 } catch (NoSuchMethodException e) {
120 System.err.println("Warning: The loaded log4j library is too old. Log4j tracing with LTTng will be disabled.");
121 return false;
122 } catch (NullPointerException e) {
123 /* Should never happen */
124 return false;
125 } catch (SecurityException e) {
126 return false;
127 }
128
129 return true;
130 }
131
132 private static Class<?> loadClass(String className) throws ClassNotFoundException {
133 ClassLoader loader;
134 Class<?> loadedClass;
135
136 try {
137 /* Try to load class using the current thread's context class loader */
138 loader = Thread.currentThread().getContextClassLoader();
139 loadedClass = loader.loadClass(className);
140 } catch (ClassNotFoundException e) {
141 /* Loading failed, try using the system class loader */
142 loader = ClassLoader.getSystemClassLoader();
143 loadedClass = loader.loadClass(className);
144 }
145
146 return loadedClass;
147 }
148
149 private void initAgentJULClasses() {
150 try {
151 Class<?> lttngJUL = loadClass("org.lttng.ust.agent.jul.LTTngJUL");
152 julUser = (LogFramework) lttngJUL.getDeclaredConstructor(new Class[] { Boolean.class }).newInstance(false);
153 julRoot = (LogFramework) lttngJUL.getDeclaredConstructor(new Class[] { Boolean.class }).newInstance(true);
154 this.useJUL = true;
155 } catch (ClassNotFoundException e) {
156 /* LTTng JUL classes not found, no need to create the relevant objects */
157 this.useJUL = false;
158 } catch (InstantiationException e) {
159 this.useJUL = false;
160 } catch (NoSuchMethodException e) {
161 this.useJUL = false;
162 } catch (IllegalAccessException e) {
163 this.useJUL = false;
164 } catch (InvocationTargetException e) {
165 this.useJUL = false;
166 }
167 }
168
169 private void initAgentLog4jClasses() {
170 try {
171 Class<?> lttngLog4j = loadClass("org.lttng.ust.agent.log4j.LTTngLog4j");
172 log4jUser = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(false);
173 log4jRoot = (LogFramework)lttngLog4j.getDeclaredConstructor(new Class[] {Boolean.class}).newInstance(true);
174 this.useLog4j = true;
175 } catch (ClassNotFoundException e) {
176 /* LTTng Log4j classes not found, no need to create the relevant objects */
177 this.useLog4j = false;
178 } catch (InstantiationException e) {
179 this.useLog4j = false;
180 } catch (NoSuchMethodException e) {
181 this.useLog4j = false;
182 } catch (IllegalAccessException e) {
183 this.useLog4j = false;
184 } catch (InvocationTargetException e) {
185 this.useLog4j = false;
186 }
187 }
188
189 /**
190 * Public getter to acquire a reference to this singleton object.
191 *
192 * @return The agent instance
193 * @throws IOException
194 */
195 public static synchronized LTTngAgent getLTTngAgent() throws IOException {
196 if (curAgent == null) {
197 curAgent = new LTTngAgent();
198 curAgent.init();
199 }
200
201 return curAgent;
202 }
203
204 private synchronized void init() throws SecurityException {
205 if (initialized) {
206 return;
207 }
208
209 Integer numJULThreads = 0;
210 Integer numLog4jThreads = 0;
211
212 if (this.useJUL) {
213 numJULThreads = initJULClientThreads();
214 }
215
216 if (this.useLog4j) {
217 numLog4jThreads = initLog4jClientThreads();
218 }
219
220 Integer numThreads = numJULThreads + numLog4jThreads;
221
222 /* Wait for each registration to end. */
223 try {
224 registerSem.tryAcquire(numThreads,
225 SEM_TIMEOUT,
226 TimeUnit.SECONDS);
227 } catch (InterruptedException e) {
228 e.printStackTrace();
229 }
230
231 initialized = true;
232 }
233
234 private synchronized static Integer initJULClientThreads() {
235 Integer numThreads = 2;
236
237 /* Handle user session daemon if any. */
238 julUserClient = new LTTngTCPSessiondClient(Domain.JUL,
239 julUser,
240 registerSem);
241
242 String userThreadName = "LTTng UST agent JUL user thread";
243 sessiondThreadJULUser = new Thread(julUserClient, userThreadName);
244 sessiondThreadJULUser.setDaemon(true);
245 sessiondThreadJULUser.start();
246
247 /* Handle root session daemon. */
248 julRootClient = new LTTngTCPSessiondClient(Domain.JUL,
249 julRoot,
250 registerSem);
251
252 String rootThreadName = "LTTng UST agent JUL root thread";
253 sessiondThreadJULRoot = new Thread(julRootClient, rootThreadName);
254 sessiondThreadJULRoot.setDaemon(true);
255 sessiondThreadJULRoot.start();
256
257 return numThreads;
258 }
259
260 private synchronized static Integer initLog4jClientThreads() {
261 Integer numThreads = 2;
262
263 log4jUserClient = new LTTngTCPSessiondClient(Domain.LOG4J,
264 log4jUser,
265 registerSem);
266
267 String userThreadName = "LTTng UST agent Log4j user thread";
268 sessiondThreadLog4jUser = new Thread(log4jUserClient, userThreadName);
269 sessiondThreadLog4jUser.setDaemon(true);
270 sessiondThreadLog4jUser.start();
271
272 log4jRootClient = new LTTngTCPSessiondClient(Domain.LOG4J,
273 log4jRoot,
274 registerSem);
275
276 String rootThreadName = "LTTng UST agent Log4j root thread";
277 sessiondThreadLog4jRoot = new Thread(log4jRootClient,rootThreadName);
278 sessiondThreadLog4jRoot.setDaemon(true);
279 sessiondThreadLog4jRoot.start();
280
281 return numThreads;
282 }
283
284 /**
285 * Dispose the agent. Applications should call this once they are done
286 * logging.
287 */
288 public void dispose() {
289 if (this.useJUL) {
290 julUserClient.destroy();
291 julRootClient.destroy();
292 julUser.reset();
293 julRoot.reset();
294 }
295
296 if (this.useLog4j) {
297 log4jUserClient.destroy();
298 log4jRootClient.destroy();
299 log4jUser.reset();
300 log4jRoot.reset();
301 }
302
303 try {
304 if (this.useJUL) {
305 sessiondThreadJULUser.join();
306 sessiondThreadJULRoot.join();
307 }
308
309 if (this.useLog4j) {
310 sessiondThreadLog4jUser.join();
311 sessiondThreadLog4jRoot.join();
312 }
313
314 } catch (InterruptedException e) {
315 e.printStackTrace();
316 }
317 }
318 }
This page took 0.036466 seconds and 5 git commands to generate.