Skip to content

Package: MailLogger

MailLogger

nameinstructionbranchcomplexitylinemethod
MailLogger(Class, String, Session)
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
MailLogger(Class, String, String, boolean, PrintStream)
M: 33 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
MailLogger(Class, String, boolean, PrintStream)
M: 24 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
MailLogger(String, String, Session)
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
MailLogger(String, String, boolean, PrintStream)
M: 20 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
config(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
debugOut(String)
M: 23 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
fine(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
finer(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
finest(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
getLogger(Class, String)
M: 10 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getLogger(String, String)
M: 10 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getSubLogger(String, String)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getSubLogger(String, String, boolean)
M: 20 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
ifDebugOut(String)
M: 7 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
inferCaller()
M: 54 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 18 C: 0
0%
M: 1 C: 0
0%
isLoggable(Level)
M: 12 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
isLoggerImplFrame(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
log(Level, String)
M: 21 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
log(Level, String, Object)
M: 34 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
log(Level, String, Object[])
M: 29 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
log(Level, String, Throwable)
M: 42 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%
logf(Level, String, Object[])
M: 13 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
packageOf(Class)
M: 24 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package jakarta.mail;
18:
19: import java.io.PrintStream;
20: import java.text.MessageFormat;
21: import java.util.logging.Level;
22: import java.util.logging.Logger;
23:
24: /**
25: * A simplified logger used by Jakarta Mail to handle logging to a
26: * PrintStream and logging through a java.util.logging.Logger.
27: * If debug is set, messages are written to the PrintStream and
28: * prefixed by the specified prefix (which is not included in
29: * Logger messages).
30: * Messages are logged by the Logger based on the configuration
31: * of the logging system.
32: */
33:
34: /*
35: * It would be so much simpler to just subclass Logger and override
36: * the log(LogRecord) method, as the javadocs suggest, but that doesn't
37: * work because Logger makes the decision about whether to log the message
38: * or not before calling the log(LogRecord) method. Instead, we just
39: * provide the few log methods we need here.
40: */
41:
42: final class MailLogger {
43: /**
44: * For log messages.
45: */
46: private final Logger logger;
47: /**
48: * For debug output.
49: */
50: private final String prefix;
51: /**
52: * Produce debug output?
53: */
54: private final boolean debug;
55: /**
56: * Stream for debug output.
57: */
58: private final PrintStream out;
59:
60: /**
61: * Construct a new MailLogger using the specified Logger name,
62: * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
63: *
64: * @param name the Logger name
65: * @param prefix the prefix for debug output, or null for none
66: * @param debug if true, write to PrintStream
67: * @param out the PrintStream to write to
68: */
69: public MailLogger(String name, String prefix, boolean debug,
70: PrintStream out) {
71: logger = Logger.getLogger(name);
72: this.prefix = prefix;
73: this.debug = debug;
74:• this.out = out != null ? out : System.out;
75: }
76:
77: /**
78: * Construct a new MailLogger using the specified class' package
79: * name as the Logger name,
80: * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
81: *
82: * @param clazz the Logger name is the package name of this class
83: * @param prefix the prefix for debug output, or null for none
84: * @param debug if true, write to PrintStream
85: * @param out the PrintStream to write to
86: */
87: public MailLogger(Class<?> clazz, String prefix, boolean debug,
88: PrintStream out) {
89: String name = packageOf(clazz);
90: logger = Logger.getLogger(name);
91: this.prefix = prefix;
92: this.debug = debug;
93:• this.out = out != null ? out : System.out;
94: }
95:
96: /**
97: * Construct a new MailLogger using the specified class' package
98: * name combined with the specified subname as the Logger name,
99: * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
100: *
101: * @param clazz the Logger name is the package name of this class
102: * @param subname the Logger name relative to this Logger name
103: * @param prefix the prefix for debug output, or null for none
104: * @param debug if true, write to PrintStream
105: * @param out the PrintStream to write to
106: */
107: public MailLogger(Class<?> clazz, String subname, String prefix, boolean debug,
108: PrintStream out) {
109: String name = packageOf(clazz) + "." + subname;
110: logger = Logger.getLogger(name);
111: this.prefix = prefix;
112: this.debug = debug;
113:• this.out = out != null ? out : System.out;
114: }
115:
116: /**
117: * Construct a new MailLogger using the specified Logger name and
118: * debug prefix (e.g., "DEBUG"). Get the debug flag and PrintStream
119: * from the Session.
120: *
121: * @param name the Logger name
122: * @param prefix the prefix for debug output, or null for none
123: * @param session where to get the debug flag and PrintStream
124: */
125: @Deprecated
126: public MailLogger(String name, String prefix, Session session) {
127: this(name, prefix, session.getDebug(), session.getDebugOut());
128: }
129:
130: /**
131: * Construct a new MailLogger using the specified class' package
132: * name as the Logger name and the specified
133: * debug prefix (e.g., "DEBUG"). Get the debug flag and PrintStream
134: * from the Session.
135: *
136: * @param clazz the Logger name is the package name of this class
137: * @param prefix the prefix for debug output, or null for none
138: * @param session where to get the debug flag and PrintStream
139: */
140: @Deprecated
141: public MailLogger(Class<?> clazz, String prefix, Session session) {
142: this(clazz, prefix, session.getDebug(), session.getDebugOut());
143: }
144:
145: /**
146: * Create a MailLogger that uses a Logger with the specified name
147: * and prefix. The new MailLogger uses the same debug flag and
148: * PrintStream as this MailLogger.
149: *
150: * @param name the Logger name
151: * @param prefix the prefix for debug output, or null for none
152: * @return a MailLogger for the given name and prefix.
153: */
154: public MailLogger getLogger(String name, String prefix) {
155: return new MailLogger(name, prefix, debug, out);
156: }
157:
158: /**
159: * Create a MailLogger using the specified class' package
160: * name as the Logger name and the specified prefix.
161: * The new MailLogger uses the same debug flag and
162: * PrintStream as this MailLogger.
163: *
164: * @param clazz the Logger name is the package name of this class
165: * @param prefix the prefix for debug output, or null for none
166: * @return a MailLogger for the given name and prefix.
167: */
168: public MailLogger getLogger(Class<?> clazz, String prefix) {
169: return new MailLogger(clazz, prefix, debug, out);
170: }
171:
172: /**
173: * Create a MailLogger that uses a Logger whose name is composed
174: * of this MailLogger's name plus the specified sub-name, separated
175: * by a dot. The new MailLogger uses the new prefix for debug output.
176: * This is used primarily by the protocol trace code that wants a
177: * different prefix (none).
178: *
179: * @param subname the Logger name relative to this Logger name
180: * @param prefix the prefix for debug output, or null for none
181: * @return a MailLogger for the given name and prefix.
182: */
183: public MailLogger getSubLogger(String subname, String prefix) {
184: return new MailLogger(logger.getName() + "." + subname, prefix,
185: debug, out);
186: }
187:
188: /**
189: * Create a MailLogger that uses a Logger whose name is composed
190: * of this MailLogger's name plus the specified sub-name, separated
191: * by a dot. The new MailLogger uses the new prefix for debug output.
192: * This is used primarily by the protocol trace code that wants a
193: * different prefix (none).
194: *
195: * @param subname the Logger name relative to this Logger name
196: * @param prefix the prefix for debug output, or null for none
197: * @param debug the debug flag for the sub-logger
198: * @return a MailLogger for the given name and prefix.
199: */
200: public MailLogger getSubLogger(String subname, String prefix,
201: boolean debug) {
202: return new MailLogger(logger.getName() + "." + subname, prefix,
203: debug, out);
204: }
205:
206: /**
207: * Log the message at the specified level.
208: *
209: * @param level the log level.
210: * @param msg the message.
211: */
212: public void log(Level level, String msg) {
213: ifDebugOut(msg);
214:• if (logger.isLoggable(level)) {
215: final StackTraceElement frame = inferCaller();
216: logger.logp(level, frame.getClassName(), frame.getMethodName(), msg);
217: }
218: }
219:
220: /**
221: * Log the message at the specified level.
222: *
223: * @param level the log level.
224: * @param msg the message.
225: * @param param1 the additional parameter.
226: */
227: public void log(Level level, String msg, Object param1) {
228:• if (debug) {
229: msg = MessageFormat.format(msg, new Object[]{param1});
230: debugOut(msg);
231: }
232:
233:• if (logger.isLoggable(level)) {
234: final StackTraceElement frame = inferCaller();
235: logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, param1);
236: }
237: }
238:
239: /**
240: * Log the message at the specified level.
241: *
242: * @param level the log level.
243: * @param msg the message.
244: * @param params the message parameters.
245: */
246: public void log(Level level, String msg, Object... params) {
247:• if (debug) {
248: msg = MessageFormat.format(msg, params);
249: debugOut(msg);
250: }
251:
252:• if (logger.isLoggable(level)) {
253: final StackTraceElement frame = inferCaller();
254: logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, params);
255: }
256: }
257:
258: /**
259: * Log the message at the specified level using a format string.
260: *
261: * @param level the log level.
262: * @param msg the message format string.
263: * @param params the message parameters.
264: * @since JavaMail 1.5.4
265: */
266: public void logf(Level level, String msg, Object... params) {
267: msg = String.format(msg, params);
268: ifDebugOut(msg);
269: logger.log(level, msg);
270: }
271:
272: /**
273: * Log the message at the specified level.
274: *
275: * @param level the log level.
276: * @param msg the message.
277: * @param thrown the throwable to log.
278: */
279: public void log(Level level, String msg, Throwable thrown) {
280:• if (debug) {
281:• if (thrown != null) {
282: debugOut(msg + ", THROW: ");
283: thrown.printStackTrace(out);
284: } else {
285: debugOut(msg);
286: }
287: }
288:
289:• if (logger.isLoggable(level)) {
290: final StackTraceElement frame = inferCaller();
291: logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, thrown);
292: }
293: }
294:
295: /**
296: * Log a message at the CONFIG level.
297: *
298: * @param msg the message.
299: */
300: public void config(String msg) {
301: log(Level.CONFIG, msg);
302: }
303:
304: /**
305: * Log a message at the FINE level.
306: *
307: * @param msg the message.
308: */
309: public void fine(String msg) {
310: log(Level.FINE, msg);
311: }
312:
313: /**
314: * Log a message at the FINER level.
315: *
316: * @param msg the message.
317: */
318: public void finer(String msg) {
319: log(Level.FINER, msg);
320: }
321:
322: /**
323: * Log a message at the FINEST level.
324: *
325: * @param msg the message.
326: */
327: public void finest(String msg) {
328: log(Level.FINEST, msg);
329: }
330:
331: /**
332: * If "debug" is set, or our embedded Logger is loggable at the
333: * given level, return true.
334: *
335: * @param level the log level.
336: * @return true if loggable.
337: */
338: public boolean isLoggable(Level level) {
339:• return debug || logger.isLoggable(level);
340: }
341:
342: /**
343: * Common code to conditionally log debug statements.
344: *
345: * @param msg the message to log.
346: */
347: private void ifDebugOut(String msg) {
348:• if (debug)
349: debugOut(msg);
350: }
351:
352: /**
353: * Common formatting for debug output.
354: *
355: * @param msg the message to log.
356: */
357: private void debugOut(String msg) {
358:• if (prefix != null)
359: out.println(prefix + ": " + msg);
360: else
361: out.println(msg);
362: }
363:
364: /**
365: * Return the package name of the class.
366: * Sometimes there will be no Package object for the class,
367: * e.g., if the class loader hasn't created one (see Class.getPackage()).
368: *
369: * @param clazz the class source.
370: * @return the package name or an empty string.
371: */
372: private String packageOf(Class<?> clazz) {
373: Package p = clazz.getPackage();
374:• if (p != null)
375: return p.getName(); // hopefully the common case
376: String cname = clazz.getName();
377: int i = cname.lastIndexOf('.');
378:• if (i > 0)
379: return cname.substring(0, i);
380: // no package name, now what?
381: return "";
382: }
383:
384: /**
385: * A disadvantage of not being able to use Logger directly in Jakarta Mail
386: * code is that the "source class" information that Logger guesses will
387: * always refer to this class instead of our caller. This method
388: * duplicates what Logger does to try to find *our* caller, so that
389: * Logger doesn't have to do it (and get the wrong answer), and because
390: * our caller is what's wanted.
391: *
392: * @return StackTraceElement that logged the message. Treat as read-only.
393: */
394: private StackTraceElement inferCaller() {
395: // Get the stack trace.
396: StackTraceElement[] stack = (new Throwable()).getStackTrace();
397: // First, search back to a method in the Logger class.
398: int ix = 0;
399:• while (ix < stack.length) {
400: StackTraceElement frame = stack[ix];
401: String cname = frame.getClassName();
402:• if (isLoggerImplFrame(cname)) {
403: break;
404: }
405: ix++;
406: }
407: // Now search for the first frame before the "Logger" class.
408:• while (ix < stack.length) {
409: StackTraceElement frame = stack[ix];
410: String cname = frame.getClassName();
411:• if (!isLoggerImplFrame(cname)) {
412: // We've found the relevant frame.
413: return frame;
414: }
415: ix++;
416: }
417: // We haven't found a suitable frame, so just punt. This is
418: // OK as we are only committed to making a "best effort" here.
419: return new StackTraceElement(MailLogger.class.getName(), "log",
420: MailLogger.class.getName(), -1);
421: }
422:
423: /**
424: * Frames to ignore as part of the MailLogger to JUL bridge.
425: *
426: * @param cname the class name.
427: * @return true if the class name is part of the MailLogger bridge.
428: */
429: private boolean isLoggerImplFrame(String cname) {
430: return MailLogger.class.getName().equals(cname);
431: }
432: }