Frames | No Frames |
1: /* Handler.java -- a class for publishing log messages 2: Copyright (C) 2002, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util.logging; 40: 41: import java.io.UnsupportedEncodingException; 42: 43: /** 44: * A <code>Handler</code> publishes <code>LogRecords</code> to 45: * a sink, for example a file, the console or a network socket. 46: * There are different subclasses of <code>Handler</code> 47: * to deal with different kinds of sinks. 48: * 49: * <p>FIXME: Are handlers thread-safe, or is the assumption that only 50: * loggers are, and a handler can belong only to one single logger? If 51: * the latter, should we enforce it? (Spec not clear). In any 52: * case, it needs documentation. 53: * 54: * @author Sascha Brawer (brawer@acm.org) 55: */ 56: public abstract class Handler 57: { 58: Formatter formatter; 59: Filter filter; 60: Level level; 61: ErrorManager errorManager; 62: String encoding; 63: 64: /** 65: * Constructs a Handler with a logging severity level of 66: * <code>Level.ALL</code>, no formatter, no filter, and 67: * an instance of <code>ErrorManager</code> managing errors. 68: * 69: * <p><strong>Specification Note:</strong> The specification of the 70: * Java<sup>TM</sup> Logging API does not mention which character 71: * encoding is to be used by freshly constructed Handlers. The GNU 72: * implementation uses the default platform encoding, but other 73: * Java implementations might behave differently. 74: * 75: * <p><strong>Specification Note:</strong> While a freshly constructed 76: * Handler is required to have <em>no filter</em> according to the 77: * specification, <code>null</code> is not a valid parameter for 78: * <code>Handler.setFormatter</code>. Therefore, the following 79: * code will throw a <code>java.lang.NullPointerException</code>: 80: * 81: * <p><pre>Handler h = new MyConcreteSubclassOfHandler(); 82: h.setFormatter(h.getFormatter());</pre> 83: * 84: * It seems strange that a freshly constructed Handler is not 85: * supposed to provide a Formatter, but this is what the specification 86: * says. 87: */ 88: protected Handler() 89: { 90: level = Level.ALL; 91: } 92: 93: 94: /** 95: * Publishes a <code>LogRecord</code> to an appropriate sink, 96: * provided the record passes all tests for being loggable. The 97: * <code>Handler</code> will localize the message of the log 98: * record and substitute any message parameters. 99: * 100: * <p>Most applications do not need to call this method directly. 101: * Instead, they will use use a {@link Logger}, which will 102: * create LogRecords and distribute them to registered handlers. 103: * 104: * <p>In case of an I/O failure, the <code>ErrorManager</code> 105: * of this <code>Handler</code> will be informed, but the caller 106: * of this method will not receive an exception. 107: * 108: * @param record the log event to be published. 109: */ 110: public abstract void publish(LogRecord record); 111: 112: 113: /** 114: * Forces any data that may have been buffered to the underlying 115: * output device. 116: * 117: * <p>In case of an I/O failure, the <code>ErrorManager</code> 118: * of this <code>Handler</code> will be informed, but the caller 119: * of this method will not receive an exception. 120: */ 121: public abstract void flush(); 122: 123: 124: /** 125: * Closes this <code>Handler</code> after having flushed 126: * the buffers. As soon as <code>close</code> has been called, 127: * a <code>Handler</code> should not be used anymore. Attempts 128: * to publish log records, to flush buffers, or to modify the 129: * <code>Handler</code> in any other way may throw runtime 130: * exceptions after calling <code>close</code>. 131: * 132: * <p>In case of an I/O failure, the <code>ErrorManager</code> 133: * of this <code>Handler</code> will be informed, but the caller 134: * of this method will not receive an exception. 135: * 136: * @throws SecurityException if a security manager exists and 137: * the caller is not granted the permission to control 138: * the logging infrastructure. 139: */ 140: public abstract void close() 141: throws SecurityException; 142: 143: 144: /** 145: * Returns the <code>Formatter</code> which will be used to 146: * localize the text of log messages and to substitute 147: * message parameters. A <code>Handler</code> is encouraged, 148: * but not required to actually use an assigned 149: * <code>Formatter</code>. 150: * 151: * @return the <code>Formatter</code> being used, or 152: * <code>null</code> if this <code>Handler</code> 153: * does not use formatters and no formatter has 154: * ever been set by calling <code>setFormatter</code>. 155: */ 156: public Formatter getFormatter() 157: { 158: return formatter; 159: } 160: 161: 162: /** 163: * Sets the <code>Formatter</code> which will be used to 164: * localize the text of log messages and to substitute 165: * message parameters. A <code>Handler</code> is encouraged, 166: * but not required to actually use an assigned 167: * <code>Formatter</code>. 168: * 169: * @param formatter the new <code>Formatter</code> to use. 170: * 171: * @throws SecurityException if a security manager exists and 172: * the caller is not granted the permission to control 173: * the logging infrastructure. 174: * 175: * @throws NullPointerException if <code>formatter</code> is 176: * <code>null</code>. 177: */ 178: public void setFormatter(Formatter formatter) 179: throws SecurityException 180: { 181: LogManager.getLogManager().checkAccess(); 182: 183: /* Throws a NullPointerException if formatter is null. */ 184: formatter.getClass(); 185: 186: this.formatter = formatter; 187: } 188: 189: 190: /** 191: * Returns the character encoding which this handler uses for publishing 192: * log records. 193: * 194: * @return the name of a character encoding, or <code>null</code> 195: * for the default platform encoding. 196: */ 197: public String getEncoding() 198: { 199: return encoding; 200: } 201: 202: 203: /** 204: * Sets the character encoding which this handler uses for publishing 205: * log records. The encoding of a <code>Handler</code> must be 206: * set before any log records have been published. 207: * 208: * @param encoding the name of a character encoding, or <code>null</code> 209: * for the default encoding. 210: * 211: * @exception SecurityException if a security manager exists and 212: * the caller is not granted the permission to control 213: * the logging infrastructure. 214: * 215: */ 216: public void setEncoding(String encoding) 217: throws SecurityException, UnsupportedEncodingException 218: { 219: /* Should any developer ever change this implementation, they are 220: * advised to have a look at StreamHandler.setEncoding(String), 221: * which overrides this method without calling super.setEncoding. 222: */ 223: LogManager.getLogManager().checkAccess(); 224: 225: /* Simple check for supported encodings. This is more expensive 226: * than it could be, but this method is overwritten by StreamHandler 227: * anyway. 228: */ 229: if (encoding != null) 230: new String(new byte[0], encoding); 231: 232: this.encoding = encoding; 233: } 234: 235: 236: /** 237: * Returns the <code>Filter</code> that currently controls which 238: * log records are being published by this <code>Handler</code>. 239: * 240: * @return the currently active <code>Filter</code>, or 241: * <code>null</code> if no filter has been associated. 242: * In the latter case, log records are filtered purely 243: * based on their severity level. 244: */ 245: public Filter getFilter() 246: { 247: return filter; 248: } 249: 250: 251: /** 252: * Sets the <code>Filter</code> for controlling which 253: * log records will be published by this <code>Handler</code>. 254: * 255: * @param filter the <code>Filter</code> to use, or 256: * <code>null</code> to filter log records purely based 257: * on their severity level. 258: */ 259: public void setFilter(Filter filter) 260: throws SecurityException 261: { 262: LogManager.getLogManager().checkAccess(); 263: this.filter = filter; 264: } 265: 266: 267: /** 268: * Returns the <code>ErrorManager</code> that currently deals 269: * with errors originating from this Handler. 270: * 271: * @exception SecurityException if a security manager exists and 272: * the caller is not granted the permission to control 273: * the logging infrastructure. 274: */ 275: public ErrorManager getErrorManager() 276: { 277: LogManager.getLogManager().checkAccess(); 278: 279: /* Developers wanting to change the subsequent code should 280: * have a look at Handler.reportError -- it also can create 281: * an ErrorManager, but does so without checking permissions 282: * to control the logging infrastructure. 283: */ 284: if (errorManager == null) 285: errorManager = new ErrorManager(); 286: 287: return errorManager; 288: } 289: 290: 291: public void setErrorManager(ErrorManager manager) 292: { 293: LogManager.getLogManager().checkAccess(); 294: 295: /* Make sure manager is not null. */ 296: manager.getClass(); 297: 298: this.errorManager = manager; 299: } 300: 301: 302: protected void reportError(String message, Exception ex, int code) 303: { 304: if (errorManager == null) 305: errorManager = new ErrorManager(); 306: 307: errorManager.error(message, ex, code); 308: } 309: 310: 311: /** 312: * Returns the severity level threshold for this <code>Handler</code> 313: * All log records with a lower severity level will be discarded; 314: * a log record of the same or a higher level will be published 315: * unless an installed <code>Filter</code> decides to discard it. 316: * 317: * @return the severity level below which all log messages 318: * will be discarded. 319: */ 320: public Level getLevel() 321: { 322: return level; 323: } 324: 325: 326: /** 327: * Sets the severity level threshold for this <code>Handler</code>. 328: * All log records with a lower severity level will be discarded; 329: * a log record of the same or a higher level will be published 330: * unless an installed <code>Filter</code> decides to discard it. 331: * 332: * @param level the severity level below which all log messages 333: * will be discarded. 334: * 335: * @exception SecurityException if a security manager exists and 336: * the caller is not granted the permission to control 337: * the logging infrastructure. 338: * 339: * @exception NullPointerException if <code>level</code> is 340: * <code>null</code>. 341: */ 342: public void setLevel(Level level) 343: { 344: LogManager.getLogManager().checkAccess(); 345: 346: /* Throw NullPointerException if level is null. */ 347: level.getClass(); 348: this.level = level; 349: } 350: 351: 352: /** 353: * Checks whether a <code>LogRecord</code> would be logged 354: * if it was passed to this <code>Handler</code> for publication. 355: * 356: * <p>The <code>Handler</code> implementation considers a record as 357: * loggable if its level is greater than or equal to the severity 358: * level threshold. In a second step, if a {@link Filter} has 359: * been installed, its {@link Filter#isLoggable(LogRecord) isLoggable} 360: * method is invoked. Subclasses of <code>Handler</code> can override 361: * this method to impose their own constraints. 362: * 363: * @param record the <code>LogRecord</code> to be checked. 364: * 365: * @return <code>true</code> if <code>record</code> would 366: * be published by {@link #publish(LogRecord) publish}, 367: * <code>false</code> if it would be discarded. 368: * 369: * @see #setLevel(Level) 370: * @see #setFilter(Filter) 371: * @see Filter#isLoggable(LogRecord) 372: * 373: * @throws NullPointerException if <code>record</code> 374: * is <code>null</code>. 375: */ 376: public boolean isLoggable(LogRecord record) 377: { 378: if (record.getLevel().intValue() < level.intValue()) 379: return false; 380: 381: if (filter != null) 382: return filter.isLoggable(record); 383: else 384: return true; 385: } 386: }