1.1 --- a/rt/emul/compact/src/main/java/java/util/logging/Logger.java Sat Sep 07 13:55:09 2013 +0200
1.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/Logger.java Sat Sep 07 13:56:22 2013 +0200
1.3 @@ -26,10 +26,9 @@
1.4
1.5 package java.util.logging;
1.6
1.7 -import java.util.*;
1.8 -import java.util.concurrent.CopyOnWriteArrayList;
1.9 -import java.security.*;
1.10 -import java.lang.ref.WeakReference;
1.11 +import java.util.HashMap;
1.12 +import java.util.Map;
1.13 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.14
1.15 /**
1.16 * A Logger object is used to log messages for a specific
1.17 @@ -165,31 +164,13 @@
1.18
1.19
1.20 public class Logger {
1.21 - private static final Handler emptyHandlers[] = new Handler[0];
1.22 - private static final int offValue = Level.OFF.intValue();
1.23 - private LogManager manager;
1.24 + private static int offValue = Level.OFF.intValue();
1.25 + private static final Map<String,Logger> ALL = new HashMap<>();
1.26 private String name;
1.27 - private final CopyOnWriteArrayList<Handler> handlers =
1.28 - new CopyOnWriteArrayList<>();
1.29 - private String resourceBundleName;
1.30 - private volatile boolean useParentHandlers = true;
1.31 - private volatile Filter filter;
1.32 - private boolean anonymous;
1.33
1.34 - private ResourceBundle catalog; // Cached resource bundle
1.35 - private String catalogName; // name associated with catalog
1.36 - private Locale catalogLocale; // locale associated with catalog
1.37 -
1.38 - // The fields relating to parent-child relationships and levels
1.39 - // are managed under a separate lock, the treeLock.
1.40 - private static Object treeLock = new Object();
1.41 - // We keep weak references from parents to children, but strong
1.42 - // references from children to parents.
1.43 - private volatile Logger parent; // our nearest parent.
1.44 - private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent
1.45 - private volatile Level levelObject;
1.46 private volatile int levelValue; // current effective level value
1.47 -
1.48 + private Level levelObject;
1.49 +
1.50 /**
1.51 * GLOBAL_LOGGER_NAME is a name for the global logger.
1.52 *
1.53 @@ -249,11 +230,6 @@
1.54 * no corresponding resource can be found.
1.55 */
1.56 protected Logger(String name, String resourceBundleName) {
1.57 - this.manager = LogManager.getLogManager();
1.58 - if (resourceBundleName != null) {
1.59 - // Note: we may get a MissingResourceException here.
1.60 - setupResourceInfo(resourceBundleName);
1.61 - }
1.62 this.name = name;
1.63 levelValue = Level.INFO.intValue();
1.64 }
1.65 @@ -267,20 +243,8 @@
1.66 levelValue = Level.INFO.intValue();
1.67 }
1.68
1.69 - // It is called from the LogManager.<clinit> to complete
1.70 - // initialization of the global Logger.
1.71 - void setLogManager(LogManager manager) {
1.72 - this.manager = manager;
1.73 - }
1.74 -
1.75 private void checkAccess() throws SecurityException {
1.76 - if (!anonymous) {
1.77 - if (manager == null) {
1.78 - // Complete initialization of the global Logger.
1.79 - manager = LogManager.getLogManager();
1.80 - }
1.81 - manager.checkAccess();
1.82 - }
1.83 + throw new SecurityException();
1.84 }
1.85
1.86 /**
1.87 @@ -314,18 +278,7 @@
1.88 // Synchronization is not required here. All synchronization for
1.89 // adding a new Logger object is handled by LogManager.addLogger().
1.90 public static Logger getLogger(String name) {
1.91 - // This method is intentionally not a wrapper around a call
1.92 - // to getLogger(name, resourceBundleName). If it were then
1.93 - // this sequence:
1.94 - //
1.95 - // getLogger("Foo", "resourceBundleForFoo");
1.96 - // getLogger("Foo");
1.97 - //
1.98 - // would throw an IllegalArgumentException in the second call
1.99 - // because the wrapper would result in an attempt to replace
1.100 - // the existing "resourceBundleForFoo" with null.
1.101 - LogManager manager = LogManager.getLogManager();
1.102 - return manager.demandLogger(name);
1.103 + return getLogger(name, null);
1.104 }
1.105
1.106 /**
1.107 @@ -372,16 +325,12 @@
1.108 // Synchronization is not required here. All synchronization for
1.109 // adding a new Logger object is handled by LogManager.addLogger().
1.110 public static Logger getLogger(String name, String resourceBundleName) {
1.111 - LogManager manager = LogManager.getLogManager();
1.112 - Logger result = manager.demandLogger(name);
1.113 - if (result.resourceBundleName == null) {
1.114 - // Note: we may get a MissingResourceException here.
1.115 - result.setupResourceInfo(resourceBundleName);
1.116 - } else if (!result.resourceBundleName.equals(resourceBundleName)) {
1.117 - throw new IllegalArgumentException(result.resourceBundleName +
1.118 - " != " + resourceBundleName);
1.119 + Logger l = ALL.get(name);
1.120 + if (l == null) {
1.121 + l = new Logger(name, resourceBundleName);
1.122 + ALL.put(name, l);
1.123 }
1.124 - return result;
1.125 + return l;
1.126 }
1.127
1.128
1.129 @@ -437,14 +386,7 @@
1.130 // Synchronization is not required here. All synchronization for
1.131 // adding a new anonymous Logger object is handled by doSetParent().
1.132 public static Logger getAnonymousLogger(String resourceBundleName) {
1.133 - LogManager manager = LogManager.getLogManager();
1.134 - // cleanup some Loggers that have been GC'ed
1.135 - manager.drainLoggerRefQueueBounded();
1.136 - Logger result = new Logger(null, resourceBundleName);
1.137 - result.anonymous = true;
1.138 - Logger root = manager.getLogger("");
1.139 - result.doSetParent(root);
1.140 - return result;
1.141 + return new Logger(null, resourceBundleName);
1.142 }
1.143
1.144 /**
1.145 @@ -455,9 +397,9 @@
1.146 *
1.147 * @return localization bundle (may be null)
1.148 */
1.149 - public ResourceBundle getResourceBundle() {
1.150 - return findResourceBundle(getResourceBundleName());
1.151 - }
1.152 +// public ResourceBundle getResourceBundle() {
1.153 +// return findResourceBundle(getResourceBundleName());
1.154 +// }
1.155
1.156 /**
1.157 * Retrieve the localization resource bundle name for this
1.158 @@ -467,7 +409,7 @@
1.159 * @return localization bundle name (may be null)
1.160 */
1.161 public String getResourceBundleName() {
1.162 - return resourceBundleName;
1.163 + return null;
1.164 }
1.165
1.166 /**
1.167 @@ -481,19 +423,18 @@
1.168 * @exception SecurityException if a security manager exists and if
1.169 * the caller does not have LoggingPermission("control").
1.170 */
1.171 - public void setFilter(Filter newFilter) throws SecurityException {
1.172 - checkAccess();
1.173 - filter = newFilter;
1.174 - }
1.175 +// public void setFilter(Filter newFilter) throws SecurityException {
1.176 +// checkAccess();
1.177 +// }
1.178
1.179 /**
1.180 * Get the current filter for this Logger.
1.181 *
1.182 * @return a filter object (may be null)
1.183 */
1.184 - public Filter getFilter() {
1.185 - return filter;
1.186 - }
1.187 +// public Filter getFilter() {
1.188 +// return filter;
1.189 +// }
1.190
1.191 /**
1.192 * Log a LogRecord.
1.193 @@ -505,41 +446,32 @@
1.194 * @param record the LogRecord to be published
1.195 */
1.196 public void log(LogRecord record) {
1.197 - if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
1.198 - return;
1.199 - }
1.200 - Filter theFilter = filter;
1.201 - if (theFilter != null && !theFilter.isLoggable(record)) {
1.202 + if (record.getLevel().intValue() < levelValue) {
1.203 return;
1.204 }
1.205
1.206 - // Post the LogRecord to all our Handlers, and then to
1.207 - // our parents' handlers, all the way up the tree.
1.208 -
1.209 - Logger logger = this;
1.210 - while (logger != null) {
1.211 - for (Handler handler : logger.getHandlers()) {
1.212 - handler.publish(record);
1.213 - }
1.214 -
1.215 - if (!logger.getUseParentHandlers()) {
1.216 - break;
1.217 - }
1.218 -
1.219 - logger = logger.getParent();
1.220 - }
1.221 + consoleLog(
1.222 + record.getLevel().toString(),
1.223 + record.getLoggerName(),
1.224 + record.getMessage()
1.225 + );
1.226 }
1.227 +
1.228 + @JavaScriptBody(args = { "method", "logger", "msg" }, body =
1.229 + "window.console[method]('[' + logger + ']: ' + msg);"
1.230 + )
1.231 + private static native void consoleLog(
1.232 + String method, String logger, String msg
1.233 + );
1.234
1.235 // private support method for logging.
1.236 // We fill in the logger name, resource bundle name, and
1.237 // resource bundle and then call "void log(LogRecord)".
1.238 private void doLog(LogRecord lr) {
1.239 + doLog(lr, lr.getResourceBundleName());
1.240 + }
1.241 + private void doLog(LogRecord lr, String bundleName) {
1.242 lr.setLoggerName(name);
1.243 - String ebname = getEffectiveResourceBundleName();
1.244 - if (ebname != null) {
1.245 - lr.setResourceBundleName(ebname);
1.246 - lr.setResourceBundle(findResourceBundle(ebname));
1.247 - }
1.248 log(lr);
1.249 }
1.250
1.251 @@ -748,17 +680,6 @@
1.252 // Start of convenience methods WITH className, methodName and bundle name.
1.253 //=========================================================================
1.254
1.255 - // Private support method for logging for "logrb" methods.
1.256 - // We fill in the logger name, resource bundle name, and
1.257 - // resource bundle and then call "void log(LogRecord)".
1.258 - private void doLog(LogRecord lr, String rbname) {
1.259 - lr.setLoggerName(name);
1.260 - if (rbname != null) {
1.261 - lr.setResourceBundleName(rbname);
1.262 - lr.setResourceBundle(findResourceBundle(rbname));
1.263 - }
1.264 - log(lr);
1.265 - }
1.266
1.267 /**
1.268 * Log a message, specifying source class, method, and resource bundle name
1.269 @@ -1168,11 +1089,8 @@
1.270 * the caller does not have LoggingPermission("control").
1.271 */
1.272 public void setLevel(Level newLevel) throws SecurityException {
1.273 - checkAccess();
1.274 - synchronized (treeLock) {
1.275 - levelObject = newLevel;
1.276 - updateEffectiveLevel();
1.277 - }
1.278 + levelValue = newLevel.intValue();
1.279 + levelObject = newLevel;
1.280 }
1.281
1.282 /**
1.283 @@ -1220,12 +1138,12 @@
1.284 * @exception SecurityException if a security manager exists and if
1.285 * the caller does not have LoggingPermission("control").
1.286 */
1.287 - public void addHandler(Handler handler) throws SecurityException {
1.288 - // Check for null handler
1.289 - handler.getClass();
1.290 - checkAccess();
1.291 - handlers.add(handler);
1.292 - }
1.293 +// public void addHandler(Handler handler) throws SecurityException {
1.294 +// // Check for null handler
1.295 +// handler.getClass();
1.296 +// checkAccess();
1.297 +// handlers.add(handler);
1.298 +// }
1.299
1.300 /**
1.301 * Remove a log Handler.
1.302 @@ -1236,22 +1154,22 @@
1.303 * @exception SecurityException if a security manager exists and if
1.304 * the caller does not have LoggingPermission("control").
1.305 */
1.306 - public void removeHandler(Handler handler) throws SecurityException {
1.307 - checkAccess();
1.308 - if (handler == null) {
1.309 - return;
1.310 - }
1.311 - handlers.remove(handler);
1.312 - }
1.313 +// public void removeHandler(Handler handler) throws SecurityException {
1.314 +// checkAccess();
1.315 +// if (handler == null) {
1.316 +// return;
1.317 +// }
1.318 +// handlers.remove(handler);
1.319 +// }
1.320
1.321 /**
1.322 * Get the Handlers associated with this logger.
1.323 * <p>
1.324 * @return an array of all registered Handlers
1.325 */
1.326 - public Handler[] getHandlers() {
1.327 - return handlers.toArray(emptyHandlers);
1.328 - }
1.329 +// public Handler[] getHandlers() {
1.330 +// return handlers.toArray(emptyHandlers);
1.331 +// }
1.332
1.333 /**
1.334 * Specify whether or not this logger should send its output
1.335 @@ -1266,7 +1184,6 @@
1.336 */
1.337 public void setUseParentHandlers(boolean useParentHandlers) {
1.338 checkAccess();
1.339 - this.useParentHandlers = useParentHandlers;
1.340 }
1.341
1.342 /**
1.343 @@ -1276,97 +1193,7 @@
1.344 * @return true if output is to be sent to the logger's parent
1.345 */
1.346 public boolean getUseParentHandlers() {
1.347 - return useParentHandlers;
1.348 - }
1.349 -
1.350 - // Private utility method to map a resource bundle name to an
1.351 - // actual resource bundle, using a simple one-entry cache.
1.352 - // Returns null for a null name.
1.353 - // May also return null if we can't find the resource bundle and
1.354 - // there is no suitable previous cached value.
1.355 -
1.356 - private synchronized ResourceBundle findResourceBundle(String name) {
1.357 - // Return a null bundle for a null name.
1.358 - if (name == null) {
1.359 - return null;
1.360 - }
1.361 -
1.362 - Locale currentLocale = Locale.getDefault();
1.363 -
1.364 - // Normally we should hit on our simple one entry cache.
1.365 - if (catalog != null && currentLocale == catalogLocale
1.366 - && name == catalogName) {
1.367 - return catalog;
1.368 - }
1.369 -
1.370 - // Use the thread's context ClassLoader. If there isn't one,
1.371 - // use the SystemClassloader.
1.372 - ClassLoader cl = Thread.currentThread().getContextClassLoader();
1.373 - if (cl == null) {
1.374 - cl = ClassLoader.getSystemClassLoader();
1.375 - }
1.376 - try {
1.377 - catalog = ResourceBundle.getBundle(name, currentLocale, cl);
1.378 - catalogName = name;
1.379 - catalogLocale = currentLocale;
1.380 - return catalog;
1.381 - } catch (MissingResourceException ex) {
1.382 - // Woops. We can't find the ResourceBundle in the default
1.383 - // ClassLoader. Drop through.
1.384 - }
1.385 -
1.386 -
1.387 - // Fall back to searching up the call stack and trying each
1.388 - // calling ClassLoader.
1.389 - for (int ix = 0; ; ix++) {
1.390 - Class clz = sun.reflect.Reflection.getCallerClass(ix);
1.391 - if (clz == null) {
1.392 - break;
1.393 - }
1.394 - ClassLoader cl2 = clz.getClassLoader();
1.395 - if (cl2 == null) {
1.396 - cl2 = ClassLoader.getSystemClassLoader();
1.397 - }
1.398 - if (cl == cl2) {
1.399 - // We've already checked this classloader.
1.400 - continue;
1.401 - }
1.402 - cl = cl2;
1.403 - try {
1.404 - catalog = ResourceBundle.getBundle(name, currentLocale, cl);
1.405 - catalogName = name;
1.406 - catalogLocale = currentLocale;
1.407 - return catalog;
1.408 - } catch (MissingResourceException ex) {
1.409 - // Ok, this one didn't work either.
1.410 - // Drop through, and try the next one.
1.411 - }
1.412 - }
1.413 -
1.414 - if (name.equals(catalogName)) {
1.415 - // Return the previous cached value for that name.
1.416 - // This may be null.
1.417 - return catalog;
1.418 - }
1.419 - // Sorry, we're out of luck.
1.420 - return null;
1.421 - }
1.422 -
1.423 - // Private utility method to initialize our one entry
1.424 - // resource bundle cache.
1.425 - // Note: for consistency reasons, we are careful to check
1.426 - // that a suitable ResourceBundle exists before setting the
1.427 - // ResourceBundleName.
1.428 - private synchronized void setupResourceInfo(String name) {
1.429 - if (name == null) {
1.430 - return;
1.431 - }
1.432 - ResourceBundle rb = findResourceBundle(name);
1.433 - if (rb == null) {
1.434 - // We've failed to find an expected ResourceBundle.
1.435 - throw new MissingResourceException("Can't find " + name + " bundle", name, "");
1.436 - }
1.437 - resourceBundleName = name;
1.438 + return true;
1.439 }
1.440
1.441 /**
1.442 @@ -1388,7 +1215,19 @@
1.443 // would synchronize on treeLock (in fact, there is no way for external
1.444 // callers to so synchronize). Therefore, we have made parent volatile
1.445 // instead.
1.446 - return parent;
1.447 + String n = getName();
1.448 + int at = n.length();
1.449 + for (;;) {
1.450 + int last = n.lastIndexOf('.', at - 1);
1.451 + if (last == -1) {
1.452 + return getGlobal();
1.453 + }
1.454 + Logger p = ALL.get(n.substring(0, last));
1.455 + if (p != null) {
1.456 + return p;
1.457 + }
1.458 + at = last;
1.459 + }
1.460 }
1.461
1.462 /**
1.463 @@ -1405,126 +1244,7 @@
1.464 if (parent == null) {
1.465 throw new NullPointerException();
1.466 }
1.467 - manager.checkAccess();
1.468 - doSetParent(parent);
1.469 + checkAccess();
1.470 }
1.471
1.472 - // Private method to do the work for parenting a child
1.473 - // Logger onto a parent logger.
1.474 - private void doSetParent(Logger newParent) {
1.475 -
1.476 - // System.err.println("doSetParent \"" + getName() + "\" \""
1.477 - // + newParent.getName() + "\"");
1.478 -
1.479 - synchronized (treeLock) {
1.480 -
1.481 - // Remove ourself from any previous parent.
1.482 - LogManager.LoggerWeakRef ref = null;
1.483 - if (parent != null) {
1.484 - // assert parent.kids != null;
1.485 - for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
1.486 - ref = iter.next();
1.487 - Logger kid = ref.get();
1.488 - if (kid == this) {
1.489 - // ref is used down below to complete the reparenting
1.490 - iter.remove();
1.491 - break;
1.492 - } else {
1.493 - ref = null;
1.494 - }
1.495 - }
1.496 - // We have now removed ourself from our parents' kids.
1.497 - }
1.498 -
1.499 - // Set our new parent.
1.500 - parent = newParent;
1.501 - if (parent.kids == null) {
1.502 - parent.kids = new ArrayList<>(2);
1.503 - }
1.504 - if (ref == null) {
1.505 - // we didn't have a previous parent
1.506 - ref = manager.new LoggerWeakRef(this);
1.507 - }
1.508 - ref.setParentRef(new WeakReference<Logger>(parent));
1.509 - parent.kids.add(ref);
1.510 -
1.511 - // As a result of the reparenting, the effective level
1.512 - // may have changed for us and our children.
1.513 - updateEffectiveLevel();
1.514 -
1.515 - }
1.516 - }
1.517 -
1.518 - // Package-level method.
1.519 - // Remove the weak reference for the specified child Logger from the
1.520 - // kid list. We should only be called from LoggerWeakRef.dispose().
1.521 - final void removeChildLogger(LogManager.LoggerWeakRef child) {
1.522 - synchronized (treeLock) {
1.523 - for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
1.524 - LogManager.LoggerWeakRef ref = iter.next();
1.525 - if (ref == child) {
1.526 - iter.remove();
1.527 - return;
1.528 - }
1.529 - }
1.530 - }
1.531 - }
1.532 -
1.533 - // Recalculate the effective level for this node and
1.534 - // recursively for our children.
1.535 -
1.536 - private void updateEffectiveLevel() {
1.537 - // assert Thread.holdsLock(treeLock);
1.538 -
1.539 - // Figure out our current effective level.
1.540 - int newLevelValue;
1.541 - if (levelObject != null) {
1.542 - newLevelValue = levelObject.intValue();
1.543 - } else {
1.544 - if (parent != null) {
1.545 - newLevelValue = parent.levelValue;
1.546 - } else {
1.547 - // This may happen during initialization.
1.548 - newLevelValue = Level.INFO.intValue();
1.549 - }
1.550 - }
1.551 -
1.552 - // If our effective value hasn't changed, we're done.
1.553 - if (levelValue == newLevelValue) {
1.554 - return;
1.555 - }
1.556 -
1.557 - levelValue = newLevelValue;
1.558 -
1.559 - // System.err.println("effective level: \"" + getName() + "\" := " + level);
1.560 -
1.561 - // Recursively update the level on each of our kids.
1.562 - if (kids != null) {
1.563 - for (int i = 0; i < kids.size(); i++) {
1.564 - LogManager.LoggerWeakRef ref = kids.get(i);
1.565 - Logger kid = ref.get();
1.566 - if (kid != null) {
1.567 - kid.updateEffectiveLevel();
1.568 - }
1.569 - }
1.570 - }
1.571 - }
1.572 -
1.573 -
1.574 - // Private method to get the potentially inherited
1.575 - // resource bundle name for this Logger.
1.576 - // May return null
1.577 - private String getEffectiveResourceBundleName() {
1.578 - Logger target = this;
1.579 - while (target != null) {
1.580 - String rbn = target.getResourceBundleName();
1.581 - if (rbn != null) {
1.582 - return rbn;
1.583 - }
1.584 - target = target.getParent();
1.585 - }
1.586 - return null;
1.587 - }
1.588 -
1.589 -
1.590 }