0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package java.util.logging;
0019:
0020: import java.security.AccessController;
0021: import java.security.PrivilegedAction;
0022: import java.util.ArrayList;
0023: import java.util.List;
0024: import java.util.Locale;
0025: import java.util.MissingResourceException;
0026: import java.util.ResourceBundle;
0027:
0028: import org.apache.harmony.logging.internal.nls.Messages;
0029:
0030: /**
0031: * Loggers are used to log records to certain outputs, including file, console,
0032: * etc. They use various handlers to actually do the output-dependent
0033: * operations.
0034: * <p>
0035: * Client applications can get named loggers by calling the methods
0036: * <code>getLogger</code>. They can also get anonymous loggers by calling the
0037: * methods <code>getAnonymousLogger</code>. Named loggers are organized in a
0038: * namespace hierarchy managed by a log manager. The naming convention is
0039: * usually the same as java package's naming convention, i.e., using
0040: * dot-separated strings. Anonymous loggers do not belong to any namespace.
0041: * </p>
0042: * <p>
0043: * Loggers "inherit" log level setting from their parent if its own level is set
0044: * to <code>null</code>. This is also true for the resource bundle. The
0045: * logger's resource bundle is used to localize the log messages if no resource
0046: * bundle name is given when a log method is called. If
0047: * <code>getUseParentHandlers</code> is <code>true</code>, loggers also
0048: * inherit their parent's handlers. Here "inherit" only means the "behaviors"
0049: * are inherited. The internal fields value will not change, for example,
0050: * <code>getLevel()</code> still returns <code>null</code>.
0051: * </p>
0052: * <p>
0053: * When loading a given resource bundle, the logger first tries to use the
0054: * context classloader. If that fails, it tries the system classloader. And if
0055: * that still fails, it searches up the class stack and uses each class's
0056: * classloader to try to locate the resource bundle.
0057: * </p>
0058: * <p>
0059: * Some log methods accept log requests that do not specify the source class and
0060: * source method. In these cases, the logging framework will automatically infer
0061: * the calling class and method, but not guaranteed to be accurate.
0062: * </p>
0063: * <p>
0064: * Once a <code>LogRecord</code> object has been passed into the logging
0065: * framework, it is owned by the logging framework and the client applications
0066: * should not use it any longer.
0067: * </p>
0068: * <p>
0069: * All methods of this class are thread-safe.
0070: * </p>
0071: *
0072: * @see LogManager
0073: */
0074: public class Logger {
0075:
0076: /**
0077: * The global logger is provided as convenience for casual use.
0078: */
0079: public final static Logger global = new Logger("global", null); //$NON-NLS-1$
0080:
0081: // the name of this logger
0082: private volatile String name;
0083:
0084: // the parent logger of this logger
0085: private Logger parent;
0086:
0087: // the logging level of this logger
0088: private volatile Level levelObjVal;
0089:
0090: // the logging level as int of this logger
0091: private volatile int levelIntVal;
0092:
0093: // the filter
0094: private Filter filter;
0095:
0096: // the name of the resource bundle used to localize logging messages
0097: private String resBundleName;
0098:
0099: // the loaded resource bundle according to the specified name
0100: private ResourceBundle resBundle;
0101:
0102: // the handlers attached to this logger
0103: private List<Handler> handlers;
0104:
0105: /*
0106: * flag indicating whether to notify parent's handlers on receiving a log
0107: * request
0108: */
0109: private boolean notifyParentHandlers;
0110:
0111: // flag indicating whether this logger is named or anonymous
0112: private boolean isNamed;
0113:
0114: private List<Logger> childs;
0115:
0116: private LogManager manager;
0117:
0118: private boolean handlerInited;
0119:
0120: /**
0121: * Constructs a <code>Logger</code> object with the supplied name and
0122: * resource bundle name.
0123: *
0124: * @param name
0125: * the name of this logger, may be null for anonymous loggers
0126: * @param resourceBundleName
0127: * the name of the resource bundle used to localize logging
0128: * messages, may be null
0129: * @throws MissingResourceException
0130: * If the specified resource bundle can not be loaded.
0131: */
0132: protected Logger(String name, String resourceBundleName) {
0133: // try to load the specified resource bundle first
0134: if (null == resourceBundleName) {
0135: this .resBundleName = null;
0136: this .resBundle = null;
0137: } else {
0138: this .resBundle = loadResourceBundle(resourceBundleName);
0139: this .resBundleName = resourceBundleName;
0140: }
0141: this .name = name;
0142: this .parent = null;
0143: this .filter = null;
0144: this .childs = new ArrayList<Logger>();
0145: this .notifyParentHandlers = true;
0146: // any logger is not anonymous by default
0147: this .isNamed = true;
0148:
0149: // -- 'null' means that level will be inherited from parent (see
0150: // getLevel)
0151: // -- Level.INFO is default level if we don't set it. It will be
0152: // -- changed to parent level or to configLevel after adding to the
0153: // -- family tree. As of this, actually, setting to Level.INFO is
0154: // -- not needed here.
0155: this .levelObjVal = null;
0156: this .levelIntVal = Level.INFO.intValue();
0157: }
0158:
0159: // -- should be called under the lm lock
0160: private void setLevelImpl(Level newLevel) {
0161: // update levels for the whole hierarchy
0162: int oldVal = levelIntVal;
0163: levelObjVal = newLevel;
0164: if (null == newLevel) {
0165: levelIntVal = null != parent ? parent.levelIntVal
0166: : Level.INFO.intValue();
0167: } else {
0168: levelIntVal = newLevel.intValue();
0169: }
0170: if (oldVal != levelIntVal) {
0171: forceChildsToInherit();
0172: }
0173: }
0174:
0175: // -- should be called under the lm lock
0176: private void forceChildsToInherit() {
0177: for (Logger child : childs) {
0178: if (null == child.levelObjVal) { // should inherit
0179: child.setLevelImpl(null);
0180: }
0181: }
0182: }
0183:
0184: /**
0185: * Load the specified resource bundle, use privileged code.
0186: *
0187: * @param resourceBundleName
0188: * the name of the resource bundle to load, cannot be null
0189: * @return the loaded resource bundle.
0190: * @throws MissingResourceException
0191: * If the specified resource bundle can not be loaded.
0192: */
0193: static ResourceBundle loadResourceBundle(String resourceBundleName) {
0194: // try context class loader to load the resource
0195: ClassLoader cl = AccessController
0196: .doPrivileged(new PrivilegedAction<ClassLoader>() {
0197: public ClassLoader run() {
0198: return Thread.currentThread()
0199: .getContextClassLoader();
0200: }
0201: });
0202: if (null != cl) {
0203: try {
0204: return ResourceBundle.getBundle(resourceBundleName,
0205: Locale.getDefault(), cl);
0206: } catch (MissingResourceException e) {
0207: // Failed to load using context classloader, ignore
0208: }
0209: }
0210: // try system class loader to load the resource
0211: cl = AccessController
0212: .doPrivileged(new PrivilegedAction<ClassLoader>() {
0213: public ClassLoader run() {
0214: return ClassLoader.getSystemClassLoader();
0215: }
0216: });
0217: if (null != cl) {
0218: try {
0219: return ResourceBundle.getBundle(resourceBundleName,
0220: Locale.getDefault(), cl);
0221: } catch (MissingResourceException e) {
0222: // Failed to load using system classloader, ignore
0223: }
0224: }
0225: // try all class loaders up the class stack
0226: final Class<?>[] classes = AccessController
0227: .doPrivileged(new PrivilegedAction<Class<?>[]>() {
0228: public Class<?>[] run() {
0229: return (new PrivateSecurityManager())
0230: .privateGetClassContext();
0231: }
0232: });
0233: // the first class, which is PrivateSecurityManager, is skipped
0234: for (int i = 1; i < classes.length; i++) {
0235: final int index = i;
0236: try {
0237: cl = AccessController
0238: .doPrivileged(new PrivilegedAction<ClassLoader>() {
0239: public ClassLoader run() {
0240: return classes[index].getClassLoader();
0241: }
0242: });
0243: if (null == cl) {
0244: continue;
0245: }
0246: return ResourceBundle.getBundle(resourceBundleName,
0247: Locale.getDefault(), cl);
0248: } catch (MissingResourceException e) {
0249: // Failed to load using the current class's classloader, ignore
0250: }
0251: }
0252: // logging.8=Failed to load the specified resource bundle "{0}".
0253: throw new MissingResourceException(Messages.getString(
0254: "logging.8", //$NON-NLS-1$
0255: resourceBundleName), resourceBundleName, null);
0256: }
0257:
0258: /**
0259: * Gets an anonymous logger to use internally in a thread. Anonymous loggers
0260: * are not registered in the log manager's namespace. No security checks
0261: * will be performed when updating an anonymous logger's control settings so
0262: * that they can be used in applets.
0263: * <p>
0264: * Anonymous loggers' parent is set to be the root logger. This enables them
0265: * to inherit default logging level and handlers from the root logger.
0266: * </p>
0267: *
0268: * @return a new instance of anonymous logger
0269: */
0270: public static Logger getAnonymousLogger() {
0271: return getAnonymousLogger(null);
0272: }
0273:
0274: /**
0275: * Gets an anonymous logger to use internally in a thread. Anonymous loggers
0276: * are not registered in the log manager's namespace. No security checks
0277: * will be performed when updating an anonymous logger's control settings so
0278: * that they can be used in applets.
0279: * <p>
0280: * Anonymous loggers' parent is set to be the root logger. This enables them
0281: * to inherit default logging level and handlers from the root logger.
0282: * </p>
0283: *
0284: * @param resourceBundleName
0285: * the name of the resource bundle used to localize log messages
0286: * @return a new instance of anonymous logger
0287: * @throws MissingResourceException
0288: * If the specified resource bundle can not be loaded.
0289: */
0290: public static Logger getAnonymousLogger(String resourceBundleName) {
0291: final Logger l = new Logger(null, resourceBundleName);
0292: l.isNamed = false;
0293: l.internalSetParent(LogManager.getLogManager().getLogger("")); //$NON-NLS-1$
0294: return l;
0295: }
0296:
0297: /*
0298: * Check whether the same resource bundle has been specified. Synchronize to
0299: * ensure the consistency between resource bundle and its name.
0300: */
0301: private static void updateResourceBundle(Logger l,
0302: String resourceBundleName) {
0303: synchronized (l) {
0304: if (null == l.getResourceBundleName()) {
0305: if (null == resourceBundleName) {
0306: return;
0307: }
0308: /*
0309: * load the resource bundle if none is specified before
0310: */
0311: l.resBundle = loadResourceBundle(resourceBundleName);
0312: l.resBundleName = resourceBundleName;
0313: } else if (!l.getResourceBundleName().equals(
0314: resourceBundleName)) {
0315: /*
0316: * throw exception if the specified resource bundles are
0317: * inconsistent with each other, i.e., different names
0318: */
0319: // logging.9=The specified resource bundle name "{0}" is
0320: // inconsistent with the existing one "{1}".
0321: throw new IllegalArgumentException(Messages.getString(
0322: "logging.9", //$NON-NLS-1$
0323: resourceBundleName, l.getResourceBundleName()));
0324: }
0325: }
0326: }
0327:
0328: /*
0329: * Gets a named logger associated with the supplied resource bundle. This
0330: * method accepts null resource bundle name. The method body is synchronized
0331: * on the instance of the LogManager to insure the consistency of the whole
0332: * operation.
0333: */
0334: private static Logger getLoggerWithRes(String name,
0335: String resourceBundleName, boolean hasResourceName) {
0336: LogManager man = LogManager.getLogManager();
0337: Logger l = null;
0338: synchronized (man) {
0339: // Try to find an existing logger with the specified name
0340: l = man.getLogger(name);
0341: // If no existing logger with the same name, create a new one
0342: if (null == l) {
0343: l = new Logger(name, resourceBundleName);
0344: man.addLogger(l);
0345: return l;
0346: }
0347: }
0348: if (hasResourceName) {
0349: updateResourceBundle(l, resourceBundleName);
0350: }
0351: return l;
0352: }
0353:
0354: /**
0355: * Gets a named logger. The returned logger may already exist, or may be
0356: * newly created. If the latter, its level will be set to the configured
0357: * level according to the <code>LogManager</code>'s properties if any.
0358: *
0359: * @param name
0360: * the name of the logger to get, cannot be null
0361: * @return a named logger
0362: * @throws MissingResourceException
0363: * If the specified resource bundle can not be loaded.
0364: */
0365: public static Logger getLogger(String name) {
0366: return getLoggerWithRes(name, null, false);
0367: }
0368:
0369: /**
0370: * Gets a named logger associated with the supplied resource bundle. The
0371: * resource bundle will be used to localize logging messages.
0372: *
0373: * @param name
0374: * the name of the logger to get, cannot be null
0375: * @param resourceBundleName
0376: * the name of the resource bundle, may be null
0377: * @return a named logger
0378: */
0379: public static Logger getLogger(String name,
0380: String resourceBundleName) {
0381: return getLoggerWithRes(name, resourceBundleName, true);
0382: }
0383:
0384: /**
0385: * Adds a handler to this logger. The handler will be fed with log records
0386: * received by this logger.
0387: *
0388: * @param handler
0389: * the handler object to add, cannot be null
0390: * @throws SecurityException
0391: * If a security manager determines that the caller does not
0392: * have the required permission.
0393: */
0394: public void addHandler(Handler handler) {
0395: if (null == handler) {
0396: // logging.A=The 'handler' parameter is null.
0397: throw new NullPointerException(Messages
0398: .getString("logging.A")); //$NON-NLS-1$
0399: }
0400: // Anonymous loggers can always add handlers
0401: if (this .isNamed) {
0402: LogManager.getLogManager().checkAccess();
0403: }
0404: initHandler();
0405: synchronized (this ) {
0406: this .handlers.add(handler);
0407: }
0408: }
0409:
0410: /*
0411: * Be cautious to avoid deadlock when using this method, it gets lock on
0412: * manager at first, and then gets lock on this Logger, so any methods
0413: * should not hold lock on this Logger when invoking this method.
0414: */
0415: private void initHandler() {
0416: if (!handlerInited) {
0417: synchronized (this ) {
0418: if (!handlerInited) {
0419: if (handlers == null) {
0420: handlers = new ArrayList<Handler>();
0421: }
0422: if (manager == null) {
0423: return;
0424: }
0425:
0426: String handlerStr = manager
0427: .getProperty("".equals(name) ? "handlers" : name + ".handlers"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0428: if (null == handlerStr) {
0429: return;
0430: }
0431: String[] strs = handlerStr.split(",|\\s"); //$NON-NLS-1$
0432: for (int i = 0; i < strs.length; i++) {
0433: String handlerName = strs[i];
0434: if (handlerName.equals("")) { //$NON-NLS-1$
0435: continue;
0436: }
0437: Handler handler = (Handler) LogManager
0438: .getInstanceByClass(handlerName);
0439: handlers.add(handler);
0440: String level = manager.getProperty(handlerName
0441: + ".level"); //$NON-NLS-1$
0442: if (null != level) {
0443: handler.setLevel(Level.parse(level));
0444: }
0445: }
0446: handlerInited = true;
0447: }
0448: }
0449: }
0450: }
0451:
0452: /**
0453: * Gets all the handlers associated with this logger.
0454: *
0455: * @return an array of all the handlers associated with this logger
0456: */
0457: public Handler[] getHandlers() {
0458: initHandler();
0459: synchronized (this ) {
0460: return handlers.toArray(new Handler[handlers.size()]);
0461: }
0462: }
0463:
0464: /**
0465: * Removes a handler for this logger. If the specified handler does not
0466: * exist, this method has no effect.
0467: *
0468: * @param handler
0469: * the handler to be removed, cannot be null
0470: * @throws SecurityException
0471: * If a security manager determines that the caller does not
0472: * have the required permission.
0473: */
0474: public void removeHandler(Handler handler) {
0475: // Anonymous loggers can always remove handlers
0476: if (this .isNamed) {
0477: LogManager.getLogManager().checkAccess();
0478: }
0479: if (null == handler) {
0480: return;
0481: }
0482: initHandler();
0483: synchronized (this ) {
0484: this .handlers.remove(handler);
0485: }
0486: }
0487:
0488: /**
0489: * Gets the filter used by this logger.
0490: *
0491: * @return the filter used by this logger
0492: */
0493: public Filter getFilter() {
0494: return this .filter;
0495: }
0496:
0497: /**
0498: * Sets the filter used by this logger.
0499: *
0500: * @param newFilter
0501: * the filter to set
0502: * @throws SecurityException
0503: * If a security manager determines that the caller does not
0504: * have the required permission.
0505: */
0506: public void setFilter(Filter newFilter) {
0507: // Anonymous loggers can always set the filter
0508: if (this .isNamed) {
0509: LogManager.getLogManager().checkAccess();
0510: }
0511: filter = newFilter;
0512: }
0513:
0514: /**
0515: * Gets the logging level of this logger.
0516: *
0517: * @return the logging level of this logger
0518: */
0519: public Level getLevel() {
0520: return levelObjVal;
0521: }
0522:
0523: /**
0524: * Sets the logging level for this logger. A <code>null</code> level
0525: * indicates this logger will inherit its parent's level.
0526: *
0527: * @param newLevel
0528: * the logging level to set
0529: * @throws SecurityException
0530: * If a security manager determines that the caller does not
0531: * have the required permission.
0532: */
0533: public void setLevel(Level newLevel) {
0534: // Anonymous loggers can always set the level
0535: if (this .isNamed) {
0536: LogManager.getLogManager().checkAccess();
0537: }
0538: synchronized (LogManager.getLogManager()) {
0539: setLevelImpl(newLevel);
0540: }
0541: }
0542:
0543: /**
0544: * Gets the flag which indicates whether to use parent's handlers to publish
0545: * incoming log records, potentially recursively up the namespace.
0546: *
0547: * @return <code>true</code> if set to use parent's handlers, otherwise
0548: * <code>false</code>
0549: */
0550: public boolean getUseParentHandlers() {
0551: return this .notifyParentHandlers;
0552: }
0553:
0554: /**
0555: * Sets the flag which indicates whether to use parent's handlers to publish
0556: * incoming log records, potentially recursively up the namespace.
0557: *
0558: * @param notifyParentHandlers
0559: * the flag whether to use parent's handlers
0560: * @throws SecurityException
0561: * If a security manager determines that the caller does not
0562: * have the required permission.
0563: */
0564: public void setUseParentHandlers(boolean notifyParentHandlers) {
0565: // Anonymous loggers can always set the useParentHandlers flag
0566: if (this .isNamed) {
0567: LogManager.getLogManager().checkAccess();
0568: }
0569: this .notifyParentHandlers = notifyParentHandlers;
0570: }
0571:
0572: /**
0573: * Gets the parent of this logger in the namespace.
0574: *
0575: * @return the parent of this logger in the namespace
0576: */
0577: public Logger getParent() {
0578: return parent;
0579: }
0580:
0581: /**
0582: * Sets the parent of this logger in the namespace. This method should
0583: * usually be used by the <code>LogManager</code> object only. This method
0584: * does not check security.
0585: *
0586: * @param newParent
0587: * the parent logger to set
0588: */
0589: void internalSetParent(Logger newParent) {
0590: // All hierarchy related modifications should get LogManager lock at
0591: // first
0592: synchronized (LogManager.getLogManager()) {
0593: parent = newParent;
0594: // -- update level after setting a parent.
0595: // -- if level == null we should inherit the parent's level
0596: if (null == levelObjVal) {
0597: setLevelImpl(levelObjVal);
0598: }
0599: newParent.addChild(this );
0600: }
0601: }
0602:
0603: /**
0604: * Sets the parent of this logger in the namespace. This method should
0605: * usually be used by the <code>LogManager</code> object only.
0606: *
0607: * @param parent
0608: * the parent logger to set
0609: * @throws SecurityException
0610: * If a security manager determines that the caller does not
0611: * have the required permission.
0612: */
0613: public void setParent(Logger parent) {
0614: if (null == parent) {
0615: // logging.B=The 'parent' parameter is null.
0616: throw new NullPointerException(Messages
0617: .getString("logging.B")); //$NON-NLS-1$
0618: }
0619: // even anonymous loggers are checked
0620: LogManager.getLogManager().checkAccess();
0621: internalSetParent(parent);
0622: }
0623:
0624: final void addChild(Logger logger) {
0625: childs.add(logger);
0626: }
0627:
0628: final void removeChild(Logger child) {
0629: childs.remove(child);
0630: }
0631:
0632: /**
0633: * Gets the name of this logger.
0634: *
0635: * @return the name of this logger
0636: */
0637: public String getName() {
0638: return this .name;
0639: }
0640:
0641: /**
0642: * Gets the loaded resource bundle used by this logger to localize logging
0643: * messages. If it's null, the parent's resource bundle will be inherited.
0644: *
0645: * @return the loaded resource bundle used by this logger
0646: */
0647: public ResourceBundle getResourceBundle() {
0648: return this .resBundle;
0649: }
0650:
0651: /**
0652: * Gets the name of the loaded resource bundle used by this logger to
0653: * localize logging messages. If it's null, the parent's resource bundle
0654: * name will be inherited.
0655: *
0656: * @return the name of the loaded resource bundle used by this logger
0657: */
0658: public String getResourceBundleName() {
0659: return this .resBundleName;
0660: }
0661:
0662: /**
0663: * This method is for compatibility. Tests written to the reference
0664: * implementation API imply that the isLoggable() method is not called
0665: * directly. This behavior is important because subclass may override
0666: * isLoggable() method, so that affect the result of log methods.
0667: */
0668: private boolean internalIsLoggable(Level l) {
0669: int effectiveLevel = levelIntVal;
0670: if (effectiveLevel == Level.OFF.intValue()) {
0671: // always return false if the effective level is off
0672: return false;
0673: }
0674: return l.intValue() >= effectiveLevel;
0675: }
0676:
0677: /**
0678: * Determines whether this logger will actually log messages of the
0679: * specified level. The effective level used to do the determination may be
0680: * inherited from its parent. The default level is <code>Level.INFO</code>.
0681: *
0682: * @param l
0683: * the level to check
0684: * @return <code>true</code> if this logger will actually log this level,
0685: * otherwise <code>false</code>
0686: */
0687: public boolean isLoggable(Level l) {
0688: return internalIsLoggable(l);
0689: }
0690:
0691: /*
0692: * Sets the resource bundle and its name for a supplied LogRecord object.
0693: * This method first tries to use this logger's resource bundle if any,
0694: * otherwise try to inherit from this logger's parent, recursively up the
0695: * namespace. Synchronize to ensure the consistency between resource bundle
0696: * and its name.
0697: */
0698: private void setResourceBundle(LogRecord record) {
0699: if (null != this .resBundleName) {
0700: record.setResourceBundle(this .resBundle);
0701: record.setResourceBundleName(this .resBundleName);
0702: } else {
0703: Logger anyParent = this .parent;
0704: // no need to synchronize here, because if resBundleName
0705: // is not null, there is no chance to modify it
0706: while (null != anyParent) {
0707: if (null != anyParent.resBundleName) {
0708: record.setResourceBundle(anyParent.resBundle);
0709: record
0710: .setResourceBundleName(anyParent.resBundleName);
0711: return;
0712: }
0713: anyParent = anyParent.parent;
0714: }
0715: }
0716: }
0717:
0718: /**
0719: * Logs a message indicating entering a method. A log record with log level
0720: * <code>Level.FINER</code>, log message "ENTRY", and the specified
0721: * source class name and source method name is submitted for logging.
0722: *
0723: * @param sourceClass
0724: * the calling class name
0725: * @param sourceMethod
0726: * the method name
0727: */
0728: public void entering(String sourceClass, String sourceMethod) {
0729: if (internalIsLoggable(Level.FINER)) {
0730: LogRecord record = new LogRecord(Level.FINER, "ENTRY"); //$NON-NLS-1$
0731: record.setLoggerName(this .name);
0732: record.setSourceClassName(sourceClass);
0733: record.setSourceMethodName(sourceMethod);
0734: setResourceBundle(record);
0735: log(record);
0736: }
0737: }
0738:
0739: /**
0740: * Logs a message indicating entering a method. A log record with log level
0741: * <code>Level.FINER</code>, log message "ENTRY", and the specified
0742: * source class name and source method name and one parameter is submitted
0743: * for logging.
0744: *
0745: * @param sourceClass
0746: * the source class name
0747: * @param sourceMethod
0748: * the source method name
0749: * @param param
0750: * the parameter for the method call
0751: */
0752: public void entering(String sourceClass, String sourceMethod,
0753: Object param) {
0754: if (internalIsLoggable(Level.FINER)) {
0755: LogRecord record = new LogRecord(Level.FINER,
0756: "ENTRY" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
0757: record.setLoggerName(this .name);
0758: record.setSourceClassName(sourceClass);
0759: record.setSourceMethodName(sourceMethod);
0760: record.setParameters(new Object[] { param });
0761: setResourceBundle(record);
0762: log(record);
0763: }
0764: }
0765:
0766: /**
0767: * Logs a message indicating entering a method. A log record with log level
0768: * <code>Level.FINER</code>, log message "ENTRY", and the specified
0769: * source class name and source method name and parameters is submitted for
0770: * logging.
0771: *
0772: * @param sourceClass
0773: * the source class name
0774: * @param sourceMethod
0775: * the source method name
0776: * @param params
0777: * an array of parameters for the method call
0778: */
0779: public void entering(String sourceClass, String sourceMethod,
0780: Object[] params) {
0781: if (internalIsLoggable(Level.FINER)) {
0782: String msg = "ENTRY"; //$NON-NLS-1$
0783: if (null != params) {
0784: StringBuilder msgBuffer = new StringBuilder("ENTRY"); //$NON-NLS-1$
0785: for (int i = 0; i < params.length; i++) {
0786: msgBuffer.append(" {" + i + "}"); //$NON-NLS-1$ //$NON-NLS-2$
0787: }
0788: msg = msgBuffer.toString();
0789: }
0790: LogRecord record = new LogRecord(Level.FINER, msg);
0791: record.setLoggerName(this .name);
0792: record.setSourceClassName(sourceClass);
0793: record.setSourceMethodName(sourceMethod);
0794: record.setParameters(params);
0795: setResourceBundle(record);
0796: log(record);
0797: }
0798: }
0799:
0800: /**
0801: * Logs a message indicating existing a method. A log record with log level
0802: * <code>Level.FINER</code>, log message "RETURN", and the specified
0803: * source class name and source method name is submitted for logging.
0804: *
0805: * @param sourceClass
0806: * the calling class name
0807: * @param sourceMethod
0808: * the method name
0809: */
0810: public void exiting(String sourceClass, String sourceMethod) {
0811: if (internalIsLoggable(Level.FINER)) {
0812: LogRecord record = new LogRecord(Level.FINER, "RETURN"); //$NON-NLS-1$
0813: record.setLoggerName(this .name);
0814: record.setSourceClassName(sourceClass);
0815: record.setSourceMethodName(sourceMethod);
0816: setResourceBundle(record);
0817: log(record);
0818: }
0819: }
0820:
0821: /**
0822: * Logs a message indicating exiting a method. A log record with log level
0823: * <code>Level.FINER</code>, log message "RETURN", and the specified
0824: * source class name and source method name and return value is submitted
0825: * for logging.
0826: *
0827: * @param sourceClass
0828: * the source class name
0829: * @param sourceMethod
0830: * the source method name
0831: * @param result
0832: * the return value of the method call
0833: */
0834: public void exiting(String sourceClass, String sourceMethod,
0835: Object result) {
0836: if (internalIsLoggable(Level.FINER)) {
0837: LogRecord record = new LogRecord(Level.FINER,
0838: "RETURN" + " {0}"); //$NON-NLS-1$ //$NON-NLS-2$
0839: record.setLoggerName(this .name);
0840: record.setSourceClassName(sourceClass);
0841: record.setSourceMethodName(sourceMethod);
0842: record.setParameters(new Object[] { result });
0843: setResourceBundle(record);
0844: log(record);
0845: }
0846: }
0847:
0848: /**
0849: * Logs a message indicating throwing an exception. A log record with log
0850: * level <code>Level.FINER</code>, log message "THROW", and the specified
0851: * source class name and source method name and <code>Throwable</code>
0852: * object is submitted for logging.
0853: *
0854: * @param sourceClass
0855: * the source class name
0856: * @param sourceMethod
0857: * the source method name
0858: * @param thrown
0859: * the <code>Throwable</code> object
0860: */
0861: public void throwing(String sourceClass, String sourceMethod,
0862: Throwable thrown) {
0863: if (internalIsLoggable(Level.FINER)) {
0864: LogRecord record = new LogRecord(Level.FINER, "THROW"); //$NON-NLS-1$
0865: record.setLoggerName(this .name);
0866: record.setSourceClassName(sourceClass);
0867: record.setSourceMethodName(sourceMethod);
0868: record.setThrown(thrown);
0869: setResourceBundle(record);
0870: log(record);
0871: }
0872: }
0873:
0874: /**
0875: * Logs a message of level <code>Level.SEVERE</code>.
0876: *
0877: * @param msg
0878: * the message to log
0879: */
0880: public void severe(String msg) {
0881: if (internalIsLoggable(Level.SEVERE)) {
0882: LogRecord record = new LogRecord(Level.SEVERE, msg);
0883: record.setLoggerName(this .name);
0884: setResourceBundle(record);
0885: log(record);
0886: }
0887: }
0888:
0889: /**
0890: * Logs a message of level <code>Level.WARNING</code>.
0891: *
0892: * @param msg
0893: * the message to log
0894: */
0895: public void warning(String msg) {
0896: if (internalIsLoggable(Level.WARNING)) {
0897: LogRecord record = new LogRecord(Level.WARNING, msg);
0898: record.setLoggerName(this .name);
0899: setResourceBundle(record);
0900: log(record);
0901: }
0902: }
0903:
0904: /**
0905: * Logs a message of level <code>Level.INFO</code>.
0906: *
0907: * @param msg
0908: * the message to log
0909: */
0910: public void info(String msg) {
0911: if (internalIsLoggable(Level.INFO)) {
0912: LogRecord record = new LogRecord(Level.INFO, msg);
0913: record.setLoggerName(this .name);
0914: setResourceBundle(record);
0915: log(record);
0916: }
0917: }
0918:
0919: /**
0920: * Logs a message of level <code>Level.CONFIG</code>.
0921: *
0922: * @param msg
0923: * the message to log
0924: */
0925: public void config(String msg) {
0926: if (internalIsLoggable(Level.CONFIG)) {
0927: LogRecord record = new LogRecord(Level.CONFIG, msg);
0928: record.setLoggerName(this .name);
0929: setResourceBundle(record);
0930: log(record);
0931: }
0932: }
0933:
0934: /**
0935: * Logs a message of level <code>Level.FINE</code>.
0936: *
0937: * @param msg
0938: * the message to log
0939: */
0940: public void fine(String msg) {
0941: if (internalIsLoggable(Level.FINE)) {
0942: LogRecord record = new LogRecord(Level.FINE, msg);
0943: record.setLoggerName(this .name);
0944: setResourceBundle(record);
0945: log(record);
0946: }
0947: }
0948:
0949: /**
0950: * Logs a message of level <code>Level.FINER</code>.
0951: *
0952: * @param msg
0953: * the message to log
0954: */
0955: public void finer(String msg) {
0956: if (internalIsLoggable(Level.FINER)) {
0957: LogRecord record = new LogRecord(Level.FINER, msg);
0958: record.setLoggerName(this .name);
0959: setResourceBundle(record);
0960: log(record);
0961: }
0962: }
0963:
0964: /**
0965: * Logs a message of level <code>Level.FINEST</code>.
0966: *
0967: * @param msg
0968: * the message to log
0969: */
0970: public void finest(String msg) {
0971: if (internalIsLoggable(Level.FINEST)) {
0972: LogRecord record = new LogRecord(Level.FINEST, msg);
0973: record.setLoggerName(this .name);
0974: setResourceBundle(record);
0975: log(record);
0976: }
0977: }
0978:
0979: /**
0980: * Logs a message of the specified level.
0981: *
0982: * @param logLevel
0983: * the level of the given message
0984: * @param msg
0985: * the message to log
0986: */
0987: public void log(Level logLevel, String msg) {
0988: if (internalIsLoggable(logLevel)) {
0989: LogRecord record = new LogRecord(logLevel, msg);
0990: record.setLoggerName(this .name);
0991: setResourceBundle(record);
0992: log(record);
0993: }
0994: }
0995:
0996: /**
0997: * Logs a message of the specified level with the supplied parameter.
0998: *
0999: * @param logLevel
1000: * the level of the given message
1001: * @param msg
1002: * the message to log
1003: * @param param
1004: * the parameter associated with the event that need to be logged
1005: */
1006: public void log(Level logLevel, String msg, Object param) {
1007: if (internalIsLoggable(logLevel)) {
1008: LogRecord record = new LogRecord(logLevel, msg);
1009: record.setLoggerName(this .name);
1010: record.setParameters(new Object[] { param });
1011: setResourceBundle(record);
1012: log(record);
1013: }
1014: }
1015:
1016: /**
1017: * Logs a message of the specified level with the supplied parameter array.
1018: *
1019: * @param logLevel
1020: * the level of the given message
1021: * @param msg
1022: * the message to log
1023: * @param params
1024: * the parameter array associated with the event that need to be
1025: * logged
1026: */
1027: public void log(Level logLevel, String msg, Object[] params) {
1028: if (internalIsLoggable(logLevel)) {
1029: LogRecord record = new LogRecord(logLevel, msg);
1030: record.setLoggerName(this .name);
1031: record.setParameters(params);
1032: setResourceBundle(record);
1033: log(record);
1034: }
1035: }
1036:
1037: /**
1038: * Logs a message of the specified level with the supplied
1039: * <code>Throwable</code> object.
1040: *
1041: * @param logLevel
1042: * the level of the given message
1043: * @param msg
1044: * the message to log
1045: * @param thrown
1046: * the <code>Throwable</code> object associated with the event
1047: * that need to be logged
1048: */
1049: public void log(Level logLevel, String msg, Throwable thrown) {
1050: if (internalIsLoggable(logLevel)) {
1051: LogRecord record = new LogRecord(logLevel, msg);
1052: record.setLoggerName(this .name);
1053: record.setThrown(thrown);
1054: setResourceBundle(record);
1055: log(record);
1056: }
1057: }
1058:
1059: /**
1060: * Logs a given log record. Only those with a logging level no lower than
1061: * this logger's level will be submitted to this logger's handlers for
1062: * logging. If <code>getUseParentHandlers()</code> is <code>true</code>,
1063: * the log record will also be submitted to the parent logger's handlers,
1064: * potentially recursively up the namespace.
1065: * <p>
1066: * Since all other log methods call this method to actually perform the
1067: * logging action, subclasses of this class can override this method to
1068: * catch all logging activities.
1069: * </p>
1070: *
1071: * @param record
1072: * the log record to be logged
1073: */
1074: public void log(LogRecord record) {
1075: if (internalIsLoggable(record.getLevel())) {
1076: // apply the filter if any
1077: Filter f = filter;
1078: if (null != f && !f.isLoggable(record)) {
1079: return;
1080: }
1081: initHandler();
1082: /*
1083: * call the handlers of this logger, throw any exception that occurs
1084: */
1085: Handler[] allHandlers = getHandlers();
1086: for (Handler element : allHandlers) {
1087: element.publish(record);
1088: }
1089: // call the parent's handlers if set useParentHandlers
1090: Logger temp = this ;
1091: Logger theParent = temp.parent;
1092: while (theParent != null && temp.getUseParentHandlers()) {
1093: Handler[] ha = theParent.getHandlers();
1094: for (Handler element : ha) {
1095: element.publish(record);
1096: }
1097: temp = theParent;
1098: theParent = temp.parent;
1099: }
1100: }
1101: }
1102:
1103: /**
1104: * Logs a message of the given level with the specified source class name
1105: * and source method name.
1106: *
1107: * @param logLevel
1108: * the level of the given message
1109: * @param sourceClass
1110: * the source class name
1111: * @param sourceMethod
1112: * the source method name
1113: * @param msg
1114: * the message to be logged
1115: */
1116: public void logp(Level logLevel, String sourceClass,
1117: String sourceMethod, String msg) {
1118: if (internalIsLoggable(logLevel)) {
1119: LogRecord record = new LogRecord(logLevel, msg);
1120: record.setLoggerName(this .name);
1121: record.setSourceClassName(sourceClass);
1122: record.setSourceMethodName(sourceMethod);
1123: setResourceBundle(record);
1124: log(record);
1125: }
1126: }
1127:
1128: /**
1129: * Logs a message of the given level with the specified source class name
1130: * and source method name and parameter.
1131: *
1132: * @param logLevel
1133: * the level of the given message
1134: * @param sourceClass
1135: * the source class name
1136: * @param sourceMethod
1137: * the source method name
1138: * @param msg
1139: * the message to be logged
1140: * @param param
1141: * the parameter associated with the event that need to be logged
1142: */
1143: public void logp(Level logLevel, String sourceClass,
1144: String sourceMethod, String msg, Object param) {
1145: if (internalIsLoggable(logLevel)) {
1146: LogRecord record = new LogRecord(logLevel, msg);
1147: record.setLoggerName(this .name);
1148: record.setSourceClassName(sourceClass);
1149: record.setSourceMethodName(sourceMethod);
1150: record.setParameters(new Object[] { param });
1151: setResourceBundle(record);
1152: log(record);
1153: }
1154: }
1155:
1156: /**
1157: * Logs a message of the given level with the specified source class name
1158: * and source method name and parameter array.
1159: *
1160: * @param logLevel
1161: * the level of the given message
1162: * @param sourceClass
1163: * the source class name
1164: * @param sourceMethod
1165: * the source method name
1166: * @param msg
1167: * the message to be logged
1168: * @param params
1169: * the parameter array associated with the event that need to be
1170: * logged
1171: */
1172: public void logp(Level logLevel, String sourceClass,
1173: String sourceMethod, String msg, Object[] params) {
1174: if (internalIsLoggable(logLevel)) {
1175: LogRecord record = new LogRecord(logLevel, msg);
1176: record.setLoggerName(this .name);
1177: record.setSourceClassName(sourceClass);
1178: record.setSourceMethodName(sourceMethod);
1179: record.setParameters(params);
1180: setResourceBundle(record);
1181: log(record);
1182: }
1183: }
1184:
1185: /**
1186: * Logs a message of the given level with the specified source class name
1187: * and source method name and <code>Throwable</code> object.
1188: *
1189: * @param logLevel
1190: * the level of the given message
1191: * @param sourceClass
1192: * the source class name
1193: * @param sourceMethod
1194: * the source method name
1195: * @param msg
1196: * the message to be logged
1197: * @param thrown
1198: * the <code>Throwable</code> object
1199: */
1200: public void logp(Level logLevel, String sourceClass,
1201: String sourceMethod, String msg, Throwable thrown) {
1202: if (internalIsLoggable(logLevel)) {
1203: LogRecord record = new LogRecord(logLevel, msg);
1204: record.setLoggerName(this .name);
1205: record.setSourceClassName(sourceClass);
1206: record.setSourceMethodName(sourceMethod);
1207: record.setThrown(thrown);
1208: setResourceBundle(record);
1209: log(record);
1210: }
1211: }
1212:
1213: /**
1214: * Logs a message of the given level with the specified source class name
1215: * and source method name, using the given resource bundle to localize the
1216: * message.
1217: *
1218: * @param logLevel
1219: * the level of the given message
1220: * @param sourceClass
1221: * the source class name
1222: * @param sourceMethod
1223: * the source method name
1224: * @param bundleName
1225: * the name of the resource bundle, used to localize the message
1226: * @param msg
1227: * the message to be logged
1228: */
1229: public void logrb(Level logLevel, String sourceClass,
1230: String sourceMethod, String bundleName, String msg) {
1231: if (internalIsLoggable(logLevel)) {
1232: LogRecord record = new LogRecord(logLevel, msg);
1233: if (null != bundleName) {
1234: try {
1235: record
1236: .setResourceBundle(loadResourceBundle(bundleName));
1237: } catch (MissingResourceException e) {
1238: // ignore
1239: }
1240: record.setResourceBundleName(bundleName);
1241: }
1242: record.setLoggerName(this .name);
1243: record.setSourceClassName(sourceClass);
1244: record.setSourceMethodName(sourceMethod);
1245: log(record);
1246: }
1247: }
1248:
1249: /**
1250: * Logs a message of the given level with the specified source class name
1251: * and source method name and parameter, using the given resource bundle to
1252: * localize the message.
1253: *
1254: * @param logLevel
1255: * the level of the given message
1256: * @param sourceClass
1257: * the source class name
1258: * @param sourceMethod
1259: * the source method name
1260: * @param bundleName
1261: * the name of the resource bundle, used to localize the message
1262: * @param msg
1263: * the message to be logged
1264: * @param param
1265: * the parameter associated with the event that need to be logged
1266: */
1267: public void logrb(Level logLevel, String sourceClass,
1268: String sourceMethod, String bundleName, String msg,
1269: Object param) {
1270: if (internalIsLoggable(logLevel)) {
1271: LogRecord record = new LogRecord(logLevel, msg);
1272: if (null != bundleName) {
1273: try {
1274: record
1275: .setResourceBundle(loadResourceBundle(bundleName));
1276: } catch (MissingResourceException e) {
1277: // ignore
1278: }
1279: record.setResourceBundleName(bundleName);
1280: }
1281: record.setLoggerName(this .name);
1282: record.setSourceClassName(sourceClass);
1283: record.setSourceMethodName(sourceMethod);
1284: record.setParameters(new Object[] { param });
1285: log(record);
1286: }
1287: }
1288:
1289: /**
1290: * Logs a message of the given level with the specified source class name
1291: * and source method name and parameter array, using the given resource
1292: * bundle to localize the message.
1293: *
1294: * @param logLevel
1295: * the level of the given message
1296: * @param sourceClass
1297: * the source class name
1298: * @param sourceMethod
1299: * the source method name
1300: * @param bundleName
1301: * the name of the resource bundle, used to localize the message
1302: * @param msg
1303: * the message to be logged
1304: * @param params
1305: * the parameter array associated with the event that need to be
1306: * logged
1307: */
1308: public void logrb(Level logLevel, String sourceClass,
1309: String sourceMethod, String bundleName, String msg,
1310: Object[] params) {
1311: if (internalIsLoggable(logLevel)) {
1312: LogRecord record = new LogRecord(logLevel, msg);
1313: if (null != bundleName) {
1314: try {
1315: record
1316: .setResourceBundle(loadResourceBundle(bundleName));
1317: } catch (MissingResourceException e) {
1318: // ignore
1319: }
1320: record.setResourceBundleName(bundleName);
1321: }
1322: record.setLoggerName(this .name);
1323: record.setSourceClassName(sourceClass);
1324: record.setSourceMethodName(sourceMethod);
1325: record.setParameters(params);
1326: log(record);
1327: }
1328: }
1329:
1330: /**
1331: * Logs a message of the given level with the specified source class name
1332: * and source method name and <code>Throwable</code> object, using the
1333: * given resource bundle to localize the message.
1334: *
1335: * @param logLevel
1336: * the level of the given message
1337: * @param sourceClass
1338: * the source class name
1339: * @param sourceMethod
1340: * the source method name
1341: * @param bundleName
1342: * the name of the resource bundle, used to localize the message
1343: * @param msg
1344: * the message to be logged
1345: * @param thrown
1346: * the <code>Throwable</code> object
1347: */
1348: public void logrb(Level logLevel, String sourceClass,
1349: String sourceMethod, String bundleName, String msg,
1350: Throwable thrown) {
1351: if (internalIsLoggable(logLevel)) {
1352: LogRecord record = new LogRecord(logLevel, msg);
1353: if (null != bundleName) {
1354: try {
1355: record
1356: .setResourceBundle(loadResourceBundle(bundleName));
1357: } catch (MissingResourceException e) {
1358: // ignore
1359: }
1360: record.setResourceBundleName(bundleName);
1361: }
1362: record.setLoggerName(this .name);
1363: record.setSourceClassName(sourceClass);
1364: record.setSourceMethodName(sourceMethod);
1365: record.setThrown(thrown);
1366: log(record);
1367: }
1368: }
1369:
1370: /*
1371: * This security manager is used to access the class context.
1372: */
1373: static class PrivateSecurityManager extends SecurityManager {
1374: public Class<?>[] privateGetClassContext() {
1375: return super .getClassContext();
1376: }
1377: }
1378:
1379: void setManager(LogManager manager) {
1380: if (this .manager != manager) {
1381: this .manager = manager;
1382: handlerInited = false;
1383: }
1384: // init level here, but let handlers be for lazy loading
1385: final String configedLevel = manager.getProperty(name
1386: + ".level"); //$NON-NLS-1$
1387: if (null != configedLevel) {
1388: try {
1389: AccessController
1390: .doPrivileged(new PrivilegedAction<Object>() {
1391: public Object run() {
1392: setLevel(Level.parse(configedLevel));
1393: return null;
1394: }
1395: });
1396: } catch (IllegalArgumentException e) {
1397: // ignore
1398: }
1399: }
1400: }
1401:
1402: synchronized void reset() {
1403: levelObjVal = null;
1404: levelIntVal = Level.INFO.intValue();
1405: if (handlers != null) {
1406: for (Handler element : handlers) {
1407: // close all handlers, when unknown exceptions happen,
1408: // ignore them and go on
1409: try {
1410: element.close();
1411: } catch (Exception e) {
1412: // Ignored.
1413: }
1414: }
1415: handlers.clear();
1416: }
1417: handlerInited = false;
1418: }
1419: }
|