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 {@code true}. When the
107 * value is {@code true}, the handlers associated with the logger are guaranteed
108 * to be closed on {@linkplain reset} and shutdown. This can be turned off
109 * by explicitly setting "<logger>.handlers.ensureCloseOnReset=false" in
110 * the configuration. Note that turning this property off causes the risk of
111 * introducing a resource leak, as the logger may get garbage collected before
112 * {@code reset()} is called, thus preventing its handlers from being closed
113 * on {@code reset()}. In that case it is the responsibility of the application
114 * to ensure that the handlers are closed before the logger is garbage
115 * collected.
116 *
117 * <li>A property "<logger>.useParentHandlers". This defines a boolean
118 * value. By default every logger calls its parent in addition to
119 * handling the logging message itself, this often result in messages
120 * being handled by the root logger as well. When setting this property
121 * to false a Handler needs to be configured for this logger otherwise
122 * no logging messages are delivered.
123 *
124 * <li>A property "config". This property is intended to allow
125 * arbitrary configuration code to be run. The property defines a
126 * whitespace or comma separated list of class names. A new instance will be
127 * created for each named class. The default constructor of each class
128 * may execute arbitrary code to update the logging configuration, such as
129 * setting logger levels, adding handlers, adding filters, etc.
130 * </ul>
131 * <p>
132 * Note that all classes loaded during LogManager configuration are
133 * first searched on the system class path before any user class path.
134 * That includes the LogManager class, any config classes, and any
135 * handler classes.
136 * <p>
166 private volatile Properties props = new Properties();
167 private final static Level defaultLevel = Level.INFO;
168
169 // LoggerContext for system loggers and user loggers
170 private final LoggerContext systemContext = new SystemLoggerContext();
171 private final LoggerContext userContext = new LoggerContext();
172 // non final field - make it volatile to make sure that other threads
173 // will see the new value once ensureLogManagerInitialized() has finished
174 // executing.
175 private volatile Logger rootLogger;
176 // Have we done the primordial reading of the configuration file?
177 // (Must be done after a suitable amount of java.lang.System
178 // initialization has been done)
179 private volatile boolean readPrimordialConfiguration;
180 // Have we initialized global (root) handlers yet?
181 // This gets set to false in readConfiguration
182 private boolean initializedGlobalHandlers = true;
183 // True if JVM death is imminent and the exit hook has been called.
184 private boolean deathImminent;
185
186 // This list contains the loggers for which some handlers have been
187 // explicitly configured in the configuration file.
188 // It prevents these loggers from being arbitrarily garbage collected.
189 private static final class CloseOnReset {
190 private final Logger logger;
191 private CloseOnReset(Logger ref) {
192 this.logger = Objects.requireNonNull(ref);
193 }
194 @Override
195 public boolean equals(Object other) {
196 return (other instanceof CloseOnReset) && ((CloseOnReset)other).logger == logger;
197 }
198 @Override
199 public int hashCode() {
200 return System.identityHashCode(logger);
201 }
202 public Logger get() {
203 return logger;
204 }
205 public static CloseOnReset create(Logger logger) {
206 return new CloseOnReset(logger);
207 }
208 }
209 private final CopyOnWriteArrayList<CloseOnReset> closeOnResetLoggers =
210 new CopyOnWriteArrayList<>();
211
212
213 private final Map<Object, Runnable> listeners =
214 Collections.synchronizedMap(new IdentityHashMap<>());
215
216 static {
217 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
218 @Override
219 public LogManager run() {
220 LogManager mgr = null;
221 String cname = null;
222 try {
223 cname = System.getProperty("java.util.logging.manager");
224 if (cname != null) {
225 try {
226 Class<?> clz = ClassLoader.getSystemClassLoader()
227 .loadClass(cname);
228 mgr = (LogManager) clz.newInstance();
229 } catch (ClassNotFoundException ex) {
230 Class<?> clz = Thread.currentThread()
231 .getContextClassLoader().loadClass(cname);
232 mgr = (LogManager) clz.newInstance();
233 }
234 }
235 } catch (Exception ex) {
236 System.err.println("Could not load Logmanager \"" + cname + "\"");
237 ex.printStackTrace();
238 }
239 if (mgr == null) {
240 mgr = new LogManager();
241 }
242 return mgr;
243
244 }
245 });
246 }
247
248 // This private class is used as a shutdown hook.
249 // It does a "reset" to close all open handlers.
250 private class Cleaner extends Thread {
251
252 private Cleaner() {
253 /* Set context class loader to null in order to avoid
254 * keeping a strong reference to an application classloader.
255 */
256 this.setContextClassLoader(null);
257 }
258
259 @Override
260 public void run() {
261 // This is to ensure the LogManager.<clinit> is completed
262 // before synchronized block. Otherwise deadlocks are possible.
263 LogManager mgr = manager;
264
265 // If the global handlers haven't been initialized yet, we
266 // don't want to initialize them just so we can close them!
267 synchronized (LogManager.this) {
898 // we'll just loop around and try again.
899 result = findLogger(name);
900 }
901 } while (result == null);
902 }
903 return result;
904 }
905 }
906
907 // Add new per logger handlers.
908 // We need to raise privilege here. All our decisions will
909 // be made based on the logging configuration, which can
910 // only be modified by trusted code.
911 private void loadLoggerHandlers(final Logger logger, final String name,
912 final String handlersPropertyName)
913 {
914 AccessController.doPrivileged(new PrivilegedAction<Object>() {
915 @Override
916 public Object run() {
917 String names[] = parseClassNames(handlersPropertyName);
918 final boolean ensureCloseOnReset = names.length > 0
919 && getBooleanProperty(
920 handlersPropertyName + ".ensureCloseOnReset",
921 true);
922 int count = 0;
923 for (String type : names) {
924 try {
925 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
926 Handler hdl = (Handler) clz.newInstance();
927 // Check if there is a property defining the
928 // this handler's level.
929 String levs = getProperty(type + ".level");
930 if (levs != null) {
931 Level l = Level.findLevel(levs);
932 if (l != null) {
933 hdl.setLevel(l);
934 } else {
935 // Probably a bad level. Drop through.
936 System.err.println("Can't set level for " + type);
937 }
938 }
939 // Add this Handler to the logger
940 logger.addHandler(hdl);
941 if (++count == 1 && ensureCloseOnReset) {
942 // add this logger to the closeOnResetLoggers list.
943 closeOnResetLoggers.addIfAbsent(CloseOnReset.create(logger));
944 }
945 } catch (Exception ex) {
946 System.err.println("Can't load log handler \"" + type + "\"");
947 System.err.println("" + ex);
948 ex.printStackTrace();
949 }
950 }
951
952 return null;
953 }
954 });
955 }
956
957
958 // loggerRefQueue holds LoggerWeakRef objects for Logger objects
959 // that have been GC'ed.
960 private final ReferenceQueue<Logger> loggerRefQueue
961 = new ReferenceQueue<>();
962
963 // Package-level inner class.
964 // Helper class for managing WeakReferences to Logger objects.
965 //
966 // LogManager.namedLoggers
967 // - has weak references to all named Loggers
968 // - namedLoggers keeps the LoggerWeakRef objects for the named
969 // Loggers around until we can deal with the book keeping for
970 // the named Logger that is being GC'ed.
971 // LogManager.LogNode.loggerRef
1266 }
1267 try (final InputStream in = new FileInputStream(fname)) {
1268 final BufferedInputStream bin = new BufferedInputStream(in);
1269 readConfiguration(bin);
1270 }
1271 }
1272
1273 /**
1274 * Reset the logging configuration.
1275 * <p>
1276 * For all named loggers, the reset operation removes and closes
1277 * all Handlers and (except for the root logger) sets the level
1278 * to null. The root logger's level is set to Level.INFO.
1279 *
1280 * @exception SecurityException if a security manager exists and if
1281 * the caller does not have LoggingPermission("control").
1282 */
1283
1284 public void reset() throws SecurityException {
1285 checkPermission();
1286 List<CloseOnReset> persistent;
1287 synchronized (this) {
1288 props = new Properties();
1289 // make sure we keep the loggers persistent until reset is done.
1290 // Those are the loggers for which we previously created a
1291 // handler from the configuration, and we need to prevent them
1292 // from being gc'ed until those handlers are closed.
1293 persistent = new ArrayList<>(closeOnResetLoggers);
1294 closeOnResetLoggers.clear();
1295 // Since we are doing a reset we no longer want to initialize
1296 // the global handlers, if they haven't been initialized yet.
1297 initializedGlobalHandlers = true;
1298 }
1299 for (LoggerContext cx : contexts()) {
1300 Enumeration<String> enum_ = cx.getLoggerNames();
1301 while (enum_.hasMoreElements()) {
1302 String name = enum_.nextElement();
1303 Logger logger = cx.findLogger(name);
1304 if (logger != null) {
1305 resetLogger(logger);
1306 }
1307 }
1308 }
1309 persistent.clear();
1310 }
1311
1312 // Private method to reset an individual target logger.
1313 private void resetLogger(Logger logger) {
1314 // Close all the Logger's handlers.
1315 Handler[] targets = logger.getHandlers();
1316 for (Handler h : targets) {
1317 logger.removeHandler(h);
1318 try {
1319 h.close();
1320 } catch (Exception ex) {
1321 // Problems closing a handler? Keep going...
1322 }
1323 }
1324 String name = logger.getName();
1325 if (name != null && name.equals("")) {
1326 // This is the root logger.
1327 logger.setLevel(defaultLevel);
1328 } else {
1329 logger.setLevel(null);
|