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>
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>
153 private volatile Properties props = new Properties();
154 private final static Level defaultLevel = Level.INFO;
155
156 // LoggerContext for system loggers and user loggers
157 private final LoggerContext systemContext = new SystemLoggerContext();
158 private final LoggerContext userContext = new LoggerContext();
159 // non final field - make it volatile to make sure that other threads
160 // will see the new value once ensureLogManagerInitialized() has finished
161 // executing.
162 private volatile Logger rootLogger;
163 // Have we done the primordial reading of the configuration file?
164 // (Must be done after a suitable amount of java.lang.System
165 // initialization has been done)
166 private volatile boolean readPrimordialConfiguration;
167 // Have we initialized global (root) handlers yet?
168 // This gets set to false in readConfiguration
169 private boolean initializedGlobalHandlers = true;
170 // True if JVM death is imminent and the exit hook has been called.
171 private boolean deathImminent;
172
173 // This list contains the loggers for which some handlers have been
174 // explicitely configured in the configuration file.
175 // It prevents these loggers from being arbitrarily garbage collected.
176 private static final class PersistentLogger {
177 private final Logger logger;
178 private PersistentLogger(Logger ref) {
179 this.logger = Objects.requireNonNull(ref);
180 }
181 @Override
182 public boolean equals(Object other) {
183 return (other instanceof PersistentLogger) && ((PersistentLogger)other).logger == logger;
184 }
185 @Override
186 public int hashCode() {
187 return System.identityHashCode(logger);
188 }
189 public Logger get() {
190 return logger;
191 }
192 public static PersistentLogger create(Logger logger) {
193 return new PersistentLogger(logger);
194 }
195 }
196 private final CopyOnWriteArrayList<PersistentLogger> persistentLoggers =
197 new CopyOnWriteArrayList<>();
198
199
200 private final Map<Object, Runnable> listeners =
201 Collections.synchronizedMap(new IdentityHashMap<>());
202
203 static {
204 manager = AccessController.doPrivileged(new PrivilegedAction<LogManager>() {
205 @Override
206 public LogManager run() {
207 LogManager mgr = null;
208 String cname = null;
209 try {
210 cname = System.getProperty("java.util.logging.manager");
211 if (cname != null) {
212 try {
213 Class<?> clz = ClassLoader.getSystemClassLoader()
214 .loadClass(cname);
215 mgr = (LogManager) clz.newInstance();
216 } catch (ClassNotFoundException ex) {
217 Class<?> clz = Thread.currentThread()
218 .getContextClassLoader().loadClass(cname);
219 mgr = (LogManager) clz.newInstance();
220 }
221 }
222 } catch (Exception ex) {
223 System.err.println("Could not load Logmanager \"" + cname + "\"");
224 ex.printStackTrace();
225 }
226 if (mgr == null) {
227 mgr = new LogManager();
228 }
229 return mgr;
230
231 }
232 });
233 }
234
235 // This private class is used as a shutdown hook.
236 // It does a "reset" to close all open handlers.
237 private class Cleaner extends Thread {
238
239 private Cleaner() {
240 /* Set context class loader to null in order to avoid
241 * keeping a strong reference to an application classloader.
242 */
243 this.setContextClassLoader(null);
244 }
245
246 @Override
247 public void run() {
248 // This is to ensure the LogManager.<clinit> is completed
249 // before synchronized block. Otherwise deadlocks are possible.
250 LogManager mgr = manager;
251
252 // If the global handlers haven't been initialized yet, we
253 // don't want to initialize them just so we can close them!
254 synchronized (LogManager.this) {
885 // we'll just loop around and try again.
886 result = findLogger(name);
887 }
888 } while (result == null);
889 }
890 return result;
891 }
892 }
893
894 // Add new per logger handlers.
895 // We need to raise privilege here. All our decisions will
896 // be made based on the logging configuration, which can
897 // only be modified by trusted code.
898 private void loadLoggerHandlers(final Logger logger, final String name,
899 final String handlersPropertyName)
900 {
901 AccessController.doPrivileged(new PrivilegedAction<Object>() {
902 @Override
903 public Object run() {
904 String names[] = parseClassNames(handlersPropertyName);
905 int count = 0;
906 for (String type : names) {
907 try {
908 Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(type);
909 Handler hdl = (Handler) clz.newInstance();
910 // Check if there is a property defining the
911 // this handler's level.
912 String levs = getProperty(type + ".level");
913 if (levs != null) {
914 Level l = Level.findLevel(levs);
915 if (l != null) {
916 hdl.setLevel(l);
917 } else {
918 // Probably a bad level. Drop through.
919 System.err.println("Can't set level for " + type);
920 }
921 }
922 // Add this Handler to the logger
923 logger.addHandler(hdl);
924 if (++count == 1) {
925 // add this logger to the persitentLoggers list.
926 persistentLoggers.addIfAbsent(
927 PersistentLogger.create(logger));
928 }
929 } catch (Exception ex) {
930 System.err.println("Can't load log handler \"" + type + "\"");
931 System.err.println("" + ex);
932 ex.printStackTrace();
933 }
934 }
935
936 return null;
937 }
938 });
939 }
940
941
942 // loggerRefQueue holds LoggerWeakRef objects for Logger objects
943 // that have been GC'ed.
944 private final ReferenceQueue<Logger> loggerRefQueue
945 = new ReferenceQueue<>();
946
947 // Package-level inner class.
948 // Helper class for managing WeakReferences to Logger objects.
949 //
950 // LogManager.namedLoggers
951 // - has weak references to all named Loggers
952 // - namedLoggers keeps the LoggerWeakRef objects for the named
953 // Loggers around until we can deal with the book keeping for
954 // the named Logger that is being GC'ed.
955 // LogManager.LogNode.loggerRef
1250 }
1251 try (final InputStream in = new FileInputStream(fname)) {
1252 final BufferedInputStream bin = new BufferedInputStream(in);
1253 readConfiguration(bin);
1254 }
1255 }
1256
1257 /**
1258 * Reset the logging configuration.
1259 * <p>
1260 * For all named loggers, the reset operation removes and closes
1261 * all Handlers and (except for the root logger) sets the level
1262 * to null. The root logger's level is set to Level.INFO.
1263 *
1264 * @exception SecurityException if a security manager exists and if
1265 * the caller does not have LoggingPermission("control").
1266 */
1267
1268 public void reset() throws SecurityException {
1269 checkPermission();
1270 List<PersistentLogger> persistent;
1271 synchronized (this) {
1272 props = new Properties();
1273 // make sure we keep the loggers persistent until reset is done.
1274 // Those are the loggers for which we previously created a
1275 // handler from the configuration, and we need to prevent them
1276 // from being gc'ed until those handlers are closed.
1277 persistent = new ArrayList<>(persistentLoggers);
1278 persistentLoggers.clear();
1279 // Since we are doing a reset we no longer want to initialize
1280 // the global handlers, if they haven't been initialized yet.
1281 initializedGlobalHandlers = true;
1282 }
1283 for (LoggerContext cx : contexts()) {
1284 Enumeration<String> enum_ = cx.getLoggerNames();
1285 while (enum_.hasMoreElements()) {
1286 String name = enum_.nextElement();
1287 Logger logger = cx.findLogger(name);
1288 if (logger != null) {
1289 resetLogger(logger);
1290 }
1291 }
1292 }
1293 persistent.clear();
1294 }
1295
1296 // Private method to reset an individual target logger.
1297 private void resetLogger(Logger logger) {
1298 // Close all the Logger's handlers.
1299 Handler[] targets = logger.getHandlers();
1300 for (Handler h : targets) {
1301 logger.removeHandler(h);
1302 try {
1303 h.close();
1304 } catch (Exception ex) {
1305 // Problems closing a handler? Keep going...
1306 }
1307 }
1308 String name = logger.getName();
1309 if (name != null && name.equals("")) {
1310 // This is the root logger.
1311 logger.setLevel(defaultLevel);
1312 } else {
1313 logger.setLevel(null);
|