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, 2021 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: * @param level the log level.
209: * @param msg the message.
210: */
211: public void log(Level level, String msg) {
212:         ifDebugOut(msg);
213:•        if (logger.isLoggable(level)) {
214:          final StackTraceElement frame = inferCaller();
215:          logger.logp(level, frame.getClassName(), frame.getMethodName(), msg);
216:         }
217: }
218:
219: /**
220: * Log the message at the specified level.
221: * @param level the log level.
222: * @param msg the message.
223: * @param param1 the additional parameter.
224: */
225: public void log(Level level, String msg, Object param1) {
226:•        if (debug) {
227:          msg = MessageFormat.format(msg, new Object[] { param1 });
228:          debugOut(msg);
229:         }
230:         
231:•        if (logger.isLoggable(level)) {
232:          final StackTraceElement frame = inferCaller();
233:          logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, param1);
234:         }
235: }
236:
237: /**
238: * Log the message at the specified level.
239: * @param level the log level.
240: * @param msg the message.
241: * @param params the message parameters.
242: */
243: public void log(Level level, String msg, Object... params) {
244:•        if (debug) {
245:          msg = MessageFormat.format(msg, params);
246:          debugOut(msg);
247:         }
248:         
249:•        if (logger.isLoggable(level)) {
250:          final StackTraceElement frame = inferCaller();
251:          logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, params);
252:         }
253: }
254:
255: /**
256: * Log the message at the specified level using a format string.
257: * @param level the log level.
258: * @param msg the message format string.
259: * @param params the message parameters.
260: *
261: * @since        JavaMail 1.5.4
262: */
263: public void logf(Level level, String msg, Object... params) {
264:         msg = String.format(msg, params);
265:         ifDebugOut(msg);
266:         logger.log(level, msg);
267: }
268:
269: /**
270: * Log the message at the specified level.
271: * @param level the log level.
272: * @param msg the message.
273: * @param thrown the throwable to log.
274: */
275: public void log(Level level, String msg, Throwable thrown) {
276:•        if (debug) {
277:•         if (thrown != null) {
278:                 debugOut(msg + ", THROW: ");
279:                 thrown.printStackTrace(out);
280:          } else {
281:                 debugOut(msg);
282:          }
283:         }
284:
285:•        if (logger.isLoggable(level)) {
286:          final StackTraceElement frame = inferCaller();
287:          logger.logp(level, frame.getClassName(), frame.getMethodName(), msg, thrown);
288:         }
289: }
290:
291: /**
292: * Log a message at the CONFIG level.
293: * @param msg the message.
294: */
295: public void config(String msg) {
296:         log(Level.CONFIG, msg);
297: }
298:
299: /**
300: * Log a message at the FINE level.
301: * @param msg the message.
302: */
303: public void fine(String msg) {
304:         log(Level.FINE, msg);
305: }
306:
307: /**
308: * Log a message at the FINER level.
309: * @param msg the message.
310: */
311: public void finer(String msg) {
312:         log(Level.FINER, msg);
313: }
314:
315: /**
316: * Log a message at the FINEST level.
317: * @param msg the message.
318: */
319: public void finest(String msg) {
320:         log(Level.FINEST, msg);
321: }
322:
323: /**
324: * If "debug" is set, or our embedded Logger is loggable at the
325: * given level, return true.
326: * @param level the log level.
327: * @return true if loggable.
328: */
329: public boolean isLoggable(Level level) {
330:•        return debug || logger.isLoggable(level);
331: }
332:
333: /**
334: * Common code to conditionally log debug statements.
335: * @param msg the message to log.
336: */
337: private void ifDebugOut(String msg) {
338:•        if (debug)
339:          debugOut(msg);
340: }
341:
342: /**
343: * Common formatting for debug output.
344: * @param msg the message to log.
345: */
346: private void debugOut(String msg) {
347:•        if (prefix != null)
348:          out.println(prefix + ": " + msg);
349:         else
350:          out.println(msg);
351: }
352:
353: /**
354: * Return the package name of the class.
355: * Sometimes there will be no Package object for the class,
356: * e.g., if the class loader hasn't created one (see Class.getPackage()).
357: * @param clazz the class source.
358: * @return the package name or an empty string.
359: */
360: private String packageOf(Class<?> clazz) {
361:         Package p = clazz.getPackage();
362:•        if (p != null)
363:          return p.getName();                // hopefully the common case
364:         String cname = clazz.getName();
365:         int i = cname.lastIndexOf('.');
366:•        if (i > 0)
367:          return cname.substring(0, i);
368:         // no package name, now what?
369:         return "";
370: }
371:
372: /**
373: * A disadvantage of not being able to use Logger directly in Jakarta Mail
374: * code is that the "source class" information that Logger guesses will
375: * always refer to this class instead of our caller. This method
376: * duplicates what Logger does to try to find *our* caller, so that
377: * Logger doesn't have to do it (and get the wrong answer), and because
378: * our caller is what's wanted.
379: * @return StackTraceElement that logged the message. Treat as read-only.
380: */
381: private StackTraceElement inferCaller() {
382:         // Get the stack trace.
383:         StackTraceElement stack[] = (new Throwable()).getStackTrace();
384:         // First, search back to a method in the Logger class.
385:         int ix = 0;
386:•        while (ix < stack.length) {
387:          StackTraceElement frame = stack[ix];
388:          String cname = frame.getClassName();
389:•         if (isLoggerImplFrame(cname)) {
390:                 break;
391:          }
392:          ix++;
393:         }
394:         // Now search for the first frame before the "Logger" class.
395:•        while (ix < stack.length) {
396:          StackTraceElement frame = stack[ix];
397:          String cname = frame.getClassName();
398:•         if (!isLoggerImplFrame(cname)) {
399:                 // We've found the relevant frame.
400:                 return frame;
401:          }
402:          ix++;
403:         }
404:         // We haven't found a suitable frame, so just punt. This is
405:         // OK as we are only committed to making a "best effort" here.
406:         return new StackTraceElement(MailLogger.class.getName(), "log",
407: MailLogger.class.getName(), -1);
408: }
409:
410: /**
411: * Frames to ignore as part of the MailLogger to JUL bridge.
412: * @param cname the class name.
413: * @return true if the class name is part of the MailLogger bridge.
414: */
415: private boolean isLoggerImplFrame(String cname) {
416:         return MailLogger.class.getName().equals(cname);
417: }
418: }