001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)ComponentLogger.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.framework;
030:
031: import java.io.File;
032: import java.io.FileInputStream;
033: import java.io.FileOutputStream;
034: import java.util.List;
035: import java.util.Properties;
036: import java.util.TreeMap;
037: import java.util.logging.Logger;
038: import java.util.logging.Level;
039: import javax.management.ObjectName;
040:
041: /**
042: * This class implements the ComponentLoggerMBean for a Component (BC or SE).
043: * This MBean acts as an agent between the JMX management service and the
044: * UI runtime to provide operations for displaying and modifying the logger
045: * levels for a component.
046: *
047: * @author Sun Microsystems, Inc.
048: */
049: public class ComponentLogger implements ComponentLoggerMBean {
050: /**
051: * Component instance handle.
052: */
053: private Component mComponent;
054:
055: /**
056: * Logger used for local logging.
057: */
058: private Logger mLog;
059:
060: /**
061: * Logger info table. This has an entry for each logger registered by the
062: * component. Each entry is an instance of LoggerInfo.
063: * This table is a TreeMap so that the loggers are kept in alphabetical
064: * order by name.
065: */
066: private TreeMap<String, LoggerInfo> mLoggerInfo;
067:
068: /**
069: * Logger name prefix for loggers that need a prefix added.
070: */
071: private String mLoggerNamePrefix;
072:
073: /**
074: * Logger level properties for this component. This is perstisted as a
075: * separate file in the component's install root.
076: */
077: private Properties mLoggerSettings;
078:
079: /**
080: * Local handle to StringTranslator.
081: */
082: private StringTranslator mTranslator;
083:
084: /**
085: * The name of the directory where the component logger level properties
086: * file is written. NOTE: This package-accessible to allow the unit test
087: * to use it.
088: */
089: static final String CONFIG_DIRECTORY = "/config/";
090:
091: /**
092: * The name of the file containing the component logger level properties.
093: * NOTE: This package-accessible to allow the unit test to use it.
094: */
095: static final String LOGGER_SETTINGS = "loggerSettings.properties";
096:
097: /**
098: * The value for a component logger level property for inheriting from the
099: * parent logger. NOTE: This package-accessible to allow the unit test
100: * to use it.
101: */
102: static final String LOGGER_DEFAULT = "DEFAULT";
103:
104: /**
105: * The suffix for the logger display name property stored in the logger
106: * properties file. NOTE: This package-accessible to allow the unit test
107: * to use it.
108: */
109: static final String DISPLAY_NAME = ".displayName";
110:
111: /**
112: * Constructor. This loads any logger levels that were previously persisted,
113: * and creates the top-level logger for the component, setting its parent
114: * to the top-level JBI logger and its level to the persisted level if
115: * found.
116: * @param component is the Component instance for this component.
117: */
118: ComponentLogger(Component component) {
119: mComponent = component;
120: EnvironmentContext env = EnvironmentContext.getInstance();
121: mLog = (Logger) env.getLogger();
122: mLoggerInfo = new TreeMap();
123: mLoggerNamePrefix = component.getName() + ".";
124: mLoggerSettings = new Properties();
125: mTranslator = (StringTranslator) env
126: .getStringTranslatorFor(this );
127:
128: // Load any persisted logger levels
129:
130: loadLoggerSettings();
131:
132: // Create the top-level logger for the component and initialize its
133: // level. Add the logger to the logger info table.
134:
135: String name = component.getName();
136: Logger logger = Logger.getLogger(name);
137: logger.setParent(env.getJbiLogger());
138: logger.setLevel(getSavedLevel(name));
139: addLogger(logger, name);
140: }
141:
142: //
143: // Methods defined in the ComponentLoggerMBean interface
144: //
145:
146: /**
147: * Get the localized display name of the specified logger. If none is
148: * available, return a default name set to the last level of the logger
149: * name.
150: *
151: * @param logName the name of the logger.
152: * @return String representing the localized display name.
153: */
154: public String getDisplayName(String logName) {
155: if (null == logName) {
156: throw new java.lang.IllegalArgumentException(
157: mTranslator.getString(
158: LocalStringKeys.NULL_ARGUMENT, "logName"));
159: }
160:
161: String displayName = null;
162:
163: // Look for an entry in the logger info table, and if it has no name
164: // set, look for an entry in the logger settings properties.
165:
166: LoggerInfo info = mLoggerInfo.get(logName);
167: if (null != info) {
168: String dn = info.getDisplayName();
169: if (null == dn) {
170: dn = mLoggerSettings
171: .getProperty(logName + DISPLAY_NAME);
172: if (null != dn) {
173: displayName = dn;
174: info.setDisplayName(dn);
175: }
176: } else {
177: displayName = dn;
178: }
179: }
180:
181: // If the display name is still not set, create a default from the
182: // last level of the logger name
183:
184: if (null == displayName) {
185: int lastDot = logName.lastIndexOf(".");
186: if (-1 < lastDot) {
187: displayName = logName.substring(lastDot + 1);
188: } else {
189: displayName = logName;
190: }
191: }
192:
193: return displayName;
194: }
195:
196: /**
197: * Get the log level of the specified logger. If the level is not set,
198: * search the parent logger chain until a logger is found with a level set.
199: * In the case where this method is called before the component has been
200: * started, the logger may not exist. In this case, retrieve the logger
201: * level property and use its value, or if there is no logger level property
202: * set, use the top-level component logger's level. The top-level component
203: * logger always exists because it is created by the constructor of this
204: * class.
205: *
206: * @param logName the name of the logger.
207: * @return String representing log level or null if no level is available.
208: * @throws javax.jbi.JBIException if the logger is not known.
209: */
210: public String getLevel(String logName)
211: throws javax.jbi.JBIException {
212: if (null == logName) {
213: throw new java.lang.IllegalArgumentException(
214: mTranslator.getString(
215: LocalStringKeys.NULL_ARGUMENT, "logName"));
216: }
217:
218: LoggerInfo info = mLoggerInfo.get(logName);
219:
220: // If the logger name has not been registered, give up.
221:
222: if (null == info) {
223: throw new javax.jbi.JBIException(mTranslator.getString(
224: LocalStringKeys.COMP_LOGGER_NOT_FOUND, logName));
225: }
226:
227: // The logger name has been registered. If the logger has not been
228: // created, use its saved level from the logger level properties,
229: // if available. If no level has been saved for this logger, get
230: // the level of the top-level component logger, which always exists.
231:
232: Logger log = info.getLogger();
233: if (null == log) {
234: String lvl = mLoggerSettings.getProperty(logName);
235: if (null == lvl || lvl.equals(LOGGER_DEFAULT)) {
236: lvl = getLevel(mComponent.getName());
237: }
238: return Level.parse(lvl).getLocalizedName();
239: }
240:
241: // The logger has been created. Get its level, and if it is not set,
242: // run the parent logger chain until a logger is found with a level
243: // set. If no logger is found with a level set, return null. Note
244: // that this should never happen, as all loggers' parent chains
245: // eventually lead to the main JDK logger, which always has a
246: // level set.
247:
248: Level level = log.getLevel();
249: while (null == level) {
250: log = log.getParent();
251: if (null != log) {
252: level = log.getLevel();
253: } else {
254: break;
255: }
256: }
257: if (null != level) {
258: return level.getLocalizedName();
259: } else {
260: return null;
261: }
262: }
263:
264: /**
265: * Get the names of all loggers controlled by this MBean.
266: *
267: * @return an array of logger names as String objects.
268: */
269: public String[] getLoggerNames() {
270: String[] s = new String[mLoggerInfo.size()];
271: mLoggerInfo.keySet().toArray(s);
272: return s;
273: }
274:
275: /**
276: * Set the log level of the specified logger to ALL.
277: *
278: * @param logName the logger name.
279: * @return 0 if operation is successful.
280: * @throws javax.jbi.JBIException if the logger is not found.
281: */
282: public int setAll(String logName) throws javax.jbi.JBIException {
283: return setLevel(logName, Level.ALL);
284: }
285:
286: /**
287: * Set the log level of the specified logger to CONFIG.
288: *
289: * @param logName the logger name.
290: * @return 0 if operation is successful.
291: * @throws javax.jbi.JBIException if the logger is not found.
292: */
293: public int setConfig(String logName) throws javax.jbi.JBIException {
294: return setLevel(logName, Level.CONFIG);
295: }
296:
297: /**
298: * Set the log level of the specified logger to the default, which is
299: * null to inherit the parent logger's level.
300: *
301: * @param logName the logger name.
302: * @return 0 if operation is successful.
303: * @throws javax.jbi.JBIException if the logger is not found.
304: */
305: public int setDefault(String logName) throws javax.jbi.JBIException {
306: return setLevel(logName, null);
307: }
308:
309: /**
310: * Set the log level of the specified logger to FINE.
311: *
312: * @param logName the logger name.
313: * @return 0 if operation is successful.
314: * @throws javax.jbi.JBIException if the logger is not found.
315: */
316: public int setFine(String logName) throws javax.jbi.JBIException {
317: return setLevel(logName, Level.FINE);
318: }
319:
320: /**
321: * Set the log level of the specified logger to FINER.
322: *
323: * @param logName the logger name.
324: * @return 0 if operation is successful.
325: * @throws javax.jbi.JBIException if the logger is not found.
326: */
327: public int setFiner(String logName) throws javax.jbi.JBIException {
328: return setLevel(logName, Level.FINER);
329: }
330:
331: /**
332: * Set the log level of the specified logger to FINEST.
333: *
334: * @param logName the logger name.
335: * @return 0 if operation is successful.
336: * @throws javax.jbi.JBIException if the logger is not found.
337: */
338: public int setFinest(String logName) throws javax.jbi.JBIException {
339: return setLevel(logName, Level.FINEST);
340: }
341:
342: /**
343: * Set the log level of the specified logger to INFO.
344: *
345: * @param logName the logger name.
346: * @return 0 if operation is successful.
347: * @throws javax.jbi.JBIException if the logger is not found.
348: */
349: public int setInfo(String logName) throws javax.jbi.JBIException {
350: return setLevel(logName, Level.INFO);
351: }
352:
353: /**
354: * Set the log level of the specified logger to OFF.
355: *
356: * @param logName the logger name.
357: * @return 0 if operation is successful.
358: * @throws javax.jbi.JBIException if the logger is not found.
359: */
360: public int setOff(String logName) throws javax.jbi.JBIException {
361: return setLevel(logName, Level.OFF);
362: }
363:
364: /**
365: * Set the log level of the specified logger to SEVERE.
366: *
367: * @param logName the logger name.
368: * @return 0 if operation is successful.
369: * @throws javax.jbi.JBIException if the logger is not found.
370: */
371: public int setSevere(String logName) throws javax.jbi.JBIException {
372: return setLevel(logName, Level.SEVERE);
373: }
374:
375: /**
376: * Set the log level of the specified logger to WARNING.
377: *
378: * @param logName the logger name.
379: * @return 0 if operation is successful.
380: * @throws javax.jbi.JBIException if the logger is not found.
381: */
382: public int setWarning(String logName) throws javax.jbi.JBIException {
383: return setLevel(logName, Level.WARNING);
384: }
385:
386: //
387: // Methods not in the ComponentLoggerMBean interface. These are used only
388: // in the framework.
389: //
390:
391: /**
392: * Add an entry to the logger info table. Each entry contains the logger
393: * name as the key and the LoggerInfo instance as the value. If an entry
394: * already exists for this logger name, but its logger reference has not
395: * been set, set it now. Do the same for the display name.
396: *
397: * @param logger The Logger instance.
398: * @param displayName The logger's display name.
399: * @return <code>true</code> if either the logger instance was not already
400: * set in the existing LoggerInfo, or there was no existing LoggerInfo for
401: * this logger. Returns <code>false</code> if there was an existing
402: * LoggerInfo and its logger instance was already set. Note that the return
403: * value is used only for unit testing.
404: */
405: boolean addLogger(Logger logger, String displayName) {
406: if (null == logger) {
407: throw new java.lang.IllegalArgumentException(mTranslator
408: .getString(LocalStringKeys.NULL_ARGUMENT, "logger"));
409: }
410: if (null == displayName) {
411: throw new java.lang.IllegalArgumentException(mTranslator
412: .getString(LocalStringKeys.NULL_ARGUMENT,
413: "displayName"));
414: }
415:
416: boolean added = false;
417: String loggerName = logger.getName();
418: LoggerInfo info = null;
419:
420: // Add a new LoggerInfo to the logger info table if one does not already
421: // exist for this logger. Otherwise, retrieve the existing LoggerInfo
422: // and update it with the logger reference and display name if not
423: // already set. This means that if the display name was pre-defined
424: // at component installation time, that name is retained and not
425: // replaced with the default display name provided by the caller.
426:
427: if (mLoggerInfo.containsKey(loggerName)) {
428: info = mLoggerInfo.get(loggerName);
429: if (null == info.getLogger()) {
430: info.setLogger(logger);
431: added = true;
432: }
433: if (null == info.getDisplayName()) {
434: info.setDisplayName(displayName);
435: }
436: } else {
437: info = new LoggerInfo(logger, displayName);
438: mLoggerInfo.put(loggerName, info);
439: added = true;
440: }
441: if (added) {
442: logger.setLevel(getSavedLevel(loggerName));
443: }
444: return added;
445: }
446:
447: /**
448: * Add predefined logger information to the logger info table. This creates
449: * a new LoggerInfo object using the provided values, and adds it to the
450: * logger info table. It also adds a property for the logger to the logger
451: * settings, with the value set to the default logger level. The logger
452: * reference is not set, as the logger has not yet been created.
453: *
454: * Note that this method is called only during installation or upgrade of
455: * a component.
456: *
457: * @param loggerName the name of the logger to be added.
458: * @param displayName the display name of the logger to be added; if this
459: * is null the last level of the logger name is used.
460: * @param addPrefix set to <code>true</code> if the prefix should be added
461: * to this logger name, or <code>false</code> if the logger name should
462: * be kept as is.
463: */
464: void addLoggerInfo(String loggerName, String displayName,
465: boolean addPrefix) {
466: // If the prefix is to be added to this logger name, and it doesn't
467: // already start with the prefix, add the prefix now
468: if (addPrefix) {
469: if (null != mLoggerNamePrefix) {
470: if (!loggerName.startsWith(mLoggerNamePrefix)) {
471: loggerName = mLoggerNamePrefix.concat(loggerName);
472: }
473: }
474: }
475:
476: // If the display name is not provided, create a default from the
477: // last level of the logger name
478: if (null == displayName) {
479: int lastDot = loggerName.lastIndexOf(".");
480: if (-1 < lastDot) {
481: displayName = loggerName.substring(lastDot + 1);
482: } else {
483: displayName = loggerName;
484: }
485: }
486:
487: if (!mLoggerInfo.containsKey(loggerName)) {
488: // Create a LoggerInfo for the logger and add it to the logger
489: // info table.
490: LoggerInfo info = new LoggerInfo(displayName);
491: mLoggerInfo.put(loggerName, info);
492: } else {
493: // Update the existing LoggerInfo for this logger.
494: LoggerInfo info = mLoggerInfo.get(loggerName);
495: info.setDisplayName(displayName);
496: }
497:
498: // Set the logger level property in the logger settings.
499: if (null == mLoggerSettings.getProperty(loggerName)) {
500: mLoggerSettings.setProperty(loggerName, LOGGER_DEFAULT);
501: mLoggerSettings.setProperty(loggerName + DISPLAY_NAME,
502: displayName);
503: }
504: }
505:
506: /**
507: * Get the logger name prefix for this component.
508: * @return the logger name prefix.
509: */
510: String getLoggerNamePrefix() {
511: return mLoggerNamePrefix;
512: }
513:
514: /**
515: * Get the saved logger level for a logger. This is used for restoring
516: * persisted logger levels that were set explicitly.
517: *
518: * @param loggerName The logger name.
519: * @return The logger level, or null if none was persisted.
520: */
521: Level getSavedLevel(String loggerName) {
522: if (null == loggerName) {
523: throw new java.lang.IllegalArgumentException(mTranslator
524: .getString(LocalStringKeys.NULL_ARGUMENT,
525: "loggerName"));
526: }
527: String level = mLoggerSettings.getProperty(loggerName);
528: if (null != level) {
529: if (level.equals(LOGGER_DEFAULT)) {
530: return null;
531: }
532: return Level.parse(level);
533: } else {
534: return null;
535: }
536: }
537:
538: /**
539: * Load logger level setting properties from the persisted file.
540: */
541: void loadLoggerSettings() {
542: FileInputStream inStream = null;
543: File configFile = new File(getConfigDirName() + LOGGER_SETTINGS);
544: try {
545: inStream = new FileInputStream(configFile);
546: mLoggerSettings.load(inStream);
547: } catch (java.io.FileNotFoundException fnfEx) {
548: ; // This just means no logger settings were persisted
549: } catch (java.io.IOException ioEx) {
550: mLog.log(Level.WARNING, mTranslator.getString(
551: LocalStringKeys.COMP_LOGGER_SETTINGS_LOAD_FAILED,
552: mComponent.getComponentTypeAsString(), mComponent
553: .getName(), configFile.getAbsolutePath()),
554: ioEx);
555: } finally {
556: if (null != inStream) {
557: try {
558: inStream.close();
559: } catch (java.io.IOException ioEx) {
560: mLog
561: .log(
562: Level.WARNING,
563: mTranslator
564: .getString(
565: LocalStringKeys.COMP_LOGGER_SETTINGS_CLOSE_FAILED,
566: mComponent
567: .getComponentTypeAsString(),
568: mComponent
569: .getName(),
570: configFile
571: .getAbsolutePath()),
572: ioEx);
573: }
574: }
575: }
576: }
577:
578: /**
579: * Save logger level setting properties to a persisted file.
580: */
581: synchronized void saveLoggerSettings() {
582: File configDir = new File(getConfigDirName());
583: if (!configDir.exists()) {
584: if (!configDir.mkdir()) {
585: mLog
586: .warning(mTranslator
587: .getString(
588: LocalStringKeys.COMP_LOGGER_SETTINGS_CREATE_FAILED,
589: configDir.getAbsolutePath(),
590: mComponent
591: .getComponentTypeAsString(),
592: mComponent.getName()));
593: return;
594: }
595: }
596:
597: File configFile = new File(getConfigDirName() + LOGGER_SETTINGS);
598: FileOutputStream outStream = null;
599: try {
600: outStream = new FileOutputStream(configFile);
601: mLoggerSettings.store(outStream, "Logger levels for "
602: + mComponent.getComponentTypeAsString() + " "
603: + mComponent.getName());
604: } catch (java.io.FileNotFoundException fnfEx) {
605: mLog.log(Level.WARNING, mTranslator.getString(
606: LocalStringKeys.COMP_LOGGER_SETTINGS_SAVE_FAILED,
607: mComponent.getComponentTypeAsString(), mComponent
608: .getName(), configFile.getAbsolutePath()),
609: fnfEx);
610: } catch (java.io.IOException ioEx) {
611: mLog.log(Level.WARNING, mTranslator.getString(
612: LocalStringKeys.COMP_LOGGER_SETTINGS_SAVE_FAILED,
613: mComponent.getComponentTypeAsString(), mComponent
614: .getName(), configFile.getAbsolutePath()),
615: ioEx);
616: } finally {
617: if (null != outStream) {
618: try {
619: outStream.close();
620: } catch (java.io.IOException ioEx) {
621: mLog
622: .log(
623: Level.WARNING,
624: mTranslator
625: .getString(
626: LocalStringKeys.COMP_LOGGER_SETTINGS_CLOSE_FAILED,
627: mComponent
628: .getComponentTypeAsString(),
629: mComponent
630: .getName(),
631: configFile
632: .getAbsolutePath()),
633: ioEx);
634: }
635: }
636: }
637:
638: }
639:
640: /**
641: * Return an indication of whether or not a logger is registered.
642: *
643: * @return <code>true</code> if the logger is registered, or
644: * <code>false</code> if not.
645: */
646: boolean isLoggerRegistered(String name) {
647: if (mLoggerInfo.containsKey(name)) {
648: LoggerInfo info = mLoggerInfo.get(name);
649: if (null != info.getLogger()) {
650: return true;
651: }
652: }
653: return false;
654: }
655:
656: /**
657: * Set the logger name prefix for this component.
658: * @param prefix the logger name prefix to be set.
659: */
660: void setLoggerNamePrefix(String prefix) {
661: if (prefix.endsWith(".")) {
662: mLoggerNamePrefix = prefix;
663: } else {
664: mLoggerNamePrefix = prefix + ".";
665: }
666: }
667:
668: //
669: // Private methods
670: //
671:
672: /**
673: * Get the config directory name for this component.
674: *
675: * @return The config directory name.
676: */
677: private String getConfigDirName() {
678: File installRoot = new File(mComponent.getInstallRoot());
679: return installRoot.getParent() + CONFIG_DIRECTORY;
680: }
681:
682: /**
683: * Set the log level of the specified logger to the specified level. This
684: * also persists the logger settings for the component so that if a restart
685: * occurs, the logger settings are retained.
686: *
687: * @param logName the logger name.
688: * @param logLevel the log level.
689: * @return 0 if operation is successful.
690: * @throws javax.jbi.JBIException if the logger is not found.
691: */
692: int setLevel(String logName, Level logLevel)
693: throws javax.jbi.JBIException {
694: if (null == logName) {
695: throw new java.lang.IllegalArgumentException(
696: mTranslator.getString(
697: LocalStringKeys.NULL_ARGUMENT, "logName"));
698: }
699:
700: LoggerInfo info = mLoggerInfo.get(logName);
701: if (null != info) {
702: Logger log = info.getLogger();
703: // This is here to support setting the levels of loggers that
704: // are not obtained through ComponentContext.getLogger()
705: if (null == log) {
706: log = Logger.getLogger(logName);
707: info.setLogger(log);
708: }
709: log.setLevel(logLevel);
710: mLog.fine("Logger "
711: + logName
712: + " set to "
713: + (logLevel == null ? "null" : logLevel
714: .getLocalizedName()));
715:
716: if (null == logLevel) {
717: mLoggerSettings.setProperty(logName, LOGGER_DEFAULT);
718: } else {
719: mLoggerSettings.setProperty(logName, logLevel
720: .getLocalizedName());
721: }
722: saveLoggerSettings();
723: return 0;
724: } else {
725: throw new javax.jbi.JBIException(mTranslator.getString(
726: LocalStringKeys.COMP_LOGGER_NOT_FOUND, logName));
727: }
728: }
729:
730: /**
731: * This private class holds information about a single component logger.
732: */
733: private class LoggerInfo {
734: /**
735: * Logger instance.
736: */
737: Logger mLogger;
738:
739: /**
740: * Display name.
741: */
742: String mDisplayName;
743:
744: /**
745: * Constructor.
746: *
747: * @param logger The Logger instance.
748: * @param displayName The display name for the logger.
749: */
750: LoggerInfo(Logger logger, String displayName) {
751: mLogger = logger;
752: mDisplayName = displayName;
753: }
754:
755: /**
756: * Alternate constructor used for pre-defined logger names.
757: *
758: * @param displayName The display name for the logger.
759: */
760: LoggerInfo(String displayName) {
761: mLogger = null;
762: mDisplayName = displayName;
763: }
764:
765: /**
766: * Get the Logger instance for this logger.
767: * @return The java.util.logging.Logger instance.
768: */
769: Logger getLogger() {
770: return mLogger;
771: }
772:
773: /**
774: * Get the Logger name for this logger.
775: * @return The name of the logger.
776: */
777: String getLoggerName() {
778: return mLogger.getName();
779: }
780:
781: /**
782: * Get the display name for this logger.
783: * @return The display name for the logger.
784: */
785: String getDisplayName() {
786: return mDisplayName;
787: }
788:
789: /**
790: * Set the Logger instance for this logger.
791: * @param logger the java.util.logging.Logger instance.
792: */
793: void setLogger(Logger logger) {
794: mLogger = logger;
795: }
796:
797: /**
798: * Set the display name for this logger.
799: * @param displayName the display name to be set.
800: */
801: void setDisplayName(String displayName) {
802: mDisplayName = displayName;
803: }
804: }
805: }
|