Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.logging/share/classes/java/util/logging/Logger.java
41159 views
1
/*
2
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.util.logging;
27
28
import java.lang.ref.WeakReference;
29
import java.security.AccessController;
30
import java.security.PrivilegedAction;
31
import java.util.ArrayList;
32
import java.util.Iterator;
33
import java.util.Locale;
34
import java.util.MissingResourceException;
35
import java.util.Objects;
36
import java.util.ResourceBundle;
37
import java.util.concurrent.CopyOnWriteArrayList;
38
import java.util.function.Supplier;
39
40
import jdk.internal.access.JavaUtilResourceBundleAccess;
41
import jdk.internal.access.SharedSecrets;
42
import jdk.internal.reflect.CallerSensitive;
43
import jdk.internal.reflect.Reflection;
44
import static jdk.internal.logger.DefaultLoggerFinder.isSystem;
45
46
/**
47
* A Logger object is used to log messages for a specific
48
* system or application component. Loggers are normally named,
49
* using a hierarchical dot-separated namespace. Logger names
50
* can be arbitrary strings, but they should normally be based on
51
* the package name or class name of the logged component, such
52
* as java.net or javax.swing. In addition it is possible to create
53
* "anonymous" Loggers that are not stored in the Logger namespace.
54
* <p>
55
* Logger objects may be obtained by calls on one of the getLogger
56
* factory methods. These will either create a new Logger or
57
* return a suitable existing Logger. It is important to note that
58
* the Logger returned by one of the {@code getLogger} factory methods
59
* may be garbage collected at any time if a strong reference to the
60
* Logger is not kept.
61
* <p>
62
* Logging messages will be forwarded to registered Handler
63
* objects, which can forward the messages to a variety of
64
* destinations, including consoles, files, OS logs, etc.
65
* <p>
66
* Each Logger keeps track of a "parent" Logger, which is its
67
* nearest existing ancestor in the Logger namespace.
68
* <p>
69
* Each Logger has a "Level" associated with it. This reflects
70
* a minimum Level that this logger cares about. If a Logger's
71
* level is set to {@code null}, then its effective level is inherited
72
* from its parent, which may in turn obtain it recursively from its
73
* parent, and so on up the tree.
74
* <p>
75
* The log level can be configured based on the properties from the
76
* logging configuration file, as described in the description
77
* of the LogManager class. However it may also be dynamically changed
78
* by calls on the Logger.setLevel method. If a logger's level is
79
* changed the change may also affect child loggers, since any child
80
* logger that has {@code null} as its level will inherit its
81
* effective level from its parent.
82
* <p>
83
* On each logging call the Logger initially performs a cheap
84
* check of the request level (e.g., SEVERE or FINE) against the
85
* effective log level of the logger. If the request level is
86
* lower than the log level, the logging call returns immediately.
87
* <p>
88
* After passing this initial (cheap) test, the Logger will allocate
89
* a LogRecord to describe the logging message. It will then call a
90
* Filter (if present) to do a more detailed check on whether the
91
* record should be published. If that passes it will then publish
92
* the LogRecord to its output Handlers. By default, loggers also
93
* publish to their parent's Handlers, recursively up the tree.
94
* <p>
95
* Each Logger may have a {@code ResourceBundle} associated with it.
96
* The {@code ResourceBundle} may be specified by name, using the
97
* {@link #getLogger(java.lang.String, java.lang.String)} factory
98
* method, or by value - using the {@link
99
* #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method.
100
* This bundle will be used for localizing logging messages.
101
* If a Logger does not have its own {@code ResourceBundle} or resource bundle
102
* name, then it will inherit the {@code ResourceBundle} or resource bundle name
103
* from its parent, recursively up the tree.
104
* <p>
105
* Most of the logger output methods take a "msg" argument. This
106
* msg argument may be either a raw value or a localization key.
107
* During formatting, if the logger has (or inherits) a localization
108
* {@code ResourceBundle} and if the {@code ResourceBundle} has a mapping for
109
* the msg string, then the msg string is replaced by the localized value.
110
* Otherwise the original msg string is used. Typically, formatters use
111
* java.text.MessageFormat style formatting to format parameters, so
112
* for example a format string "{0} {1}" would format two parameters
113
* as strings.
114
* <p>
115
* A set of methods alternatively take a "msgSupplier" instead of a "msg"
116
* argument. These methods take a {@link Supplier}{@code <String>} function
117
* which is invoked to construct the desired log message only when the message
118
* actually is to be logged based on the effective log level thus eliminating
119
* unnecessary message construction. For example, if the developer wants to
120
* log system health status for diagnosis, with the String-accepting version,
121
* the code would look like:
122
* <pre>{@code
123
*
124
* class DiagnosisMessages {
125
* static String systemHealthStatus() {
126
* // collect system health information
127
* ...
128
* }
129
* }
130
* ...
131
* logger.log(Level.FINER, DiagnosisMessages.systemHealthStatus());
132
* }</pre>
133
* With the above code, the health status is collected unnecessarily even when
134
* the log level FINER is disabled. With the Supplier-accepting version as
135
* below, the status will only be collected when the log level FINER is
136
* enabled.
137
* <pre>{@code
138
*
139
* logger.log(Level.FINER, DiagnosisMessages::systemHealthStatus);
140
* }</pre>
141
* <p>
142
* When looking for a {@code ResourceBundle}, the logger will first look at
143
* whether a bundle was specified using {@link
144
* #setResourceBundle(java.util.ResourceBundle) setResourceBundle}, and then
145
* only whether a resource bundle name was specified through the {@link
146
* #getLogger(java.lang.String, java.lang.String) getLogger} factory method.
147
* If no {@code ResourceBundle} or no resource bundle name is found,
148
* then it will use the nearest {@code ResourceBundle} or resource bundle
149
* name inherited from its parent tree.<br>
150
* When a {@code ResourceBundle} was inherited or specified through the
151
* {@link
152
* #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method, then
153
* that {@code ResourceBundle} will be used. Otherwise if the logger only
154
* has or inherited a resource bundle name, then that resource bundle name
155
* will be mapped to a {@code ResourceBundle} object, using the default Locale
156
* at the time of logging.
157
* <br id="ResourceBundleMapping">When mapping resource bundle names to
158
* {@code ResourceBundle} objects, the logger will first try to use the
159
* Thread's {@linkplain java.lang.Thread#getContextClassLoader() context class
160
* loader} to map the given resource bundle name to a {@code ResourceBundle}.
161
* If the thread context class loader is {@code null}, it will try the
162
* {@linkplain java.lang.ClassLoader#getSystemClassLoader() system class loader}
163
* instead. If the {@code ResourceBundle} is still not found, it will use the
164
* class loader of the first caller of the {@link
165
* #getLogger(java.lang.String, java.lang.String) getLogger} factory method.
166
* <p>
167
* Formatting (including localization) is the responsibility of
168
* the output Handler, which will typically call a Formatter.
169
* <p>
170
* Note that formatting need not occur synchronously. It may be delayed
171
* until a LogRecord is actually written to an external sink.
172
* <p>
173
* The logging methods are grouped in five main categories:
174
* <ul>
175
* <li><p>
176
* There are a set of "log" methods that take a log level, a message
177
* string, and optionally some parameters to the message string.
178
* <li><p>
179
* There are a set of "logp" methods (for "log precise") that are
180
* like the "log" methods, but also take an explicit source class name
181
* and method name.
182
* <li><p>
183
* There are a set of "logrb" method (for "log with resource bundle")
184
* that are like the "logp" method, but also take an explicit resource
185
* bundle object for use in localizing the log message.
186
* <li><p>
187
* There are convenience methods for tracing method entries (the
188
* "entering" methods), method returns (the "exiting" methods) and
189
* throwing exceptions (the "throwing" methods).
190
* <li><p>
191
* Finally, there are a set of convenience methods for use in the
192
* very simplest cases, when a developer simply wants to log a
193
* simple string at a given log level. These methods are named
194
* after the standard Level names ("severe", "warning", "info", etc.)
195
* and take a single argument, a message string.
196
* </ul>
197
* <p>
198
* For the methods that do not take an explicit source name and
199
* method name, the Logging framework will make a "best effort"
200
* to determine which class and method called into the logging method.
201
* However, it is important to realize that this automatically inferred
202
* information may only be approximate (or may even be quite wrong!).
203
* Virtual machines are allowed to do extensive optimizations when
204
* JITing and may entirely remove stack frames, making it impossible
205
* to reliably locate the calling class and method.
206
* <P>
207
* All methods on Logger are multi-thread safe.
208
* <p>
209
* <b>Subclassing Information:</b> Note that a LogManager class may
210
* provide its own implementation of named Loggers for any point in
211
* the namespace. Therefore, any subclasses of Logger (unless they
212
* are implemented in conjunction with a new LogManager class) should
213
* take care to obtain a Logger instance from the LogManager class and
214
* should delegate operations such as "isLoggable" and "log(LogRecord)"
215
* to that instance. Note that in order to intercept all logging
216
* output, subclasses need only override the log(LogRecord) method.
217
* All the other logging methods are implemented as calls on this
218
* log(LogRecord) method.
219
*
220
* @since 1.4
221
*/
222
public class Logger {
223
private static final Handler emptyHandlers[] = new Handler[0];
224
private static final int offValue = Level.OFF.intValue();
225
226
static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
227
228
// This class is immutable and it is important that it remains so.
229
private static final class LoggerBundle {
230
final String resourceBundleName; // Base name of the bundle.
231
final ResourceBundle userBundle; // Bundle set through setResourceBundle.
232
private LoggerBundle(String resourceBundleName, ResourceBundle bundle) {
233
this.resourceBundleName = resourceBundleName;
234
this.userBundle = bundle;
235
}
236
boolean isSystemBundle() {
237
return SYSTEM_LOGGER_RB_NAME.equals(resourceBundleName);
238
}
239
static LoggerBundle get(String name, ResourceBundle bundle) {
240
if (name == null && bundle == null) {
241
return NO_RESOURCE_BUNDLE;
242
} else if (SYSTEM_LOGGER_RB_NAME.equals(name) && bundle == null) {
243
return SYSTEM_BUNDLE;
244
} else {
245
return new LoggerBundle(name, bundle);
246
}
247
}
248
}
249
250
// This instance will be shared by all loggers created by the system
251
// code
252
private static final LoggerBundle SYSTEM_BUNDLE =
253
new LoggerBundle(SYSTEM_LOGGER_RB_NAME, null);
254
255
// This instance indicates that no resource bundle has been specified yet,
256
// and it will be shared by all loggers which have no resource bundle.
257
private static final LoggerBundle NO_RESOURCE_BUNDLE =
258
new LoggerBundle(null, null);
259
260
// Calling SharedSecrets.getJavaUtilResourceBundleAccess()
261
// forces the initialization of ResourceBundle.class, which
262
// can be too early if the VM has not finished booting yet.
263
private static final class RbAccess {
264
static final JavaUtilResourceBundleAccess RB_ACCESS =
265
SharedSecrets.getJavaUtilResourceBundleAccess();
266
}
267
268
// A value class that holds the logger configuration data.
269
// This configuration can be shared between an application logger
270
// and a system logger of the same name.
271
private static final class ConfigurationData {
272
273
// The delegate field is used to avoid races while
274
// merging configuration. This will ensure that any pending
275
// configuration action on an application logger will either
276
// be finished before the merge happens, or will be forwarded
277
// to the system logger configuration after the merge is completed.
278
// By default delegate=this.
279
private volatile ConfigurationData delegate;
280
281
volatile boolean useParentHandlers;
282
volatile Filter filter;
283
volatile Level levelObject;
284
volatile int levelValue; // current effective level value
285
final CopyOnWriteArrayList<Handler> handlers =
286
new CopyOnWriteArrayList<>();
287
288
ConfigurationData() {
289
delegate = this;
290
useParentHandlers = true;
291
levelValue = Level.INFO.intValue();
292
}
293
294
void setUseParentHandlers(boolean flag) {
295
useParentHandlers = flag;
296
if (delegate != this) {
297
// merge in progress - propagate value to system peer.
298
final ConfigurationData system = delegate;
299
synchronized (system) {
300
system.useParentHandlers = useParentHandlers;
301
}
302
}
303
}
304
305
void setFilter(Filter f) {
306
filter = f;
307
if (delegate != this) {
308
// merge in progress - propagate value to system peer.
309
final ConfigurationData system = delegate;
310
synchronized (system) {
311
system.filter = filter;
312
}
313
}
314
}
315
316
void setLevelObject(Level l) {
317
levelObject = l;
318
if (delegate != this) {
319
// merge in progress - propagate value to system peer.
320
final ConfigurationData system = delegate;
321
synchronized (system) {
322
system.levelObject = levelObject;
323
}
324
}
325
}
326
327
void setLevelValue(int v) {
328
levelValue = v;
329
if (delegate != this) {
330
// merge in progress - propagate value to system peer.
331
final ConfigurationData system = delegate;
332
synchronized (system) {
333
system.levelValue = levelValue;
334
}
335
}
336
}
337
338
void addHandler(Handler h) {
339
if (handlers.add(h)) {
340
if (delegate != this) {
341
// merge in progress - propagate value to system peer.
342
final ConfigurationData system = delegate;
343
synchronized (system) {
344
system.handlers.addIfAbsent(h);
345
}
346
}
347
}
348
}
349
350
void removeHandler(Handler h) {
351
if (handlers.remove(h)) {
352
if (delegate != this) {
353
// merge in progress - propagate value to system peer.
354
final ConfigurationData system = delegate;
355
synchronized (system) {
356
system.handlers.remove(h);
357
}
358
}
359
}
360
}
361
362
ConfigurationData merge(Logger systemPeer) {
363
if (!systemPeer.isSystemLogger) {
364
// should never come here
365
throw new InternalError("not a system logger");
366
}
367
368
ConfigurationData system = systemPeer.config;
369
370
if (system == this) {
371
// nothing to do
372
return system;
373
}
374
375
synchronized (system) {
376
// synchronize before checking on delegate to counter
377
// race conditions where two threads might attempt to
378
// merge concurrently
379
if (delegate == system) {
380
// merge already performed;
381
return system;
382
}
383
384
// publish system as the temporary delegate configuration.
385
// This should take care of potential race conditions where
386
// an other thread might attempt to call e.g. setlevel on
387
// the application logger while merge is in progress.
388
// (see implementation of ConfigurationData::setLevel)
389
delegate = system;
390
391
// merge this config object data into the system config
392
system.useParentHandlers = useParentHandlers;
393
system.filter = filter;
394
system.levelObject = levelObject;
395
system.levelValue = levelValue;
396
397
// Prevent race condition in case two threads attempt to merge
398
// configuration and add handlers at the same time. We don't want
399
// to add the same handlers twice.
400
//
401
// Handlers are created and loaded by LogManager.addLogger. If we
402
// reach here, then it means that the application logger has
403
// been created first and added with LogManager.addLogger, and the
404
// system logger was created after - and no handler has been added
405
// to it by LogManager.addLogger. Therefore, system.handlers
406
// should be empty.
407
//
408
// A non empty cfg.handlers list indicates a race condition
409
// where two threads might attempt to merge the configuration
410
// or add handlers concurrently. Though of no consequence for
411
// the other data (level etc...) this would be an issue if we
412
// added the same handlers twice.
413
//
414
for (Handler h : handlers) {
415
if (!system.handlers.contains(h)) {
416
systemPeer.addHandler(h);
417
}
418
}
419
system.handlers.retainAll(handlers);
420
system.handlers.addAllAbsent(handlers);
421
}
422
423
// sanity: update effective level after merging
424
synchronized(treeLock) {
425
systemPeer.updateEffectiveLevel();
426
}
427
428
return system;
429
}
430
431
}
432
433
// The logger configuration data. Ideally, this should be final
434
// for system loggers, and replace-once for application loggers.
435
// When an application requests a logger by name, we do not know a-priori
436
// whether that corresponds to a system logger name or not.
437
// So if no system logger by that name already exists, we simply return an
438
// application logger.
439
// If a system class later requests a system logger of the same name, then
440
// the application logger and system logger configurations will be merged
441
// in a single instance of ConfigurationData that both loggers will share.
442
private volatile ConfigurationData config;
443
444
private volatile LogManager manager;
445
private String name;
446
private volatile LoggerBundle loggerBundle = NO_RESOURCE_BUNDLE;
447
private boolean anonymous;
448
449
// Cache to speed up behavior of findResourceBundle:
450
private WeakReference<ResourceBundle> catalogRef; // Cached resource bundle
451
private String catalogName; // name associated with catalog
452
private Locale catalogLocale; // locale associated with catalog
453
454
// The fields relating to parent-child relationships and levels
455
// are managed under a separate lock, the treeLock.
456
private static final Object treeLock = new Object();
457
// We keep weak references from parents to children, but strong
458
// references from children to parents.
459
private volatile Logger parent; // our nearest parent.
460
private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
461
private WeakReference<Module> callerModuleRef;
462
private final boolean isSystemLogger;
463
464
/**
465
* GLOBAL_LOGGER_NAME is a name for the global logger.
466
*
467
* @since 1.6
468
*/
469
public static final String GLOBAL_LOGGER_NAME = "global";
470
471
/**
472
* Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
473
*
474
* @return global logger object
475
* @since 1.7
476
*/
477
public static final Logger getGlobal() {
478
// In order to break a cyclic dependence between the LogManager
479
// and Logger static initializers causing deadlocks, the global
480
// logger is created with a special constructor that does not
481
// initialize its log manager.
482
//
483
// If an application calls Logger.getGlobal() before any logger
484
// has been initialized, it is therefore possible that the
485
// LogManager class has not been initialized yet, and therefore
486
// Logger.global.manager will be null.
487
//
488
// In order to finish the initialization of the global logger, we
489
// will therefore call LogManager.getLogManager() here.
490
//
491
// To prevent race conditions we also need to call
492
// LogManager.getLogManager() unconditionally here.
493
// Indeed we cannot rely on the observed value of global.manager,
494
// because global.manager will become not null somewhere during
495
// the initialization of LogManager.
496
// If two threads are calling getGlobal() concurrently, one thread
497
// will see global.manager null and call LogManager.getLogManager(),
498
// but the other thread could come in at a time when global.manager
499
// is already set although ensureLogManagerInitialized is not finished
500
// yet...
501
// Calling LogManager.getLogManager() unconditionally will fix that.
502
503
LogManager.getLogManager();
504
505
// Now the global LogManager should be initialized,
506
// and the global logger should have been added to
507
// it, unless we were called within the constructor of a LogManager
508
// subclass installed as LogManager, in which case global.manager
509
// would still be null, and global will be lazily initialized later on.
510
511
return global;
512
}
513
514
/**
515
* The "global" Logger object is provided as a convenience to developers
516
* who are making casual use of the Logging package. Developers
517
* who are making serious use of the logging package (for example
518
* in products) should create and use their own Logger objects,
519
* with appropriate names, so that logging can be controlled on a
520
* suitable per-Logger granularity. Developers also need to keep a
521
* strong reference to their Logger objects to prevent them from
522
* being garbage collected.
523
*
524
* @deprecated Initialization of this field is prone to deadlocks.
525
* The field must be initialized by the Logger class initialization
526
* which may cause deadlocks with the LogManager class initialization.
527
* In such cases two class initialization wait for each other to complete.
528
* The preferred way to get the global logger object is via the call
529
* {@code Logger.getGlobal()}.
530
* For compatibility with old JDK versions where the
531
* {@code Logger.getGlobal()} is not available use the call
532
* {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)}
533
* or {@code Logger.getLogger("global")}.
534
*/
535
@Deprecated
536
public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
537
538
/**
539
* Protected method to construct a logger for a named subsystem.
540
* <p>
541
* The logger will be initially configured with a null Level
542
* and with useParentHandlers set to true.
543
*
544
* @param name A name for the logger. This should
545
* be a dot-separated name and should normally
546
* be based on the package name or class name
547
* of the subsystem, such as java.net
548
* or javax.swing. It may be null for anonymous Loggers.
549
* @param resourceBundleName name of ResourceBundle to be used for localizing
550
* messages for this logger. May be null if none
551
* of the messages require localization.
552
* @throws MissingResourceException if the resourceBundleName is non-null and
553
* no corresponding resource can be found.
554
*/
555
protected Logger(String name, String resourceBundleName) {
556
this(name, resourceBundleName, null, LogManager.getLogManager(), false);
557
}
558
559
Logger(String name, String resourceBundleName, Module caller,
560
LogManager manager, boolean isSystemLogger) {
561
this.manager = manager;
562
this.isSystemLogger = isSystemLogger;
563
this.config = new ConfigurationData();
564
this.name = name;
565
setupResourceInfo(resourceBundleName, caller);
566
}
567
568
// Called by LogManager when a system logger is created
569
// after a user logger of the same name.
570
// Ensure that both loggers will share the same
571
// configuration.
572
final void mergeWithSystemLogger(Logger system) {
573
// sanity checks
574
if (!system.isSystemLogger
575
|| anonymous
576
|| name == null
577
|| !name.equals(system.name)) {
578
// should never come here
579
throw new InternalError("invalid logger merge");
580
}
581
checkPermission();
582
final ConfigurationData cfg = config;
583
if (cfg != system.config) {
584
config = cfg.merge(system);
585
}
586
}
587
588
private void setCallerModuleRef(Module callerModule) {
589
if (callerModule != null) {
590
this.callerModuleRef = new WeakReference<>(callerModule);
591
}
592
}
593
594
private Module getCallerModule() {
595
return (callerModuleRef != null)
596
? callerModuleRef.get()
597
: null;
598
}
599
600
// This constructor is used only to create the global Logger.
601
// It is needed to break a cyclic dependence between the LogManager
602
// and Logger static initializers causing deadlocks.
603
private Logger(String name) {
604
// The manager field is not initialized here.
605
this.name = name;
606
this.isSystemLogger = true;
607
config = new ConfigurationData();
608
}
609
610
// It is called from LoggerContext.addLocalLogger() when the logger
611
// is actually added to a LogManager.
612
void setLogManager(LogManager manager) {
613
this.manager = manager;
614
}
615
616
private void checkPermission() throws SecurityException {
617
if (!anonymous) {
618
if (manager == null) {
619
// Complete initialization of the global Logger.
620
manager = LogManager.getLogManager();
621
}
622
manager.checkPermission();
623
}
624
}
625
626
// Until all JDK code converted to call sun.util.logging.PlatformLogger
627
// (see 7054233), we need to determine if Logger.getLogger is to add
628
// a system logger or user logger.
629
//
630
// As an interim solution, if the immediate caller whose caller loader is
631
// null, we assume it's a system logger and add it to the system context.
632
// These system loggers only set the resource bundle to the given
633
// resource bundle name (rather than the default system resource bundle).
634
private static class SystemLoggerHelper {
635
static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck");
636
private static boolean getBooleanProperty(final String key) {
637
@SuppressWarnings("removal")
638
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
639
@Override
640
public String run() {
641
return System.getProperty(key);
642
}
643
});
644
return Boolean.parseBoolean(s);
645
}
646
}
647
648
private static Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
649
LogManager manager = LogManager.getLogManager();
650
if (!SystemLoggerHelper.disableCallerCheck) {
651
if (isSystem(caller.getModule())) {
652
return manager.demandSystemLogger(name, resourceBundleName, caller);
653
}
654
}
655
return manager.demandLogger(name, resourceBundleName, caller);
656
// ends up calling new Logger(name, resourceBundleName, caller)
657
// iff the logger doesn't exist already
658
}
659
660
/**
661
* Find or create a logger for a named subsystem. If a logger has
662
* already been created with the given name it is returned. Otherwise
663
* a new logger is created.
664
* <p>
665
* If a new logger is created its log level will be configured
666
* based on the LogManager configuration and it will be configured
667
* to also send logging output to its parent's Handlers. It will
668
* be registered in the LogManager global namespace.
669
* <p>
670
* Note: The LogManager may only retain a weak reference to the newly
671
* created Logger. It is important to understand that a previously
672
* created Logger with the given name may be garbage collected at any
673
* time if there is no strong reference to the Logger. In particular,
674
* this means that two back-to-back calls like
675
* {@code getLogger("MyLogger").log(...)} may use different Logger
676
* objects named "MyLogger" if there is no strong reference to the
677
* Logger named "MyLogger" elsewhere in the program.
678
*
679
* @param name A name for the logger. This should
680
* be a dot-separated name and should normally
681
* be based on the package name or class name
682
* of the subsystem, such as java.net
683
* or javax.swing
684
* @return a suitable Logger
685
* @throws NullPointerException if the name is null.
686
*/
687
688
// Synchronization is not required here. All synchronization for
689
// adding a new Logger object is handled by LogManager.addLogger().
690
@CallerSensitive
691
public static Logger getLogger(String name) {
692
// This method is intentionally not a wrapper around a call
693
// to getLogger(name, resourceBundleName). If it were then
694
// this sequence:
695
//
696
// getLogger("Foo", "resourceBundleForFoo");
697
// getLogger("Foo");
698
//
699
// would throw an IllegalArgumentException in the second call
700
// because the wrapper would result in an attempt to replace
701
// the existing "resourceBundleForFoo" with null.
702
return Logger.getLogger(name, Reflection.getCallerClass());
703
}
704
705
/**
706
* Find or create a logger for a named subsystem on behalf
707
* of the given caller.
708
*
709
* This method is called by {@link #getLogger(java.lang.String)} after
710
* it has obtained a reference to its caller's class.
711
*
712
* @param name A name for the logger.
713
* @param callerClass The class that called {@link
714
* #getLogger(java.lang.String)}.
715
* @return a suitable Logger for {@code callerClass}.
716
*/
717
private static Logger getLogger(String name, Class<?> callerClass) {
718
return demandLogger(name, null, callerClass);
719
}
720
721
/**
722
* Find or create a logger for a named subsystem. If a logger has
723
* already been created with the given name it is returned. Otherwise
724
* a new logger is created.
725
*
726
* <p>
727
* If a new logger is created its log level will be configured
728
* based on the LogManager and it will be configured to also send logging
729
* output to its parent's Handlers. It will be registered in
730
* the LogManager global namespace.
731
* <p>
732
* Note: The LogManager may only retain a weak reference to the newly
733
* created Logger. It is important to understand that a previously
734
* created Logger with the given name may be garbage collected at any
735
* time if there is no strong reference to the Logger. In particular,
736
* this means that two back-to-back calls like
737
* {@code getLogger("MyLogger", ...).log(...)} may use different Logger
738
* objects named "MyLogger" if there is no strong reference to the
739
* Logger named "MyLogger" elsewhere in the program.
740
* <p>
741
* If the named Logger already exists and does not yet have a
742
* localization resource bundle then the given resource bundle
743
* name is used. If the named Logger already exists and has
744
* a different resource bundle name then an IllegalArgumentException
745
* is thrown.
746
*
747
* @param name A name for the logger. This should
748
* be a dot-separated name and should normally
749
* be based on the package name or class name
750
* of the subsystem, such as java.net
751
* or javax.swing
752
* @param resourceBundleName name of ResourceBundle to be used for localizing
753
* messages for this logger. May be {@code null}
754
* if none of the messages require localization.
755
* @return a suitable Logger
756
* @throws MissingResourceException if the resourceBundleName is non-null and
757
* no corresponding resource can be found.
758
* @throws IllegalArgumentException if the Logger already exists and uses
759
* a different resource bundle name; or if
760
* {@code resourceBundleName} is {@code null} but the named
761
* logger has a resource bundle set.
762
* @throws NullPointerException if the name is null.
763
*/
764
765
// Synchronization is not required here. All synchronization for
766
// adding a new Logger object is handled by LogManager.addLogger().
767
@CallerSensitive
768
public static Logger getLogger(String name, String resourceBundleName) {
769
return Logger.getLogger(name, resourceBundleName, Reflection.getCallerClass());
770
}
771
772
/**
773
* Find or create a logger for a named subsystem on behalf
774
* of the given caller.
775
*
776
* This method is called by {@link
777
* #getLogger(java.lang.String, java.lang.String)} after
778
* it has obtained a reference to its caller's class.
779
*
780
* @param name A name for the logger.
781
* @param resourceBundleName name of ResourceBundle to be used for localizing
782
* messages for this logger. May be {@code null}
783
* if none of the messages require localization.
784
* @param callerClass The class that called {@link
785
* #getLogger(java.lang.String, java.lang.String)}.
786
* This class will also be used for locating the
787
* resource bundle if {@code resourceBundleName} is
788
* not {@code null}.
789
* @return a suitable Logger for {@code callerClass}.
790
*/
791
private static Logger getLogger(String name, String resourceBundleName,
792
Class<?> callerClass) {
793
Logger result = demandLogger(name, resourceBundleName, callerClass);
794
795
// MissingResourceException or IllegalArgumentException can be
796
// thrown by setupResourceInfo().
797
// We have to set the callers ClassLoader here in case demandLogger
798
// above found a previously created Logger. This can happen, for
799
// example, if Logger.getLogger(name) is called and subsequently
800
// Logger.getLogger(name, resourceBundleName) is called. In this case
801
// we won't necessarily have the correct classloader saved away, so
802
// we need to set it here, too.
803
804
result.setupResourceInfo(resourceBundleName, callerClass);
805
return result;
806
}
807
808
// package-private
809
// Add a platform logger to the system context.
810
// i.e. caller of sun.util.logging.PlatformLogger.getLogger
811
static Logger getPlatformLogger(String name) {
812
LogManager manager = LogManager.getLogManager();
813
814
// all loggers in the system context will default to
815
// the system logger's resource bundle - therefore the caller won't
816
// be needed and can be null.
817
Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null);
818
return result;
819
}
820
821
/**
822
* Create an anonymous Logger. The newly created Logger is not
823
* registered in the LogManager namespace. There will be no
824
* access checks on updates to the logger.
825
* <p>
826
* This factory method is primarily intended for use from applets.
827
* Because the resulting Logger is anonymous it can be kept private
828
* by the creating class. This removes the need for normal security
829
* checks, which in turn allows untrusted applet code to update
830
* the control state of the Logger. For example an applet can do
831
* a setLevel or an addHandler on an anonymous Logger.
832
* <p>
833
* Even although the new logger is anonymous, it is configured
834
* to have the root logger ("") as its parent. This means that
835
* by default it inherits its effective level and handlers
836
* from the root logger. Changing its parent via the
837
* {@link #setParent(java.util.logging.Logger) setParent} method
838
* will still require the security permission specified by that method.
839
*
840
* @return a newly created private Logger
841
*/
842
public static Logger getAnonymousLogger() {
843
return getAnonymousLogger(null);
844
}
845
846
/**
847
* Create an anonymous Logger. The newly created Logger is not
848
* registered in the LogManager namespace. There will be no
849
* access checks on updates to the logger.
850
* <p>
851
* This factory method is primarily intended for use from applets.
852
* Because the resulting Logger is anonymous it can be kept private
853
* by the creating class. This removes the need for normal security
854
* checks, which in turn allows untrusted applet code to update
855
* the control state of the Logger. For example an applet can do
856
* a setLevel or an addHandler on an anonymous Logger.
857
* <p>
858
* Even although the new logger is anonymous, it is configured
859
* to have the root logger ("") as its parent. This means that
860
* by default it inherits its effective level and handlers
861
* from the root logger. Changing its parent via the
862
* {@link #setParent(java.util.logging.Logger) setParent} method
863
* will still require the security permission specified by that method.
864
*
865
* @param resourceBundleName name of ResourceBundle to be used for localizing
866
* messages for this logger.
867
* May be null if none of the messages require localization.
868
* @return a newly created private Logger
869
* @throws MissingResourceException if the resourceBundleName is non-null and
870
* no corresponding resource can be found.
871
*/
872
873
// Synchronization is not required here. All synchronization for
874
// adding a new anonymous Logger object is handled by doSetParent().
875
@CallerSensitive
876
public static Logger getAnonymousLogger(String resourceBundleName) {
877
LogManager manager = LogManager.getLogManager();
878
// cleanup some Loggers that have been GC'ed
879
manager.drainLoggerRefQueueBounded();
880
final Class<?> callerClass = Reflection.getCallerClass();
881
final Module module = callerClass.getModule();
882
Logger result = new Logger(null, resourceBundleName,
883
module, manager, false);
884
result.anonymous = true;
885
Logger root = manager.getLogger("");
886
result.doSetParent(root);
887
return result;
888
}
889
890
/**
891
* Retrieve the localization resource bundle for this
892
* logger.
893
* This method will return a {@code ResourceBundle} that was either
894
* set by the {@link
895
* #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method or
896
* <a href="#ResourceBundleMapping">mapped from the
897
* the resource bundle name</a> set via the {@link
898
* Logger#getLogger(java.lang.String, java.lang.String) getLogger} factory
899
* method for the current default locale.
900
* <br>Note that if the result is {@code null}, then the Logger will use a resource
901
* bundle or resource bundle name inherited from its parent.
902
*
903
* @return localization bundle (may be {@code null})
904
*/
905
public ResourceBundle getResourceBundle() {
906
return findResourceBundle(getResourceBundleName(), true);
907
}
908
909
/**
910
* Retrieve the localization resource bundle name for this
911
* logger.
912
* This is either the name specified through the {@link
913
* #getLogger(java.lang.String, java.lang.String) getLogger} factory method,
914
* or the {@linkplain ResourceBundle#getBaseBundleName() base name} of the
915
* ResourceBundle set through {@link
916
* #setResourceBundle(java.util.ResourceBundle) setResourceBundle} method.
917
* <br>Note that if the result is {@code null}, then the Logger will use a resource
918
* bundle or resource bundle name inherited from its parent.
919
*
920
* @return localization bundle name (may be {@code null})
921
*/
922
public String getResourceBundleName() {
923
return loggerBundle.resourceBundleName;
924
}
925
926
/**
927
* Set a filter to control output on this Logger.
928
* <P>
929
* After passing the initial "level" check, the Logger will
930
* call this Filter to check if a log record should really
931
* be published.
932
*
933
* @param newFilter a filter object (may be null)
934
* @throws SecurityException if a security manager exists,
935
* this logger is not anonymous, and the caller
936
* does not have LoggingPermission("control").
937
*/
938
public void setFilter(Filter newFilter) throws SecurityException {
939
checkPermission();
940
config.setFilter(newFilter);
941
}
942
943
/**
944
* Get the current filter for this Logger.
945
*
946
* @return a filter object (may be null)
947
*/
948
public Filter getFilter() {
949
return config.filter;
950
}
951
952
/**
953
* Log a LogRecord.
954
* <p>
955
* All the other logging methods in this class call through
956
* this method to actually perform any logging. Subclasses can
957
* override this single method to capture all log activity.
958
*
959
* @param record the LogRecord to be published
960
*/
961
public void log(LogRecord record) {
962
if (!isLoggable(record.getLevel())) {
963
return;
964
}
965
Filter theFilter = config.filter;
966
if (theFilter != null && !theFilter.isLoggable(record)) {
967
return;
968
}
969
970
// Post the LogRecord to all our Handlers, and then to
971
// our parents' handlers, all the way up the tree.
972
973
Logger logger = this;
974
while (logger != null) {
975
final Handler[] loggerHandlers = isSystemLogger
976
? logger.accessCheckedHandlers()
977
: logger.getHandlers();
978
979
for (Handler handler : loggerHandlers) {
980
handler.publish(record);
981
}
982
983
final boolean useParentHdls = isSystemLogger
984
? logger.config.useParentHandlers
985
: logger.getUseParentHandlers();
986
987
if (!useParentHdls) {
988
break;
989
}
990
991
logger = isSystemLogger ? logger.parent : logger.getParent();
992
}
993
}
994
995
// private support method for logging.
996
// We fill in the logger name, resource bundle name, and
997
// resource bundle and then call "void log(LogRecord)".
998
private void doLog(LogRecord lr) {
999
lr.setLoggerName(name);
1000
final LoggerBundle lb = getEffectiveLoggerBundle();
1001
final ResourceBundle bundle = lb.userBundle;
1002
final String ebname = lb.resourceBundleName;
1003
if (ebname != null && bundle != null) {
1004
lr.setResourceBundleName(ebname);
1005
lr.setResourceBundle(bundle);
1006
}
1007
log(lr);
1008
}
1009
1010
1011
//================================================================
1012
// Start of convenience methods WITHOUT className and methodName
1013
//================================================================
1014
1015
/**
1016
* Log a message, with no arguments.
1017
* <p>
1018
* If the logger is currently enabled for the given message
1019
* level then the given message is forwarded to all the
1020
* registered output Handler objects.
1021
*
1022
* @param level One of the message level identifiers, e.g., SEVERE
1023
* @param msg The string message (or a key in the message catalog)
1024
*/
1025
public void log(Level level, String msg) {
1026
if (!isLoggable(level)) {
1027
return;
1028
}
1029
LogRecord lr = new LogRecord(level, msg);
1030
doLog(lr);
1031
}
1032
1033
/**
1034
* Log a message, which is only to be constructed if the logging level
1035
* is such that the message will actually be logged.
1036
* <p>
1037
* If the logger is currently enabled for the given message
1038
* level then the message is constructed by invoking the provided
1039
* supplier function and forwarded to all the registered output
1040
* Handler objects.
1041
*
1042
* @param level One of the message level identifiers, e.g., SEVERE
1043
* @param msgSupplier A function, which when called, produces the
1044
* desired log message
1045
* @since 1.8
1046
*/
1047
public void log(Level level, Supplier<String> msgSupplier) {
1048
if (!isLoggable(level)) {
1049
return;
1050
}
1051
LogRecord lr = new LogRecord(level, msgSupplier.get());
1052
doLog(lr);
1053
}
1054
1055
/**
1056
* Log a message, with one object parameter.
1057
* <p>
1058
* If the logger is currently enabled for the given message
1059
* level then a corresponding LogRecord is created and forwarded
1060
* to all the registered output Handler objects.
1061
*
1062
* @param level One of the message level identifiers, e.g., SEVERE
1063
* @param msg The string message (or a key in the message catalog)
1064
* @param param1 parameter to the message
1065
*/
1066
public void log(Level level, String msg, Object param1) {
1067
if (!isLoggable(level)) {
1068
return;
1069
}
1070
LogRecord lr = new LogRecord(level, msg);
1071
Object params[] = { param1 };
1072
lr.setParameters(params);
1073
doLog(lr);
1074
}
1075
1076
/**
1077
* Log a message, with an array of object arguments.
1078
* <p>
1079
* If the logger is currently enabled for the given message
1080
* level then a corresponding LogRecord is created and forwarded
1081
* to all the registered output Handler objects.
1082
*
1083
* @param level One of the message level identifiers, e.g., SEVERE
1084
* @param msg The string message (or a key in the message catalog)
1085
* @param params array of parameters to the message
1086
*/
1087
public void log(Level level, String msg, Object params[]) {
1088
if (!isLoggable(level)) {
1089
return;
1090
}
1091
LogRecord lr = new LogRecord(level, msg);
1092
lr.setParameters(params);
1093
doLog(lr);
1094
}
1095
1096
/**
1097
* Log a message, with associated Throwable information.
1098
* <p>
1099
* If the logger is currently enabled for the given message
1100
* level then the given arguments are stored in a LogRecord
1101
* which is forwarded to all registered output handlers.
1102
* <p>
1103
* Note that the thrown argument is stored in the LogRecord thrown
1104
* property, rather than the LogRecord parameters property. Thus it is
1105
* processed specially by output Formatters and is not treated
1106
* as a formatting parameter to the LogRecord message property.
1107
*
1108
* @param level One of the message level identifiers, e.g., SEVERE
1109
* @param msg The string message (or a key in the message catalog)
1110
* @param thrown Throwable associated with log message.
1111
*/
1112
public void log(Level level, String msg, Throwable thrown) {
1113
if (!isLoggable(level)) {
1114
return;
1115
}
1116
LogRecord lr = new LogRecord(level, msg);
1117
lr.setThrown(thrown);
1118
doLog(lr);
1119
}
1120
1121
/**
1122
* Log a lazily constructed message, with associated Throwable information.
1123
* <p>
1124
* If the logger is currently enabled for the given message level then the
1125
* message is constructed by invoking the provided supplier function. The
1126
* message and the given {@link Throwable} are then stored in a {@link
1127
* LogRecord} which is forwarded to all registered output handlers.
1128
* <p>
1129
* Note that the thrown argument is stored in the LogRecord thrown
1130
* property, rather than the LogRecord parameters property. Thus it is
1131
* processed specially by output Formatters and is not treated
1132
* as a formatting parameter to the LogRecord message property.
1133
*
1134
* @param level One of the message level identifiers, e.g., SEVERE
1135
* @param thrown Throwable associated with log message.
1136
* @param msgSupplier A function, which when called, produces the
1137
* desired log message
1138
* @since 1.8
1139
*/
1140
public void log(Level level, Throwable thrown, Supplier<String> msgSupplier) {
1141
if (!isLoggable(level)) {
1142
return;
1143
}
1144
LogRecord lr = new LogRecord(level, msgSupplier.get());
1145
lr.setThrown(thrown);
1146
doLog(lr);
1147
}
1148
1149
//================================================================
1150
// Start of convenience methods WITH className and methodName
1151
//================================================================
1152
1153
/**
1154
* Log a message, specifying source class and method,
1155
* with no arguments.
1156
* <p>
1157
* If the logger is currently enabled for the given message
1158
* level then the given message is forwarded to all the
1159
* registered output Handler objects.
1160
*
1161
* @param level One of the message level identifiers, e.g., SEVERE
1162
* @param sourceClass name of class that issued the logging request
1163
* @param sourceMethod name of method that issued the logging request
1164
* @param msg The string message (or a key in the message catalog)
1165
*/
1166
public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
1167
if (!isLoggable(level)) {
1168
return;
1169
}
1170
LogRecord lr = new LogRecord(level, msg);
1171
lr.setSourceClassName(sourceClass);
1172
lr.setSourceMethodName(sourceMethod);
1173
doLog(lr);
1174
}
1175
1176
/**
1177
* Log a lazily constructed message, specifying source class and method,
1178
* with no arguments.
1179
* <p>
1180
* If the logger is currently enabled for the given message
1181
* level then the message is constructed by invoking the provided
1182
* supplier function and forwarded to all the registered output
1183
* Handler objects.
1184
*
1185
* @param level One of the message level identifiers, e.g., SEVERE
1186
* @param sourceClass name of class that issued the logging request
1187
* @param sourceMethod name of method that issued the logging request
1188
* @param msgSupplier A function, which when called, produces the
1189
* desired log message
1190
* @since 1.8
1191
*/
1192
public void logp(Level level, String sourceClass, String sourceMethod,
1193
Supplier<String> msgSupplier) {
1194
if (!isLoggable(level)) {
1195
return;
1196
}
1197
LogRecord lr = new LogRecord(level, msgSupplier.get());
1198
lr.setSourceClassName(sourceClass);
1199
lr.setSourceMethodName(sourceMethod);
1200
doLog(lr);
1201
}
1202
1203
/**
1204
* Log a message, specifying source class and method,
1205
* with a single object parameter to the log message.
1206
* <p>
1207
* If the logger is currently enabled for the given message
1208
* level then a corresponding LogRecord is created and forwarded
1209
* to all the registered output Handler objects.
1210
*
1211
* @param level One of the message level identifiers, e.g., SEVERE
1212
* @param sourceClass name of class that issued the logging request
1213
* @param sourceMethod name of method that issued the logging request
1214
* @param msg The string message (or a key in the message catalog)
1215
* @param param1 Parameter to the log message.
1216
*/
1217
public void logp(Level level, String sourceClass, String sourceMethod,
1218
String msg, Object param1) {
1219
if (!isLoggable(level)) {
1220
return;
1221
}
1222
LogRecord lr = new LogRecord(level, msg);
1223
lr.setSourceClassName(sourceClass);
1224
lr.setSourceMethodName(sourceMethod);
1225
Object params[] = { param1 };
1226
lr.setParameters(params);
1227
doLog(lr);
1228
}
1229
1230
/**
1231
* Log a message, specifying source class and method,
1232
* with an array of object arguments.
1233
* <p>
1234
* If the logger is currently enabled for the given message
1235
* level then a corresponding LogRecord is created and forwarded
1236
* to all the registered output Handler objects.
1237
*
1238
* @param level One of the message level identifiers, e.g., SEVERE
1239
* @param sourceClass name of class that issued the logging request
1240
* @param sourceMethod name of method that issued the logging request
1241
* @param msg The string message (or a key in the message catalog)
1242
* @param params Array of parameters to the message
1243
*/
1244
public void logp(Level level, String sourceClass, String sourceMethod,
1245
String msg, Object params[]) {
1246
if (!isLoggable(level)) {
1247
return;
1248
}
1249
LogRecord lr = new LogRecord(level, msg);
1250
lr.setSourceClassName(sourceClass);
1251
lr.setSourceMethodName(sourceMethod);
1252
lr.setParameters(params);
1253
doLog(lr);
1254
}
1255
1256
/**
1257
* Log a message, specifying source class and method,
1258
* with associated Throwable information.
1259
* <p>
1260
* If the logger is currently enabled for the given message
1261
* level then the given arguments are stored in a LogRecord
1262
* which is forwarded to all registered output handlers.
1263
* <p>
1264
* Note that the thrown argument is stored in the LogRecord thrown
1265
* property, rather than the LogRecord parameters property. Thus it is
1266
* processed specially by output Formatters and is not treated
1267
* as a formatting parameter to the LogRecord message property.
1268
*
1269
* @param level One of the message level identifiers, e.g., SEVERE
1270
* @param sourceClass name of class that issued the logging request
1271
* @param sourceMethod name of method that issued the logging request
1272
* @param msg The string message (or a key in the message catalog)
1273
* @param thrown Throwable associated with log message.
1274
*/
1275
public void logp(Level level, String sourceClass, String sourceMethod,
1276
String msg, Throwable thrown) {
1277
if (!isLoggable(level)) {
1278
return;
1279
}
1280
LogRecord lr = new LogRecord(level, msg);
1281
lr.setSourceClassName(sourceClass);
1282
lr.setSourceMethodName(sourceMethod);
1283
lr.setThrown(thrown);
1284
doLog(lr);
1285
}
1286
1287
/**
1288
* Log a lazily constructed message, specifying source class and method,
1289
* with associated Throwable information.
1290
* <p>
1291
* If the logger is currently enabled for the given message level then the
1292
* message is constructed by invoking the provided supplier function. The
1293
* message and the given {@link Throwable} are then stored in a {@link
1294
* LogRecord} which is forwarded to all registered output handlers.
1295
* <p>
1296
* Note that the thrown argument is stored in the LogRecord thrown
1297
* property, rather than the LogRecord parameters property. Thus it is
1298
* processed specially by output Formatters and is not treated
1299
* as a formatting parameter to the LogRecord message property.
1300
*
1301
* @param level One of the message level identifiers, e.g., SEVERE
1302
* @param sourceClass name of class that issued the logging request
1303
* @param sourceMethod name of method that issued the logging request
1304
* @param thrown Throwable associated with log message.
1305
* @param msgSupplier A function, which when called, produces the
1306
* desired log message
1307
* @since 1.8
1308
*/
1309
public void logp(Level level, String sourceClass, String sourceMethod,
1310
Throwable thrown, Supplier<String> msgSupplier) {
1311
if (!isLoggable(level)) {
1312
return;
1313
}
1314
LogRecord lr = new LogRecord(level, msgSupplier.get());
1315
lr.setSourceClassName(sourceClass);
1316
lr.setSourceMethodName(sourceMethod);
1317
lr.setThrown(thrown);
1318
doLog(lr);
1319
}
1320
1321
1322
//=========================================================================
1323
// Start of convenience methods WITH className, methodName and bundle name.
1324
//=========================================================================
1325
1326
// Private support method for logging for "logrb" methods.
1327
// We fill in the logger name, resource bundle name, and
1328
// resource bundle and then call "void log(LogRecord)".
1329
private void doLog(LogRecord lr, String rbname) {
1330
lr.setLoggerName(name);
1331
if (rbname != null) {
1332
lr.setResourceBundleName(rbname);
1333
lr.setResourceBundle(findResourceBundle(rbname, false));
1334
}
1335
log(lr);
1336
}
1337
1338
// Private support method for logging for "logrb" methods.
1339
private void doLog(LogRecord lr, ResourceBundle rb) {
1340
lr.setLoggerName(name);
1341
if (rb != null) {
1342
lr.setResourceBundleName(rb.getBaseBundleName());
1343
lr.setResourceBundle(rb);
1344
}
1345
log(lr);
1346
}
1347
1348
/**
1349
* Log a message, specifying source class, method, and resource bundle name
1350
* with no arguments.
1351
* <p>
1352
* If the logger is currently enabled for the given message
1353
* level then the given message is forwarded to all the
1354
* registered output Handler objects.
1355
* <p>
1356
* The msg string is localized using the named resource bundle. If the
1357
* resource bundle name is null, or an empty String or invalid
1358
* then the msg string is not localized.
1359
*
1360
* @param level One of the message level identifiers, e.g., SEVERE
1361
* @param sourceClass name of class that issued the logging request
1362
* @param sourceMethod name of method that issued the logging request
1363
* @param bundleName name of resource bundle to localize msg,
1364
* can be null
1365
* @param msg The string message (or a key in the message catalog)
1366
* @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
1367
* java.lang.String, java.util.ResourceBundle, java.lang.String,
1368
* java.lang.Object...)} instead.
1369
*/
1370
@Deprecated
1371
public void logrb(Level level, String sourceClass, String sourceMethod,
1372
String bundleName, String msg) {
1373
if (!isLoggable(level)) {
1374
return;
1375
}
1376
LogRecord lr = new LogRecord(level, msg);
1377
lr.setSourceClassName(sourceClass);
1378
lr.setSourceMethodName(sourceMethod);
1379
doLog(lr, bundleName);
1380
}
1381
1382
/**
1383
* Log a message, specifying source class, method, and resource bundle name,
1384
* with a single object parameter to the log message.
1385
* <p>
1386
* If the logger is currently enabled for the given message
1387
* level then a corresponding LogRecord is created and forwarded
1388
* to all the registered output Handler objects.
1389
* <p>
1390
* The msg string is localized using the named resource bundle. If the
1391
* resource bundle name is null, or an empty String or invalid
1392
* then the msg string is not localized.
1393
*
1394
* @param level One of the message level identifiers, e.g., SEVERE
1395
* @param sourceClass name of class that issued the logging request
1396
* @param sourceMethod name of method that issued the logging request
1397
* @param bundleName name of resource bundle to localize msg,
1398
* can be null
1399
* @param msg The string message (or a key in the message catalog)
1400
* @param param1 Parameter to the log message.
1401
* @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
1402
* java.lang.String, java.util.ResourceBundle, java.lang.String,
1403
* java.lang.Object...)} instead
1404
*/
1405
@Deprecated
1406
public void logrb(Level level, String sourceClass, String sourceMethod,
1407
String bundleName, String msg, Object param1) {
1408
if (!isLoggable(level)) {
1409
return;
1410
}
1411
LogRecord lr = new LogRecord(level, msg);
1412
lr.setSourceClassName(sourceClass);
1413
lr.setSourceMethodName(sourceMethod);
1414
Object params[] = { param1 };
1415
lr.setParameters(params);
1416
doLog(lr, bundleName);
1417
}
1418
1419
/**
1420
* Log a message, specifying source class, method, and resource bundle name,
1421
* with an array of object arguments.
1422
* <p>
1423
* If the logger is currently enabled for the given message
1424
* level then a corresponding LogRecord is created and forwarded
1425
* to all the registered output Handler objects.
1426
* <p>
1427
* The msg string is localized using the named resource bundle. If the
1428
* resource bundle name is null, or an empty String or invalid
1429
* then the msg string is not localized.
1430
*
1431
* @param level One of the message level identifiers, e.g., SEVERE
1432
* @param sourceClass name of class that issued the logging request
1433
* @param sourceMethod name of method that issued the logging request
1434
* @param bundleName name of resource bundle to localize msg,
1435
* can be null.
1436
* @param msg The string message (or a key in the message catalog)
1437
* @param params Array of parameters to the message
1438
* @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
1439
* java.lang.String, java.util.ResourceBundle, java.lang.String,
1440
* java.lang.Object...)} instead.
1441
*/
1442
@Deprecated
1443
public void logrb(Level level, String sourceClass, String sourceMethod,
1444
String bundleName, String msg, Object params[]) {
1445
if (!isLoggable(level)) {
1446
return;
1447
}
1448
LogRecord lr = new LogRecord(level, msg);
1449
lr.setSourceClassName(sourceClass);
1450
lr.setSourceMethodName(sourceMethod);
1451
lr.setParameters(params);
1452
doLog(lr, bundleName);
1453
}
1454
1455
/**
1456
* Log a message, specifying source class, method, and resource bundle,
1457
* with an optional list of message parameters.
1458
* <p>
1459
* If the logger is currently enabled for the given message
1460
* {@code level} then a corresponding {@code LogRecord} is created and
1461
* forwarded to all the registered output {@code Handler} objects.
1462
* <p>
1463
* The {@code msg} string is localized using the given resource bundle.
1464
* If the resource bundle is {@code null}, then the {@code msg} string is not
1465
* localized.
1466
*
1467
* @param level One of the message level identifiers, e.g., {@code SEVERE}
1468
* @param sourceClass Name of the class that issued the logging request
1469
* @param sourceMethod Name of the method that issued the logging request
1470
* @param bundle Resource bundle to localize {@code msg},
1471
* can be {@code null}.
1472
* @param msg The string message (or a key in the message catalog)
1473
* @param params Parameters to the message (optional, may be none).
1474
* @since 1.8
1475
*/
1476
public void logrb(Level level, String sourceClass, String sourceMethod,
1477
ResourceBundle bundle, String msg, Object... params) {
1478
if (!isLoggable(level)) {
1479
return;
1480
}
1481
LogRecord lr = new LogRecord(level, msg);
1482
lr.setSourceClassName(sourceClass);
1483
lr.setSourceMethodName(sourceMethod);
1484
if (params != null && params.length != 0) {
1485
lr.setParameters(params);
1486
}
1487
doLog(lr, bundle);
1488
}
1489
1490
/**
1491
* Log a message, specifying source class, method, and resource bundle,
1492
* with an optional list of message parameters.
1493
* <p>
1494
* If the logger is currently enabled for the given message
1495
* {@code level} then a corresponding {@code LogRecord} is created
1496
* and forwarded to all the registered output {@code Handler} objects.
1497
* <p>
1498
* The {@code msg} string is localized using the given resource bundle.
1499
* If the resource bundle is {@code null}, then the {@code msg} string is not
1500
* localized.
1501
*
1502
* @param level One of the message level identifiers, e.g., {@code SEVERE}
1503
* @param bundle Resource bundle to localize {@code msg};
1504
* can be {@code null}.
1505
* @param msg The string message (or a key in the message catalog)
1506
* @param params Parameters to the message (optional, may be none).
1507
* @since 9
1508
*/
1509
public void logrb(Level level, ResourceBundle bundle, String msg, Object... params) {
1510
if (!isLoggable(level)) {
1511
return;
1512
}
1513
LogRecord lr = new LogRecord(level, msg);
1514
if (params != null && params.length != 0) {
1515
lr.setParameters(params);
1516
}
1517
doLog(lr, bundle);
1518
}
1519
1520
/**
1521
* Log a message, specifying source class, method, and resource bundle name,
1522
* with associated Throwable information.
1523
* <p>
1524
* If the logger is currently enabled for the given message
1525
* level then the given arguments are stored in a LogRecord
1526
* which is forwarded to all registered output handlers.
1527
* <p>
1528
* The msg string is localized using the named resource bundle. If the
1529
* resource bundle name is null, or an empty String or invalid
1530
* then the msg string is not localized.
1531
* <p>
1532
* Note that the thrown argument is stored in the LogRecord thrown
1533
* property, rather than the LogRecord parameters property. Thus it is
1534
* processed specially by output Formatters and is not treated
1535
* as a formatting parameter to the LogRecord message property.
1536
*
1537
* @param level One of the message level identifiers, e.g., SEVERE
1538
* @param sourceClass name of class that issued the logging request
1539
* @param sourceMethod name of method that issued the logging request
1540
* @param bundleName name of resource bundle to localize msg,
1541
* can be null
1542
* @param msg The string message (or a key in the message catalog)
1543
* @param thrown Throwable associated with log message.
1544
* @deprecated Use {@link #logrb(java.util.logging.Level, java.lang.String,
1545
* java.lang.String, java.util.ResourceBundle, java.lang.String,
1546
* java.lang.Throwable)} instead.
1547
*/
1548
@Deprecated
1549
public void logrb(Level level, String sourceClass, String sourceMethod,
1550
String bundleName, String msg, Throwable thrown) {
1551
if (!isLoggable(level)) {
1552
return;
1553
}
1554
LogRecord lr = new LogRecord(level, msg);
1555
lr.setSourceClassName(sourceClass);
1556
lr.setSourceMethodName(sourceMethod);
1557
lr.setThrown(thrown);
1558
doLog(lr, bundleName);
1559
}
1560
1561
/**
1562
* Log a message, specifying source class, method, and resource bundle,
1563
* with associated Throwable information.
1564
* <p>
1565
* If the logger is currently enabled for the given message
1566
* {@code level} then the given arguments are stored in a {@code LogRecord}
1567
* which is forwarded to all registered output handlers.
1568
* <p>
1569
* The {@code msg} string is localized using the given resource bundle.
1570
* If the resource bundle is {@code null}, then the {@code msg} string is not
1571
* localized.
1572
* <p>
1573
* Note that the {@code thrown} argument is stored in the {@code LogRecord}
1574
* {@code thrown} property, rather than the {@code LogRecord}
1575
* {@code parameters} property. Thus it is
1576
* processed specially by output {@code Formatter} objects and is not treated
1577
* as a formatting parameter to the {@code LogRecord} {@code message} property.
1578
*
1579
* @param level One of the message level identifiers, e.g., {@code SEVERE}
1580
* @param sourceClass Name of the class that issued the logging request
1581
* @param sourceMethod Name of the method that issued the logging request
1582
* @param bundle Resource bundle to localize {@code msg},
1583
* can be {@code null}
1584
* @param msg The string message (or a key in the message catalog)
1585
* @param thrown Throwable associated with the log message.
1586
* @since 1.8
1587
*/
1588
public void logrb(Level level, String sourceClass, String sourceMethod,
1589
ResourceBundle bundle, String msg, Throwable thrown) {
1590
if (!isLoggable(level)) {
1591
return;
1592
}
1593
LogRecord lr = new LogRecord(level, msg);
1594
lr.setSourceClassName(sourceClass);
1595
lr.setSourceMethodName(sourceMethod);
1596
lr.setThrown(thrown);
1597
doLog(lr, bundle);
1598
}
1599
1600
/**
1601
* Log a message, specifying source class, method, and resource bundle,
1602
* with associated Throwable information.
1603
* <p>
1604
* If the logger is currently enabled for the given message
1605
* {@code level} then the given arguments are stored in a {@code LogRecord}
1606
* which is forwarded to all registered output handlers.
1607
* <p>
1608
* The {@code msg} string is localized using the given resource bundle.
1609
* If the resource bundle is {@code null}, then the {@code msg} string is not
1610
* localized.
1611
* <p>
1612
* Note that the {@code thrown} argument is stored in the {@code LogRecord}
1613
* {@code thrown} property, rather than the {@code LogRecord}
1614
* {@code parameters} property. Thus it is
1615
* processed specially by output {@code Formatter} objects and is not treated
1616
* as a formatting parameter to the {@code LogRecord} {@code message}
1617
* property.
1618
*
1619
* @param level One of the message level identifiers, e.g., {@code SEVERE}
1620
* @param bundle Resource bundle to localize {@code msg};
1621
* can be {@code null}.
1622
* @param msg The string message (or a key in the message catalog)
1623
* @param thrown Throwable associated with the log message.
1624
* @since 9
1625
*/
1626
public void logrb(Level level, ResourceBundle bundle, String msg,
1627
Throwable thrown) {
1628
if (!isLoggable(level)) {
1629
return;
1630
}
1631
LogRecord lr = new LogRecord(level, msg);
1632
lr.setThrown(thrown);
1633
doLog(lr, bundle);
1634
}
1635
1636
//======================================================================
1637
// Start of convenience methods for logging method entries and returns.
1638
//======================================================================
1639
1640
/**
1641
* Log a method entry.
1642
* <p>
1643
* This is a convenience method that can be used to log entry
1644
* to a method. A LogRecord with message "ENTRY", log level
1645
* FINER, and the given sourceMethod and sourceClass is logged.
1646
*
1647
* @param sourceClass name of class that issued the logging request
1648
* @param sourceMethod name of method that is being entered
1649
*/
1650
public void entering(String sourceClass, String sourceMethod) {
1651
logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
1652
}
1653
1654
/**
1655
* Log a method entry, with one parameter.
1656
* <p>
1657
* This is a convenience method that can be used to log entry
1658
* to a method. A LogRecord with message "ENTRY {0}", log level
1659
* FINER, and the given sourceMethod, sourceClass, and parameter
1660
* is logged.
1661
*
1662
* @param sourceClass name of class that issued the logging request
1663
* @param sourceMethod name of method that is being entered
1664
* @param param1 parameter to the method being entered
1665
*/
1666
public void entering(String sourceClass, String sourceMethod, Object param1) {
1667
logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param1);
1668
}
1669
1670
/**
1671
* Log a method entry, with an array of parameters.
1672
* <p>
1673
* This is a convenience method that can be used to log entry
1674
* to a method. A LogRecord with message "ENTRY" (followed by a
1675
* format {N} indicator for each entry in the parameter array),
1676
* log level FINER, and the given sourceMethod, sourceClass, and
1677
* parameters is logged.
1678
*
1679
* @param sourceClass name of class that issued the logging request
1680
* @param sourceMethod name of method that is being entered
1681
* @param params array of parameters to the method being entered
1682
*/
1683
public void entering(String sourceClass, String sourceMethod, Object params[]) {
1684
String msg = "ENTRY";
1685
if (params == null ) {
1686
logp(Level.FINER, sourceClass, sourceMethod, msg);
1687
return;
1688
}
1689
if (!isLoggable(Level.FINER)) return;
1690
if (params.length > 0) {
1691
final StringBuilder b = new StringBuilder(msg);
1692
for (int i = 0; i < params.length; i++) {
1693
b.append(' ').append('{').append(i).append('}');
1694
}
1695
msg = b.toString();
1696
}
1697
logp(Level.FINER, sourceClass, sourceMethod, msg, params);
1698
}
1699
1700
/**
1701
* Log a method return.
1702
* <p>
1703
* This is a convenience method that can be used to log returning
1704
* from a method. A LogRecord with message "RETURN", log level
1705
* FINER, and the given sourceMethod and sourceClass is logged.
1706
*
1707
* @param sourceClass name of class that issued the logging request
1708
* @param sourceMethod name of the method
1709
*/
1710
public void exiting(String sourceClass, String sourceMethod) {
1711
logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
1712
}
1713
1714
1715
/**
1716
* Log a method return, with result object.
1717
* <p>
1718
* This is a convenience method that can be used to log returning
1719
* from a method. A LogRecord with message "RETURN {0}", log level
1720
* FINER, and the gives sourceMethod, sourceClass, and result
1721
* object is logged.
1722
*
1723
* @param sourceClass name of class that issued the logging request
1724
* @param sourceMethod name of the method
1725
* @param result Object that is being returned
1726
*/
1727
public void exiting(String sourceClass, String sourceMethod, Object result) {
1728
logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
1729
}
1730
1731
/**
1732
* Log throwing an exception.
1733
* <p>
1734
* This is a convenience method to log that a method is
1735
* terminating by throwing an exception. The logging is done
1736
* using the FINER level.
1737
* <p>
1738
* If the logger is currently enabled for the given message
1739
* level then the given arguments are stored in a LogRecord
1740
* which is forwarded to all registered output handlers. The
1741
* LogRecord's message is set to "THROW".
1742
* <p>
1743
* Note that the thrown argument is stored in the LogRecord thrown
1744
* property, rather than the LogRecord parameters property. Thus it is
1745
* processed specially by output Formatters and is not treated
1746
* as a formatting parameter to the LogRecord message property.
1747
*
1748
* @param sourceClass name of class that issued the logging request
1749
* @param sourceMethod name of the method.
1750
* @param thrown The Throwable that is being thrown.
1751
*/
1752
public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
1753
if (!isLoggable(Level.FINER)) {
1754
return;
1755
}
1756
LogRecord lr = new LogRecord(Level.FINER, "THROW");
1757
lr.setSourceClassName(sourceClass);
1758
lr.setSourceMethodName(sourceMethod);
1759
lr.setThrown(thrown);
1760
doLog(lr);
1761
}
1762
1763
//=======================================================================
1764
// Start of simple convenience methods using level names as method names
1765
//=======================================================================
1766
1767
/**
1768
* Log a SEVERE message.
1769
* <p>
1770
* If the logger is currently enabled for the SEVERE message
1771
* level then the given message is forwarded to all the
1772
* registered output Handler objects.
1773
*
1774
* @param msg The string message (or a key in the message catalog)
1775
*/
1776
public void severe(String msg) {
1777
log(Level.SEVERE, msg);
1778
}
1779
1780
/**
1781
* Log a WARNING message.
1782
* <p>
1783
* If the logger is currently enabled for the WARNING message
1784
* level then the given message is forwarded to all the
1785
* registered output Handler objects.
1786
*
1787
* @param msg The string message (or a key in the message catalog)
1788
*/
1789
public void warning(String msg) {
1790
log(Level.WARNING, msg);
1791
}
1792
1793
/**
1794
* Log an INFO message.
1795
* <p>
1796
* If the logger is currently enabled for the INFO message
1797
* level then the given message is forwarded to all the
1798
* registered output Handler objects.
1799
*
1800
* @param msg The string message (or a key in the message catalog)
1801
*/
1802
public void info(String msg) {
1803
log(Level.INFO, msg);
1804
}
1805
1806
/**
1807
* Log a CONFIG message.
1808
* <p>
1809
* If the logger is currently enabled for the CONFIG message
1810
* level then the given message is forwarded to all the
1811
* registered output Handler objects.
1812
*
1813
* @param msg The string message (or a key in the message catalog)
1814
*/
1815
public void config(String msg) {
1816
log(Level.CONFIG, msg);
1817
}
1818
1819
/**
1820
* Log a FINE message.
1821
* <p>
1822
* If the logger is currently enabled for the FINE message
1823
* level then the given message is forwarded to all the
1824
* registered output Handler objects.
1825
*
1826
* @param msg The string message (or a key in the message catalog)
1827
*/
1828
public void fine(String msg) {
1829
log(Level.FINE, msg);
1830
}
1831
1832
/**
1833
* Log a FINER message.
1834
* <p>
1835
* If the logger is currently enabled for the FINER message
1836
* level then the given message is forwarded to all the
1837
* registered output Handler objects.
1838
*
1839
* @param msg The string message (or a key in the message catalog)
1840
*/
1841
public void finer(String msg) {
1842
log(Level.FINER, msg);
1843
}
1844
1845
/**
1846
* Log a FINEST message.
1847
* <p>
1848
* If the logger is currently enabled for the FINEST message
1849
* level then the given message is forwarded to all the
1850
* registered output Handler objects.
1851
*
1852
* @param msg The string message (or a key in the message catalog)
1853
*/
1854
public void finest(String msg) {
1855
log(Level.FINEST, msg);
1856
}
1857
1858
//=======================================================================
1859
// Start of simple convenience methods using level names as method names
1860
// and use Supplier<String>
1861
//=======================================================================
1862
1863
/**
1864
* Log a SEVERE message, which is only to be constructed if the logging
1865
* level is such that the message will actually be logged.
1866
* <p>
1867
* If the logger is currently enabled for the SEVERE message
1868
* level then the message is constructed by invoking the provided
1869
* supplier function and forwarded to all the registered output
1870
* Handler objects.
1871
*
1872
* @param msgSupplier A function, which when called, produces the
1873
* desired log message
1874
* @since 1.8
1875
*/
1876
public void severe(Supplier<String> msgSupplier) {
1877
log(Level.SEVERE, msgSupplier);
1878
}
1879
1880
/**
1881
* Log a WARNING message, which is only to be constructed if the logging
1882
* level is such that the message will actually be logged.
1883
* <p>
1884
* If the logger is currently enabled for the WARNING message
1885
* level then the message is constructed by invoking the provided
1886
* supplier function and forwarded to all the registered output
1887
* Handler objects.
1888
*
1889
* @param msgSupplier A function, which when called, produces the
1890
* desired log message
1891
* @since 1.8
1892
*/
1893
public void warning(Supplier<String> msgSupplier) {
1894
log(Level.WARNING, msgSupplier);
1895
}
1896
1897
/**
1898
* Log a INFO message, which is only to be constructed if the logging
1899
* level is such that the message will actually be logged.
1900
* <p>
1901
* If the logger is currently enabled for the INFO message
1902
* level then the message is constructed by invoking the provided
1903
* supplier function and forwarded to all the registered output
1904
* Handler objects.
1905
*
1906
* @param msgSupplier A function, which when called, produces the
1907
* desired log message
1908
* @since 1.8
1909
*/
1910
public void info(Supplier<String> msgSupplier) {
1911
log(Level.INFO, msgSupplier);
1912
}
1913
1914
/**
1915
* Log a CONFIG message, which is only to be constructed if the logging
1916
* level is such that the message will actually be logged.
1917
* <p>
1918
* If the logger is currently enabled for the CONFIG message
1919
* level then the message is constructed by invoking the provided
1920
* supplier function and forwarded to all the registered output
1921
* Handler objects.
1922
*
1923
* @param msgSupplier A function, which when called, produces the
1924
* desired log message
1925
* @since 1.8
1926
*/
1927
public void config(Supplier<String> msgSupplier) {
1928
log(Level.CONFIG, msgSupplier);
1929
}
1930
1931
/**
1932
* Log a FINE message, which is only to be constructed if the logging
1933
* level is such that the message will actually be logged.
1934
* <p>
1935
* If the logger is currently enabled for the FINE message
1936
* level then the message is constructed by invoking the provided
1937
* supplier function and forwarded to all the registered output
1938
* Handler objects.
1939
*
1940
* @param msgSupplier A function, which when called, produces the
1941
* desired log message
1942
* @since 1.8
1943
*/
1944
public void fine(Supplier<String> msgSupplier) {
1945
log(Level.FINE, msgSupplier);
1946
}
1947
1948
/**
1949
* Log a FINER message, which is only to be constructed if the logging
1950
* level is such that the message will actually be logged.
1951
* <p>
1952
* If the logger is currently enabled for the FINER message
1953
* level then the message is constructed by invoking the provided
1954
* supplier function and forwarded to all the registered output
1955
* Handler objects.
1956
*
1957
* @param msgSupplier A function, which when called, produces the
1958
* desired log message
1959
* @since 1.8
1960
*/
1961
public void finer(Supplier<String> msgSupplier) {
1962
log(Level.FINER, msgSupplier);
1963
}
1964
1965
/**
1966
* Log a FINEST message, which is only to be constructed if the logging
1967
* level is such that the message will actually be logged.
1968
* <p>
1969
* If the logger is currently enabled for the FINEST message
1970
* level then the message is constructed by invoking the provided
1971
* supplier function and forwarded to all the registered output
1972
* Handler objects.
1973
*
1974
* @param msgSupplier A function, which when called, produces the
1975
* desired log message
1976
* @since 1.8
1977
*/
1978
public void finest(Supplier<String> msgSupplier) {
1979
log(Level.FINEST, msgSupplier);
1980
}
1981
1982
//================================================================
1983
// End of convenience methods
1984
//================================================================
1985
1986
/**
1987
* Set the log level specifying which message levels will be
1988
* logged by this logger. Message levels lower than this
1989
* value will be discarded. The level value Level.OFF
1990
* can be used to turn off logging.
1991
* <p>
1992
* If the new level is null, it means that this node should
1993
* inherit its level from its nearest ancestor with a specific
1994
* (non-null) level value.
1995
*
1996
* @param newLevel the new value for the log level (may be null)
1997
* @throws SecurityException if a security manager exists,
1998
* this logger is not anonymous, and the caller
1999
* does not have LoggingPermission("control").
2000
*/
2001
public void setLevel(Level newLevel) throws SecurityException {
2002
checkPermission();
2003
synchronized (treeLock) {
2004
config.setLevelObject(newLevel);
2005
updateEffectiveLevel();
2006
}
2007
}
2008
2009
final boolean isLevelInitialized() {
2010
return config.levelObject != null;
2011
}
2012
2013
/**
2014
* Get the log Level that has been specified for this Logger.
2015
* The result may be null, which means that this logger's
2016
* effective level will be inherited from its parent.
2017
*
2018
* @return this Logger's level
2019
*/
2020
public Level getLevel() {
2021
return config.levelObject;
2022
}
2023
2024
/**
2025
* Check if a message of the given level would actually be logged
2026
* by this logger. This check is based on the Loggers effective level,
2027
* which may be inherited from its parent.
2028
*
2029
* @param level a message logging level
2030
* @return true if the given message level is currently being logged.
2031
*/
2032
public boolean isLoggable(Level level) {
2033
int levelValue = config.levelValue;
2034
if (level.intValue() < levelValue || levelValue == offValue) {
2035
return false;
2036
}
2037
return true;
2038
}
2039
2040
/**
2041
* Get the name for this logger.
2042
* @return logger name. Will be null for anonymous Loggers.
2043
*/
2044
public String getName() {
2045
return name;
2046
}
2047
2048
/**
2049
* Add a log Handler to receive logging messages.
2050
* <p>
2051
* By default, Loggers also send their output to their parent logger.
2052
* Typically the root Logger is configured with a set of Handlers
2053
* that essentially act as default handlers for all loggers.
2054
*
2055
* @param handler a logging Handler
2056
* @throws SecurityException if a security manager exists,
2057
* this logger is not anonymous, and the caller
2058
* does not have LoggingPermission("control").
2059
*/
2060
public void addHandler(Handler handler) throws SecurityException {
2061
Objects.requireNonNull(handler);
2062
checkPermission();
2063
config.addHandler(handler);
2064
}
2065
2066
/**
2067
* Remove a log Handler.
2068
* <P>
2069
* Returns silently if the given Handler is not found or is null
2070
*
2071
* @param handler a logging Handler
2072
* @throws SecurityException if a security manager exists,
2073
* this logger is not anonymous, and the caller
2074
* does not have LoggingPermission("control").
2075
*/
2076
public void removeHandler(Handler handler) throws SecurityException {
2077
checkPermission();
2078
if (handler == null) {
2079
return;
2080
}
2081
config.removeHandler(handler);
2082
}
2083
2084
/**
2085
* Get the Handlers associated with this logger.
2086
*
2087
* @return an array of all registered Handlers
2088
*/
2089
public Handler[] getHandlers() {
2090
return accessCheckedHandlers();
2091
}
2092
2093
// This method should ideally be marked final - but unfortunately
2094
// it needs to be overridden by LogManager.RootLogger
2095
Handler[] accessCheckedHandlers() {
2096
return config.handlers.toArray(emptyHandlers);
2097
}
2098
2099
/**
2100
* Specify whether or not this logger should send its output
2101
* to its parent Logger. This means that any LogRecords will
2102
* also be written to the parent's Handlers, and potentially
2103
* to its parent, recursively up the namespace.
2104
*
2105
* @param useParentHandlers true if output is to be sent to the
2106
* logger's parent.
2107
* @throws SecurityException if a security manager exists,
2108
* this logger is not anonymous, and the caller
2109
* does not have LoggingPermission("control").
2110
*/
2111
public void setUseParentHandlers(boolean useParentHandlers) {
2112
checkPermission();
2113
config.setUseParentHandlers(useParentHandlers);
2114
}
2115
2116
/**
2117
* Discover whether or not this logger is sending its output
2118
* to its parent logger.
2119
*
2120
* @return true if output is to be sent to the logger's parent
2121
*/
2122
public boolean getUseParentHandlers() {
2123
return config.useParentHandlers;
2124
}
2125
2126
private ResourceBundle catalog() {
2127
WeakReference<ResourceBundle> ref = catalogRef;
2128
return ref == null ? null : ref.get();
2129
}
2130
2131
/**
2132
* Private utility method to map a resource bundle name to an
2133
* actual resource bundle, using a simple one-entry cache.
2134
* Returns null for a null name.
2135
* May also return null if we can't find the resource bundle and
2136
* there is no suitable previous cached value.
2137
*
2138
* @param name the ResourceBundle to locate
2139
* @param useCallersModule if true search using the caller's module.
2140
* @return ResourceBundle specified by name or null if not found
2141
*/
2142
private synchronized ResourceBundle findResourceBundle(String name,
2143
boolean useCallersModule) {
2144
// When this method is called from logrb, useCallersModule==false, and
2145
// the resource bundle 'name' is the argument provided to logrb.
2146
// It may, or may not be, equal to lb.resourceBundleName.
2147
// Otherwise, useCallersModule==true, and name is the resource bundle
2148
// name that is set (or will be set) in this logger.
2149
//
2150
// When useCallersModule is false, or when the caller's module is
2151
// null, or when the caller's module is an unnamed module, we look
2152
// first in the TCCL (or the System ClassLoader if the TCCL is null)
2153
// to locate the resource bundle.
2154
//
2155
// Otherwise, if useCallersModule is true, and the caller's module is not
2156
// null, and the caller's module is named, we look in the caller's module
2157
// to locate the resource bundle.
2158
//
2159
// Finally, if the caller's module is not null and is unnamed, and
2160
// useCallersModule is true, we look in the caller's module class loader
2161
// (unless we already looked there in step 1).
2162
2163
// Return a null bundle for a null name.
2164
if (name == null) {
2165
return null;
2166
}
2167
2168
Locale currentLocale = Locale.getDefault();
2169
final LoggerBundle lb = loggerBundle;
2170
ResourceBundle catalog = catalog();
2171
2172
// Normally we should hit on our simple one entry cache.
2173
if (lb.userBundle != null &&
2174
name.equals(lb.resourceBundleName)) {
2175
return lb.userBundle;
2176
} else if (catalog != null && currentLocale.equals(catalogLocale)
2177
&& name.equals(catalogName)) {
2178
return catalog;
2179
}
2180
2181
// Use the thread's context ClassLoader. If there isn't one, use the
2182
// {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader}.
2183
ClassLoader cl = Thread.currentThread().getContextClassLoader();
2184
if (cl == null) {
2185
cl = ClassLoader.getSystemClassLoader();
2186
}
2187
2188
final Module callerModule = getCallerModule();
2189
2190
// If useCallersModule is false, we are called by logrb, with a name
2191
// that is provided by the user. In that case we will look in the TCCL.
2192
// We also look in the TCCL if callerModule is null or unnamed.
2193
if (!useCallersModule || callerModule == null || !callerModule.isNamed()) {
2194
try {
2195
Module mod = cl.getUnnamedModule();
2196
catalog = RbAccess.RB_ACCESS.getBundle(name, currentLocale, mod);
2197
catalogRef = new WeakReference<>(catalog);
2198
catalogName = name;
2199
catalogLocale = currentLocale;
2200
return catalog;
2201
} catch (MissingResourceException ex) {
2202
// We can't find the ResourceBundle in the default
2203
// ClassLoader. Drop through.
2204
if (useCallersModule && callerModule != null) {
2205
try {
2206
// We are called by an unnamed module: try with the
2207
// unnamed module class loader:
2208
PrivilegedAction<ClassLoader> getModuleClassLoader =
2209
() -> callerModule.getClassLoader();
2210
@SuppressWarnings("removal")
2211
ClassLoader moduleCL =
2212
AccessController.doPrivileged(getModuleClassLoader);
2213
// moduleCL can be null if the logger is created by a class
2214
// appended to the bootclasspath.
2215
// If moduleCL is null we would use cl, but we already tried
2216
// that above (we first looked in the TCCL for unnamed
2217
// caller modules) - so there no point in trying again: we
2218
// won't find anything more this second time.
2219
// In this case just return null.
2220
if (moduleCL == cl || moduleCL == null) return null;
2221
2222
// we already tried the TCCL and found nothing - so try
2223
// with the module's loader this time.
2224
catalog = ResourceBundle.getBundle(name, currentLocale,
2225
moduleCL);
2226
catalogRef = new WeakReference<>(catalog);
2227
catalogName = name;
2228
catalogLocale = currentLocale;
2229
return catalog;
2230
} catch (MissingResourceException x) {
2231
return null; // no luck
2232
}
2233
} else {
2234
return null;
2235
}
2236
}
2237
} else {
2238
// we should have:
2239
// useCallersModule && callerModule != null && callerModule.isNamed();
2240
// Try with the caller's module
2241
try {
2242
// Use the caller's module
2243
catalog = RbAccess.RB_ACCESS.getBundle(name, currentLocale, callerModule);
2244
catalogRef = new WeakReference<>(catalog);
2245
catalogName = name;
2246
catalogLocale = currentLocale;
2247
return catalog;
2248
} catch (MissingResourceException ex) {
2249
return null; // no luck
2250
}
2251
}
2252
}
2253
2254
private void setupResourceInfo(String name, Class<?> caller) {
2255
final Module module = caller == null ? null : caller.getModule();
2256
setupResourceInfo(name, module);
2257
}
2258
2259
// Private utility method to initialize our one entry
2260
// resource bundle name cache and the callers Module
2261
// Note: for consistency reasons, we are careful to check
2262
// that a suitable ResourceBundle exists before setting the
2263
// resourceBundleName field.
2264
// Synchronized to prevent races in setting the fields.
2265
private synchronized void setupResourceInfo(String name,
2266
Module callerModule) {
2267
final LoggerBundle lb = loggerBundle;
2268
if (lb.resourceBundleName != null) {
2269
// this Logger already has a ResourceBundle
2270
2271
if (lb.resourceBundleName.equals(name)) {
2272
// the names match so there is nothing more to do
2273
return;
2274
}
2275
2276
// cannot change ResourceBundles once they are set
2277
throw new IllegalArgumentException(
2278
lb.resourceBundleName + " != " + name);
2279
}
2280
2281
if (name == null) {
2282
return;
2283
}
2284
2285
setCallerModuleRef(callerModule);
2286
2287
if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) {
2288
checkPermission();
2289
}
2290
2291
if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
2292
loggerBundle = SYSTEM_BUNDLE;
2293
} else {
2294
ResourceBundle bundle = findResourceBundle(name, true);
2295
if (bundle == null) {
2296
// We've failed to find an expected ResourceBundle.
2297
// unset the caller's module since we were unable to find the
2298
// the bundle using it
2299
this.callerModuleRef = null;
2300
throw new MissingResourceException("Can't find " + name + " bundle from ",
2301
name, "");
2302
}
2303
2304
loggerBundle = LoggerBundle.get(name, null);
2305
}
2306
}
2307
2308
/**
2309
* Sets a resource bundle on this logger.
2310
* All messages will be logged using the given resource bundle for its
2311
* specific {@linkplain ResourceBundle#getLocale locale}.
2312
* @param bundle The resource bundle that this logger shall use.
2313
* @throws NullPointerException if the given bundle is {@code null}.
2314
* @throws IllegalArgumentException if the given bundle doesn't have a
2315
* {@linkplain ResourceBundle#getBaseBundleName base name},
2316
* or if this logger already has a resource bundle set but
2317
* the given bundle has a different base name.
2318
* @throws SecurityException if a security manager exists,
2319
* this logger is not anonymous, and the caller
2320
* does not have LoggingPermission("control").
2321
* @since 1.8
2322
*/
2323
public void setResourceBundle(ResourceBundle bundle) {
2324
checkPermission();
2325
2326
// Will throw NPE if bundle is null.
2327
final String baseName = bundle.getBaseBundleName();
2328
2329
// bundle must have a name
2330
if (baseName == null || baseName.isEmpty()) {
2331
throw new IllegalArgumentException("resource bundle must have a name");
2332
}
2333
2334
synchronized (this) {
2335
LoggerBundle lb = loggerBundle;
2336
final boolean canReplaceResourceBundle = lb.resourceBundleName == null
2337
|| lb.resourceBundleName.equals(baseName);
2338
2339
if (!canReplaceResourceBundle) {
2340
throw new IllegalArgumentException("can't replace resource bundle");
2341
}
2342
2343
2344
loggerBundle = LoggerBundle.get(baseName, bundle);
2345
}
2346
}
2347
2348
/**
2349
* Return the parent for this Logger.
2350
* <p>
2351
* This method returns the nearest extant parent in the namespace.
2352
* Thus if a Logger is called "a.b.c.d", and a Logger called "a.b"
2353
* has been created but no logger "a.b.c" exists, then a call of
2354
* getParent on the Logger "a.b.c.d" will return the Logger "a.b".
2355
* <p>
2356
* The result will be null if it is called on the root Logger
2357
* in the namespace.
2358
*
2359
* @return nearest existing parent Logger
2360
*/
2361
public Logger getParent() {
2362
// Note: this used to be synchronized on treeLock. However, this only
2363
// provided memory semantics, as there was no guarantee that the caller
2364
// would synchronize on treeLock (in fact, there is no way for external
2365
// callers to so synchronize). Therefore, we have made parent volatile
2366
// instead.
2367
return parent;
2368
}
2369
2370
/**
2371
* Set the parent for this Logger. This method is used by
2372
* the LogManager to update a Logger when the namespace changes.
2373
* <p>
2374
* It should not be called from application code.
2375
*
2376
* @param parent the new parent logger
2377
* @throws SecurityException if a security manager exists and if
2378
* the caller does not have LoggingPermission("control").
2379
*/
2380
public void setParent(Logger parent) {
2381
if (parent == null) {
2382
throw new NullPointerException();
2383
}
2384
2385
// check permission for all loggers, including anonymous loggers
2386
if (manager == null) {
2387
manager = LogManager.getLogManager();
2388
}
2389
manager.checkPermission();
2390
2391
doSetParent(parent);
2392
}
2393
2394
// Private method to do the work for parenting a child
2395
// Logger onto a parent logger.
2396
private void doSetParent(Logger newParent) {
2397
2398
// System.err.println("doSetParent \"" + getName() + "\" \""
2399
// + newParent.getName() + "\"");
2400
2401
synchronized (treeLock) {
2402
2403
// Remove ourself from any previous parent.
2404
LogManager.LoggerWeakRef ref = null;
2405
if (parent != null) {
2406
// assert parent.kids != null;
2407
for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
2408
ref = iter.next();
2409
if (ref.refersTo(this)) {
2410
// ref is used down below to complete the reparenting
2411
iter.remove();
2412
break;
2413
} else {
2414
ref = null;
2415
}
2416
}
2417
// We have now removed ourself from our parents' kids.
2418
}
2419
2420
// Set our new parent.
2421
parent = newParent;
2422
if (parent.kids == null) {
2423
parent.kids = new ArrayList<>(2);
2424
}
2425
if (ref == null) {
2426
// we didn't have a previous parent
2427
ref = manager.new LoggerWeakRef(this);
2428
}
2429
ref.setParentRef(new WeakReference<>(parent));
2430
parent.kids.add(ref);
2431
2432
// As a result of the reparenting, the effective level
2433
// may have changed for us and our children.
2434
updateEffectiveLevel();
2435
2436
}
2437
}
2438
2439
// Package-level method.
2440
// Remove the weak reference for the specified child Logger from the
2441
// kid list. We should only be called from LoggerWeakRef.dispose().
2442
final void removeChildLogger(LogManager.LoggerWeakRef child) {
2443
synchronized (treeLock) {
2444
for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
2445
LogManager.LoggerWeakRef ref = iter.next();
2446
if (ref == child) {
2447
iter.remove();
2448
return;
2449
}
2450
}
2451
}
2452
}
2453
2454
// Recalculate the effective level for this node and
2455
// recursively for our children.
2456
2457
private void updateEffectiveLevel() {
2458
// assert Thread.holdsLock(treeLock);
2459
2460
// Figure out our current effective level.
2461
int newLevelValue;
2462
final ConfigurationData cfg = config;
2463
final Level levelObject = cfg.levelObject;
2464
if (levelObject != null) {
2465
newLevelValue = levelObject.intValue();
2466
} else {
2467
if (parent != null) {
2468
newLevelValue = parent.config.levelValue;
2469
} else {
2470
// This may happen during initialization.
2471
newLevelValue = Level.INFO.intValue();
2472
}
2473
}
2474
2475
// If our effective value hasn't changed, we're done.
2476
if (cfg.levelValue == newLevelValue) {
2477
return;
2478
}
2479
2480
cfg.setLevelValue(newLevelValue);
2481
2482
// System.err.println("effective level: \"" + getName() + "\" := " + level);
2483
2484
// Recursively update the level on each of our kids.
2485
if (kids != null) {
2486
for (LogManager.LoggerWeakRef ref : kids) {
2487
Logger kid = ref.get();
2488
if (kid != null) {
2489
kid.updateEffectiveLevel();
2490
}
2491
}
2492
}
2493
}
2494
2495
2496
// Private method to get the potentially inherited
2497
// resource bundle and resource bundle name for this Logger.
2498
// This method never returns null.
2499
private LoggerBundle getEffectiveLoggerBundle() {
2500
final LoggerBundle lb = loggerBundle;
2501
if (lb.isSystemBundle()) {
2502
return SYSTEM_BUNDLE;
2503
}
2504
2505
// first take care of this logger
2506
final ResourceBundle b = getResourceBundle();
2507
if (b != null && b == lb.userBundle) {
2508
return lb;
2509
} else if (b != null) {
2510
// either lb.userBundle is null or getResourceBundle() is
2511
// overriden
2512
final String rbName = getResourceBundleName();
2513
return LoggerBundle.get(rbName, b);
2514
}
2515
2516
// no resource bundle was specified on this logger, look up the
2517
// parent stack.
2518
Logger target = this.parent;
2519
while (target != null) {
2520
final LoggerBundle trb = target.loggerBundle;
2521
if (trb.isSystemBundle()) {
2522
return SYSTEM_BUNDLE;
2523
}
2524
if (trb.userBundle != null) {
2525
return trb;
2526
}
2527
final String rbName = isSystemLogger
2528
// ancestor of a system logger is expected to be a system logger.
2529
// ignore resource bundle name if it's not.
2530
? (target.isSystemLogger ? trb.resourceBundleName : null)
2531
: target.getResourceBundleName();
2532
if (rbName != null) {
2533
return LoggerBundle.get(rbName,
2534
findResourceBundle(rbName, true));
2535
}
2536
target = isSystemLogger ? target.parent : target.getParent();
2537
}
2538
return NO_RESOURCE_BUNDLE;
2539
}
2540
2541
}
2542
2543