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