doc/man: do not use macros in the NAME section
[lttng-ust.git] / liblttng-ust-java-agent / java / lttng-ust-agent-common / org / lttng / ust / agent / LTTngAgent.java
CommitLineData
501f6777
CB
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
18package org.lttng.ust.agent;
19
d60dfbe4 20import java.lang.reflect.Constructor;
01a00a70 21import java.lang.reflect.InvocationTargetException;
d60dfbe4
AM
22import java.lang.reflect.Method;
23import java.util.logging.Handler;
24import java.util.logging.Logger;
501f6777 25
5bfeaeca
AM
26/**
27 * The central agent managing the JUL and Log4j handlers.
28 *
29 * @author David Goulet
d60dfbe4
AM
30 * @deprecated Applications are now expected to manage their Logger and Handler
31 * objects.
5bfeaeca 32 */
d60dfbe4 33@Deprecated
501f6777 34public class LTTngAgent {
08284556 35
d60dfbe4 36 private static LTTngAgent instance = null;
501f6777 37
d60dfbe4
AM
38 /**
39 * Public getter to acquire a reference to this singleton object.
40 *
41 * @return The agent instance
42 */
43 public static synchronized LTTngAgent getLTTngAgent() {
44 if (instance == null) {
45 instance = new LTTngAgent();
501f6777 46 }
d60dfbe4
AM
47 return instance;
48 }
501f6777 49
d60dfbe4
AM
50 /**
51 * Dispose the agent. Applications should call this once they are done
52 * logging.
53 */
54 public static synchronized void dispose() {
55 if (instance != null) {
56 instance.disposeInstance();
57 instance = null;
501f6777 58 }
d60dfbe4 59 return;
501f6777
CB
60 }
61
d60dfbe4
AM
62 private ILttngHandler julHandler = null;
63 private ILttngHandler log4jAppender = null;
08284556 64
d60dfbe4
AM
65 /**
66 * Private constructor. This is a singleton and a reference should be
67 * acquired using {@link #getLTTngAgent()}.
68 */
69 private LTTngAgent() {
70 initJulHandler();
71 initLog4jAppender();
72 }
501f6777 73
d60dfbe4
AM
74 /**
75 * "Destructor" method.
76 */
77 private void disposeInstance() {
78 disposeJulHandler();
79 disposeLog4jAppender();
80 }
501f6777 81
d60dfbe4
AM
82 /**
83 * Create a LTTng-JUL handler, and attach it to the JUL root logger.
84 */
85 private void initJulHandler() {
86 try {
87 Class<?> julHandlerClass = Class.forName("org.lttng.ust.agent.jul.LttngLogHandler");
88 /*
89 * It is safer to use Constructor.newInstance() rather than
90 * Class.newInstance(), because it will catch the exceptions thrown
91 * by the constructor below (which happens if the Java library is
92 * present, but the matching JNI one is not).
93 */
94 Constructor<?> julHandlerCtor = julHandlerClass.getConstructor();
95 julHandler = (ILttngHandler) julHandlerCtor.newInstance();
96
97 /* Attach the handler to the root JUL logger */
98 Logger.getLogger("").addHandler((Handler) julHandler);
01a00a70 99
d60dfbe4 100 /*
01a00a70
AM
101 * If any of the following exceptions happen, it means we could not
102 * find or initialize LTTng JUL classes. We will not setup LTTng JUL
103 * tracing in this case.
d60dfbe4 104 */
01a00a70
AM
105 } catch (SecurityException e) {
106 } catch (IllegalAccessException e) {
107 } catch (IllegalArgumentException e) {
108 } catch (ClassNotFoundException e) {
109 } catch (NoSuchMethodException e) {
110 } catch (InstantiationException e) {
111 } catch (InvocationTargetException e) {
d60dfbe4
AM
112 }
113 }
501f6777 114
d60dfbe4
AM
115 /**
116 * Create a LTTng-logj4 appender, and attach it to the log4j root logger.
117 */
118 private void initLog4jAppender() {
119 /*
120 * Since Log4j is a 3rd party library, we first need to check if we can
121 * load any of its classes.
122 */
123 if (!testLog4jClasses()) {
124 return;
125 }
501f6777 126
d60dfbe4
AM
127 try {
128 Class<?> log4jAppenderClass = Class.forName("org.lttng.ust.agent.log4j.LttngLogAppender");
129 Constructor<?> log4jAppendCtor = log4jAppenderClass.getConstructor();
130 log4jAppender = (ILttngHandler) log4jAppendCtor.newInstance();
01a00a70 131
d60dfbe4 132 /*
01a00a70
AM
133 * If any of the following exceptions happen, it means we could not
134 * find or initialize LTTng log4j classes. We will not setup LTTng
135 * log4j tracing in this case.
d60dfbe4 136 */
01a00a70
AM
137 } catch (SecurityException e) {
138 return;
139 } catch (ClassNotFoundException e) {
140 return;
141 } catch (NoSuchMethodException e) {
142 return;
143 } catch (IllegalArgumentException e) {
144 return;
145 } catch (InstantiationException e) {
146 return;
147 } catch (IllegalAccessException e) {
148 return;
149 } catch (InvocationTargetException e) {
d60dfbe4
AM
150 return;
151 }
501f6777 152
d60dfbe4
AM
153 /*
154 * Attach the appender to the root Log4j logger. Slightly more tricky
155 * here, as log4j.Logger is not in the base Java library, and we do not
156 * want the "common" package to depend on log4j. So we have to obtain it
157 * through reflection too.
158 */
159 try {
160 Class<?> loggerClass = Class.forName("org.apache.log4j.Logger");
161 Class<?> appenderClass = Class.forName("org.apache.log4j.Appender");
501f6777 162
d60dfbe4
AM
163 Method getRootLoggerMethod = loggerClass.getMethod("getRootLogger", (Class<?>[]) null);
164 Method addAppenderMethod = loggerClass.getMethod("addAppender", appenderClass);
501f6777 165
d60dfbe4
AM
166 Object rootLogger = getRootLoggerMethod.invoke(null, (Object[]) null);
167 addAppenderMethod.invoke(rootLogger, log4jAppender);
501f6777 168
d60dfbe4 169 /*
01a00a70
AM
170 * We have checked for the log4j library version previously, none of
171 * the following exceptions should happen.
d60dfbe4 172 */
01a00a70
AM
173 } catch (SecurityException e) {
174 throw new IllegalStateException(e);
175 } catch (ClassNotFoundException e) {
176 throw new IllegalStateException(e);
177 } catch (NoSuchMethodException e) {
178 throw new IllegalStateException(e);
179 } catch (IllegalArgumentException e) {
180 throw new IllegalStateException(e);
181 } catch (IllegalAccessException e) {
182 throw new IllegalStateException(e);
183 } catch (InvocationTargetException e) {
184 throw new IllegalStateException(e);
501f6777 185 }
501f6777
CB
186 }
187
d60dfbe4
AM
188 /**
189 * Check if log4j >= 1.2.15 library is present.
190 */
191 private static boolean testLog4jClasses() {
192 Class<?> loggingEventClass;
17be0b58 193
501f6777 194 try {
d60dfbe4 195 loggingEventClass = Class.forName("org.apache.log4j.spi.LoggingEvent");
501f6777 196 } catch (ClassNotFoundException e) {
d60dfbe4
AM
197 /*
198 * Log4j classes not found, no need to create the relevant objects
199 */
17be0b58
CB
200 return false;
201 }
202
203 /*
d60dfbe4
AM
204 * Detect capabilities of the log4j library. We only support log4j >=
205 * 1.2.15. The getTimeStamp() method was introduced in log4j 1.2.15, so
206 * verify that it is available.
17be0b58 207 *
d60dfbe4
AM
208 * We can't rely on the getPackage().getImplementationVersion() call
209 * that would retrieves information from the manifest file found in the
210 * JAR since the manifest file shipped from upstream is known to be
211 * broken in several versions of the library.
17be0b58 212 *
d60dfbe4 213 * More info: https://issues.apache.org/bugzilla/show_bug.cgi?id=44370
17be0b58 214 */
17be0b58 215 try {
d60dfbe4 216 loggingEventClass.getDeclaredMethod("getTimeStamp");
17be0b58 217 } catch (NoSuchMethodException e) {
d60dfbe4
AM
218 System.err.println(
219 "Warning: The loaded log4j library is too old. Log4j tracing with LTTng will be disabled.");
17be0b58
CB
220 return false;
221 } catch (SecurityException e) {
222 return false;
501f6777
CB
223 }
224
17be0b58 225 return true;
501f6777
CB
226 }
227
5bfeaeca 228 /**
d60dfbe4 229 * Detach the JUL handler from its logger and close it.
501f6777 230 */
d60dfbe4
AM
231 private void disposeJulHandler() {
232 if (julHandler == null) {
233 /* The JUL handler was not activated, we have nothing to do */
501f6777
CB
234 return;
235 }
d60dfbe4
AM
236 Logger.getLogger("").removeHandler((Handler) julHandler);
237 julHandler.close();
238 julHandler = null;
501f6777
CB
239 }
240
5bfeaeca 241 /**
d60dfbe4 242 * Detach the log4j appender from its logger and close it.
5bfeaeca 243 */
d60dfbe4
AM
244 private void disposeLog4jAppender() {
245 if (log4jAppender == null) {
246 /* The log4j appender was not active, we have nothing to do */
247 return;
501f6777
CB
248 }
249
d60dfbe4
AM
250 /*
251 * Detach the appender from the log4j root logger. Again, we have to do
252 * this via reflection.
253 */
501f6777 254 try {
d60dfbe4
AM
255 Class<?> loggerClass = Class.forName("org.apache.log4j.Logger");
256 Class<?> appenderClass = Class.forName("org.apache.log4j.Appender");
501f6777 257
d60dfbe4
AM
258 Method getRootLoggerMethod = loggerClass.getMethod("getRootLogger", (Class<?>[]) null);
259 Method removeAppenderMethod = loggerClass.getMethod("removeAppender", appenderClass);
501f6777 260
d60dfbe4
AM
261 Object rootLogger = getRootLoggerMethod.invoke(null, (Object[]) null);
262 removeAppenderMethod.invoke(rootLogger, log4jAppender);
263
d60dfbe4 264 /*
01a00a70
AM
265 * We were able to attach the appender previously, we should not
266 * have problems here either!
d60dfbe4 267 */
01a00a70
AM
268 } catch (SecurityException e) {
269 throw new IllegalStateException(e);
270 } catch (ClassNotFoundException e) {
271 throw new IllegalStateException(e);
272 } catch (NoSuchMethodException e) {
273 throw new IllegalStateException(e);
274 } catch (IllegalArgumentException e) {
275 throw new IllegalStateException(e);
276 } catch (IllegalAccessException e) {
277 throw new IllegalStateException(e);
278 } catch (InvocationTargetException e) {
279 throw new IllegalStateException(e);
501f6777 280 }
d60dfbe4
AM
281
282 /* Close the appender */
283 log4jAppender.close();
284 log4jAppender = null;
501f6777 285 }
d60dfbe4 286
501f6777 287}
This page took 0.036891 seconds and 4 git commands to generate.