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
27 package java.util.logging;
28
29 import java.io.*;
30 import java.util.*;
31 import java.security.*;
32 import java.lang.ref.ReferenceQueue;
33 import java.lang.ref.WeakReference;
34 import sun.misc.JavaAWTAccess;
35 import sun.misc.SharedSecrets;
36
37 /**
38 * There is a single global LogManager object that is used to
39 * maintain a set of shared state about Loggers and log services.
40 * <p>
41 * This LogManager object:
42 * <ul>
43 * <li> Manages a hierarchical namespace of Logger objects. All
44 * named Loggers are stored in this namespace.
45 * <li> Manages a set of logging control properties. These are
46 * simple key-value pairs that can be used by Handlers and
47 * other logging objects to configure themselves.
48 * </ul>
49 * <p>
50 * The global LogManager object can be retrieved using LogManager.getLogManager().
51 * The LogManager object is created during class initialization and
52 * cannot subsequently be changed.
53 * <p>
83 * <p>
84 * The properties for loggers and Handlers will have names starting
85 * with the dot-separated name for the handler or logger.
86 * <p>
87 * The global logging properties may include:
88 * <ul>
89 * <li>A property "handlers". This defines a whitespace or comma separated
90 * list of class names for handler classes to load and register as
91 * handlers on the root Logger (the Logger named ""). Each class
92 * name must be for a Handler class which has a default constructor.
93 * Note that these Handlers may be created lazily, when they are
94 * first used.
95 *
96 * <li>A property "<logger>.handlers". This defines a whitespace or
97 * comma separated list of class names for handlers classes to
98 * load and register as handlers to the specified logger. Each class
99 * name must be for a Handler class which has a default constructor.
100 * Note that these Handlers may be created lazily, when they are
101 * first used.
102 *
103 * <li>A property "<logger>.useParentHandlers". This defines a boolean
104 * value. By default every logger calls its parent in addition to
105 * handling the logging message itself, this often result in messages
106 * being handled by the root logger as well. When setting this property
107 * to false a Handler needs to be configured for this logger otherwise
108 * no logging messages are delivered.
109 *
110 * <li>A property "config". This property is intended to allow
111 * arbitrary configuration code to be run. The property defines a
112 * whitespace or comma separated list of class names. A new instance will be
113 * created for each named class. The default constructor of each class
114 * may execute arbitrary code to update the logging configuration, such as
115 * setting logger levels, adding handlers, adding filters, etc.
116 * </ul>
117 * <p>
118 * Note that all classes loaded during LogManager configuration are
119 * first searched on the system class path before any user class path.
120 * That includes the LogManager class, any config classes, and any
121 * handler classes.
122 * <p>
152 private volatile Properties props = new Properties();
153 private final static Level defaultLevel = Level.INFO;
154
155 // LoggerContext for system loggers and user loggers
156 private final LoggerContext systemContext = new SystemLoggerContext();
157 private final LoggerContext userContext = new LoggerContext();
158 // non final field - make it volatile to make sure that other threads
159 // will see the new value once ensureLogManagerInitialized() has finished
160 // executing.
161 private volatile Logger rootLogger;
162 // Have we done the primordial reading of the configuration file?
163 // (Must be done after a suitable amount of java.lang.System
164 // initialization has been done)
165 private volatile boolean readPrimordialConfiguration;
166 // Have we initialized global (root) handlers yet?
167 // This gets set to false in readConfiguration
168 private boolean initializedGlobalHandlers = true;
169 // True if JVM death is imminent and the exit hook has been called.
170 private boolean deathImminent;
171
172 private final Map<Object, Runnable> listeners =
173 Collections.synchronizedMap(new IdentityHashMap<>());
174
175 static {
176 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
177 @Override
178 public LogManager run() {
179 LogManager mgr = null;
180 String cname = null;
181 try {
182 cname = System.getProperty("java.util.logging.manager");
183 if (cname != null) {
184 try {
185 Class<?> clz = ClassLoader.getSystemClassLoader()
186 .loadClass(cname);
187 mgr = (LogManager) clz.newInstance();
188 } catch (ClassNotFoundException ex) {
189 Class<?> clz = Thread.currentThread()
190 .getContextClassLoader().loadClass(cname);
191 mgr = (LogManager) clz.newInstance();
192 }
193 }
194 } catch (Exception ex) {
195 System.err.println("Could not load Logmanager \"" + cname + "\"");
196 ex.printStackTrace();
197 }
198 if (mgr == null) {
199 mgr = new LogManager();
200 }
201 return mgr;
202
203 }
204 });
205 }
206
207
208 // This private class is used as a shutdown hook.
209 // It does a "reset" to close all open handlers.
210 private class Cleaner extends Thread {
211
212 private Cleaner() {
213 /* Set context class loader to null in order to avoid
214 * keeping a strong reference to an application classloader.
215 */
216 this.setContextClassLoader(null);
217 }
218
219 @Override
220 public void run() {
221 // This is to ensure the LogManager.<clinit> is completed
222 // before synchronized block. Otherwise deadlocks are possible.
223 LogManager mgr = manager;
224
225 // If the global handlers haven't been initialized yet, we
226 // don't want to initialize them just so we can close them!
227 synchronized (LogManager.this) {
858 // we'll just loop around and try again.
859 result = findLogger(name);
860 }
861 } while (result == null);
862 }
863 return result;
864 }
865 }
866
867 // Add new per logger handlers.
868 // We need to raise privilege here. All our decisions will
869 // be made based on the logging configuration, which can
870 // only be modified by trusted code.
871 private void loadLoggerHandlers(final Logger logger, final String name,
872 final String handlersPropertyName)
873 {
874 AccessController.doPrivileged(new PrivilegedAction<Object>() {
875 @Override
876 public Object run() {
877 String names[] = parseClassNames(handlersPropertyName);
878 for (String word : names) {
879 try {
880 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
881 Handler hdl = (Handler) clz.newInstance();
882 // Check if there is a property defining the
883 // this handler's level.
884 String levs = getProperty(word + ".level");
885 if (levs != null) {
886 Level l = Level.findLevel(levs);
887 if (l != null) {
888 hdl.setLevel(l);
889 } else {
890 // Probably a bad level. Drop through.
891 System.err.println("Can't set level for " + word);
892 }
893 }
894 // Add this Handler to the logger
895 logger.addHandler(hdl);
896 } catch (Exception ex) {
897 System.err.println("Can't load log handler \"" + word + "\"");
898 System.err.println("" + ex);
899 ex.printStackTrace();
900 }
901 }
902 return null;
903 }
904 });
905 }
906
907
908 // loggerRefQueue holds LoggerWeakRef objects for Logger objects
909 // that have been GC'ed.
910 private final ReferenceQueue<Logger> loggerRefQueue
911 = new ReferenceQueue<>();
912
913 // Package-level inner class.
914 // Helper class for managing WeakReferences to Logger objects.
915 //
916 // LogManager.namedLoggers
917 // - has weak references to all named Loggers
918 // - namedLoggers keeps the LoggerWeakRef objects for the named
919 // Loggers around until we can deal with the book keeping for
920 // the named Logger that is being GC'ed.
921 // LogManager.LogNode.loggerRef
1216 }
1217 try (final InputStream in = new FileInputStream(fname)) {
1218 final BufferedInputStream bin = new BufferedInputStream(in);
1219 readConfiguration(bin);
1220 }
1221 }
1222
1223 /**
1224 * Reset the logging configuration.
1225 * <p>
1226 * For all named loggers, the reset operation removes and closes
1227 * all Handlers and (except for the root logger) sets the level
1228 * to null. The root logger's level is set to Level.INFO.
1229 *
1230 * @exception SecurityException if a security manager exists and if
1231 * the caller does not have LoggingPermission("control").
1232 */
1233
1234 public void reset() throws SecurityException {
1235 checkPermission();
1236 synchronized (this) {
1237 props = new Properties();
1238 // Since we are doing a reset we no longer want to initialize
1239 // the global handlers, if they haven't been initialized yet.
1240 initializedGlobalHandlers = true;
1241 }
1242 for (LoggerContext cx : contexts()) {
1243 Enumeration<String> enum_ = cx.getLoggerNames();
1244 while (enum_.hasMoreElements()) {
1245 String name = enum_.nextElement();
1246 Logger logger = cx.findLogger(name);
1247 if (logger != null) {
1248 resetLogger(logger);
1249 }
1250 }
1251 }
1252 }
1253
1254 // Private method to reset an individual target logger.
1255 private void resetLogger(Logger logger) {
1256 // Close all the Logger's handlers.
1257 Handler[] targets = logger.getHandlers();
1258 for (Handler h : targets) {
1259 logger.removeHandler(h);
1260 try {
1261 h.close();
1262 } catch (Exception ex) {
1263 // Problems closing a handler? Keep going...
1264 }
1265 }
1266 String name = logger.getName();
1267 if (name != null && name.equals("")) {
1268 // This is the root logger.
1269 logger.setLevel(defaultLevel);
1270 } else {
1271 logger.setLevel(null);
|
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
27 package java.util.logging;
28
29 import java.io.*;
30 import java.util.*;
31 import java.security.*;
32 import java.lang.ref.ReferenceQueue;
33 import java.lang.ref.WeakReference;
34 import java.util.concurrent.CopyOnWriteArrayList;
35 import sun.misc.JavaAWTAccess;
36 import sun.misc.SharedSecrets;
37
38 /**
39 * There is a single global LogManager object that is used to
40 * maintain a set of shared state about Loggers and log services.
41 * <p>
42 * This LogManager object:
43 * <ul>
44 * <li> Manages a hierarchical namespace of Logger objects. All
45 * named Loggers are stored in this namespace.
46 * <li> Manages a set of logging control properties. These are
47 * simple key-value pairs that can be used by Handlers and
48 * other logging objects to configure themselves.
49 * </ul>
50 * <p>
51 * The global LogManager object can be retrieved using LogManager.getLogManager().
52 * The LogManager object is created during class initialization and
53 * cannot subsequently be changed.
54 * <p>
84 * <p>
85 * The properties for loggers and Handlers will have names starting
86 * with the dot-separated name for the handler or logger.
87 * <p>
88 * The global logging properties may include:
89 * <ul>
90 * <li>A property "handlers". This defines a whitespace or comma separated
91 * list of class names for handler classes to load and register as
92 * handlers on the root Logger (the Logger named ""). Each class
93 * name must be for a Handler class which has a default constructor.
94 * Note that these Handlers may be created lazily, when they are
95 * first used.
96 *
97 * <li>A property "<logger>.handlers". This defines a whitespace or
98 * comma separated list of class names for handlers classes to
99 * load and register as handlers to the specified logger. Each class
100 * name must be for a Handler class which has a default constructor.
101 * Note that these Handlers may be created lazily, when they are
102 * first used.
103 *
104 * <li>A property "<logger>.handlers.ensureCloseOnReset". This defines a
105 * a boolean value. If "<logger>.handlers" is not defined or is empty,
106 * this property is ignored. Otherwise it defaults to "true". When the value
107 * is "true", the loggers for which at least one handler was configured
108 * using the previous "<logger>.handlers" property will stay
109 * strongly referenced until {@code reset()} is called. This can be turned off
110 * by explicitly setting "<logger>.handlers.ensureCloseOnReset=false" in
111 * the configuration. Note that turning this property off causes the risk of
112 * introducing a resource leak, as the logger may get garbage collected before
113 * {@code reset()} is called, thus preventing its handlers from being closed
114 * on {@code reset()}.
115 *
116 * <li>A property "<logger>.useParentHandlers". This defines a boolean
117 * value. By default every logger calls its parent in addition to
118 * handling the logging message itself, this often result in messages
119 * being handled by the root logger as well. When setting this property
120 * to false a Handler needs to be configured for this logger otherwise
121 * no logging messages are delivered.
122 *
123 * <li>A property "config". This property is intended to allow
124 * arbitrary configuration code to be run. The property defines a
125 * whitespace or comma separated list of class names. A new instance will be
126 * created for each named class. The default constructor of each class
127 * may execute arbitrary code to update the logging configuration, such as
128 * setting logger levels, adding handlers, adding filters, etc.
129 * </ul>
130 * <p>
131 * Note that all classes loaded during LogManager configuration are
132 * first searched on the system class path before any user class path.
133 * That includes the LogManager class, any config classes, and any
134 * handler classes.
135 * <p>
165 private volatile Properties props = new Properties();
166 private final static Level defaultLevel = Level.INFO;
167
168 // LoggerContext for system loggers and user loggers
169 private final LoggerContext systemContext = new SystemLoggerContext();
170 private final LoggerContext userContext = new LoggerContext();
171 // non final field - make it volatile to make sure that other threads
172 // will see the new value once ensureLogManagerInitialized() has finished
173 // executing.
174 private volatile Logger rootLogger;
175 // Have we done the primordial reading of the configuration file?
176 // (Must be done after a suitable amount of java.lang.System
177 // initialization has been done)
178 private volatile boolean readPrimordialConfiguration;
179 // Have we initialized global (root) handlers yet?
180 // This gets set to false in readConfiguration
181 private boolean initializedGlobalHandlers = true;
182 // True if JVM death is imminent and the exit hook has been called.
183 private boolean deathImminent;
184
185 // This list contains the loggers for which some handlers have been
186 // explicitely configured in the configuration file.
187 // It prevents these loggers from being arbitrarily garbage collected.
188 private static final class PersistentLogger {
189 private final Logger logger;
190 private PersistentLogger(Logger ref) {
191 this.logger = Objects.requireNonNull(ref);
192 }
193 @Override
194 public boolean equals(Object other) {
195 return (other instanceof PersistentLogger) && ((PersistentLogger)other).logger == logger;
196 }
197 @Override
198 public int hashCode() {
199 return System.identityHashCode(logger);
200 }
201 public Logger get() {
202 return logger;
203 }
204 public static PersistentLogger create(Logger logger) {
205 return new PersistentLogger(logger);
206 }
207 }
208 private final CopyOnWriteArrayList<PersistentLogger> persistentLoggers =
209 new CopyOnWriteArrayList<>();
210
211
212 private final Map<Object, Runnable> listeners =
213 Collections.synchronizedMap(new IdentityHashMap<>());
214
215 static {
216 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
217 @Override
218 public LogManager run() {
219 LogManager mgr = null;
220 String cname = null;
221 try {
222 cname = System.getProperty("java.util.logging.manager");
223 if (cname != null) {
224 try {
225 Class<?> clz = ClassLoader.getSystemClassLoader()
226 .loadClass(cname);
227 mgr = (LogManager) clz.newInstance();
228 } catch (ClassNotFoundException ex) {
229 Class<?> clz = Thread.currentThread()
230 .getContextClassLoader().loadClass(cname);
231 mgr = (LogManager) clz.newInstance();
232 }
233 }
234 } catch (Exception ex) {
235 System.err.println("Could not load Logmanager \"" + cname + "\"");
236 ex.printStackTrace();
237 }
238 if (mgr == null) {
239 mgr = new LogManager();
240 }
241 return mgr;
242
243 }
244 });
245 }
246
247 // This private class is used as a shutdown hook.
248 // It does a "reset" to close all open handlers.
249 private class Cleaner extends Thread {
250
251 private Cleaner() {
252 /* Set context class loader to null in order to avoid
253 * keeping a strong reference to an application classloader.
254 */
255 this.setContextClassLoader(null);
256 }
257
258 @Override
259 public void run() {
260 // This is to ensure the LogManager.<clinit> is completed
261 // before synchronized block. Otherwise deadlocks are possible.
262 LogManager mgr = manager;
263
264 // If the global handlers haven't been initialized yet, we
265 // don't want to initialize them just so we can close them!
266 synchronized (LogManager.this) {
897 // we'll just loop around and try again.
898 result = findLogger(name);
899 }
900 } while (result == null);
901 }
902 return result;
903 }
904 }
905
906 // Add new per logger handlers.
907 // We need to raise privilege here. All our decisions will
908 // be made based on the logging configuration, which can
909 // only be modified by trusted code.
910 private void loadLoggerHandlers(final Logger logger, final String name,
911 final String handlersPropertyName)
912 {
913 AccessController.doPrivileged(new PrivilegedAction<Object>() {
914 @Override
915 public Object run() {
916 String names[] = parseClassNames(handlersPropertyName);
917 final boolean ensureCloseOnReset = names.length == 0 ? false
918 : getBooleanProperty(handlersPropertyName + ".ensureCloseOnReset",
919 names.length > 0);
920 int count = 0;
921 for (String type : names) {
922 try {
923 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
924 Handler hdl = (Handler) clz.newInstance();
925 // Check if there is a property defining the
926 // this handler's level.
927 String levs = getProperty(type + ".level");
928 if (levs != null) {
929 Level l = Level.findLevel(levs);
930 if (l != null) {
931 hdl.setLevel(l);
932 } else {
933 // Probably a bad level. Drop through.
934 System.err.println("Can't set level for " + type);
935 }
936 }
937 // Add this Handler to the logger
938 logger.addHandler(hdl);
939 if (++count == 1 && ensureCloseOnReset) {
940 // add this logger to the persitentLoggers list.
941 persistentLoggers.addIfAbsent(
942 PersistentLogger.create(logger));
943 }
944 } catch (Exception ex) {
945 System.err.println("Can't load log handler \"" + type + "\"");
946 System.err.println("" + ex);
947 ex.printStackTrace();
948 }
949 }
950
951 return null;
952 }
953 });
954 }
955
956
957 // loggerRefQueue holds LoggerWeakRef objects for Logger objects
958 // that have been GC'ed.
959 private final ReferenceQueue<Logger> loggerRefQueue
960 = new ReferenceQueue<>();
961
962 // Package-level inner class.
963 // Helper class for managing WeakReferences to Logger objects.
964 //
965 // LogManager.namedLoggers
966 // - has weak references to all named Loggers
967 // - namedLoggers keeps the LoggerWeakRef objects for the named
968 // Loggers around until we can deal with the book keeping for
969 // the named Logger that is being GC'ed.
970 // LogManager.LogNode.loggerRef
1265 }
1266 try (final InputStream in = new FileInputStream(fname)) {
1267 final BufferedInputStream bin = new BufferedInputStream(in);
1268 readConfiguration(bin);
1269 }
1270 }
1271
1272 /**
1273 * Reset the logging configuration.
1274 * <p>
1275 * For all named loggers, the reset operation removes and closes
1276 * all Handlers and (except for the root logger) sets the level
1277 * to null. The root logger's level is set to Level.INFO.
1278 *
1279 * @exception SecurityException if a security manager exists and if
1280 * the caller does not have LoggingPermission("control").
1281 */
1282
1283 public void reset() throws SecurityException {
1284 checkPermission();
1285 List<PersistentLogger> persistent;
1286 synchronized (this) {
1287 props = new Properties();
1288 // make sure we keep the loggers persistent until reset is done.
1289 // Those are the loggers for which we previously created a
1290 // handler from the configuration, and we need to prevent them
1291 // from being gc'ed until those handlers are closed.
1292 persistent = new ArrayList<>(persistentLoggers);
1293 persistentLoggers.clear();
1294 // Since we are doing a reset we no longer want to initialize
1295 // the global handlers, if they haven't been initialized yet.
1296 initializedGlobalHandlers = true;
1297 }
1298 for (LoggerContext cx : contexts()) {
1299 Enumeration<String> enum_ = cx.getLoggerNames();
1300 while (enum_.hasMoreElements()) {
1301 String name = enum_.nextElement();
1302 Logger logger = cx.findLogger(name);
1303 if (logger != null) {
1304 resetLogger(logger);
1305 }
1306 }
1307 }
1308 persistent.clear();
1309 }
1310
1311 // Private method to reset an individual target logger.
1312 private void resetLogger(Logger logger) {
1313 // Close all the Logger's handlers.
1314 Handler[] targets = logger.getHandlers();
1315 for (Handler h : targets) {
1316 logger.removeHandler(h);
1317 try {
1318 h.close();
1319 } catch (Exception ex) {
1320 // Problems closing a handler? Keep going...
1321 }
1322 }
1323 String name = logger.getName();
1324 if (name != null && name.equals("")) {
1325 // This is the root logger.
1326 logger.setLevel(defaultLevel);
1327 } else {
1328 logger.setLevel(null);
|