Handler.java |
1 /* 2 * %W% %E% 3 * 4 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 5 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 */ 7 8 9 package java.util.logging; 10 11 import java.io.UnsupportedEncodingException; 12 /** 13 * A <tt>Handler</tt> object takes log messages from a <tt>Logger</tt> and 14 * exports them. It might for example, write them to a console 15 * or write them to a file, or send them to a network logging service, 16 * or forward them to an OS log, or whatever. 17 * <p> 18 * A <tt>Handler</tt> can be disabled by doing a <tt>setLevel(Level.OFF)</tt> 19 * and can be re-enabled by doing a <tt>setLevel</tt> with an appropriate level. 20 * <p> 21 * <tt>Handler</tt> classes typically use <tt>LogManager</tt> properties to set 22 * default values for the <tt>Handler</tt>'s <tt>Filter</tt>, <tt>Formatter</tt>, 23 * and <tt>Level</tt>. See the specific documentation for each concrete 24 * <tt>Handler</tt> class. 25 * 26 * 27 * @version %I%, %G% 28 * @since 1.4 29 */ 30 31 public abstract class Handler { 32 private static final int offValue = Level.OFF.intValue(); 33 private LogManager manager = LogManager.getLogManager(); 34 private Filter filter; 35 private Formatter formatter; 36 private Level logLevel = Level.ALL; 37 private ErrorManager errorManager = new ErrorManager(); 38 private String encoding; 39 40 // Package private support for security checking. When sealed 41 // is true, we access check updates to the class. 42 boolean sealed = true; 43 44 /** 45 * Default constructor. The resulting <tt>Handler</tt> has a log 46 * level of <tt>Level.ALL</tt>, no <tt>Formatter</tt>, and no 47 * <tt>Filter</tt>. A default <tt>ErrorManager</tt> instance is installed 48 * as the <tt>ErrorManager</tt>. 49 */ 50 protected Handler() { 51 } 52 53 /** 54 * Publish a <tt>LogRecord</tt>. 55 * <p> 56 * The logging request was made initially to a <tt>Logger</tt> object, 57 * which initialized the <tt>LogRecord</tt> and forwarded it here. 58 * <p> 59 * The <tt>Handler</tt> is responsible for formatting the message, when and 60 * if necessary. The formatting should include localization. 61 * 62 * @param record description of the log event. A null record is 63 * silently ignored and is not published 64 */ 65 public abstract void publish(LogRecord record); 66 67 /** 68 * Flush any buffered output. 69 */ 70 public abstract void flush(); 71 72 /** 73 * Close the <tt>Handler</tt> and free all associated resources. 74 * <p> 75 * The close method will perform a <tt>flush</tt> and then close the 76 * <tt>Handler</tt>. After close has been called this <tt>Handler</tt> 77 * should no longer be used. Method calls may either be silently 78 * ignored or may throw runtime exceptions. 79 * 80 * @exception SecurityException if a security manager exists and if 81 * the caller does not have <tt>LoggingPermission("control")</tt>. 82 */ 83 public abstract void close() throws SecurityException; 84 85 /** 86 * Set a <tt>Formatter</tt>. This <tt>Formatter</tt> will be used 87 * to format <tt>LogRecords</tt> for this <tt>Handler</tt>. 88 * <p> 89 * Some <tt>Handlers</tt> may not use <tt>Formatters</tt>, in 90 * which case the <tt>Formatter</tt> will be remembered, but not used. 91 * <p> 92 * @param newFormatter the <tt>Formatter</tt> to use (may not be null) 93 * @exception SecurityException if a security manager exists and if 94 * the caller does not have <tt>LoggingPermission("control")</tt>. 95 */ 96 public void setFormatter(Formatter newFormatter) throws SecurityException { 97 checkAccess(); 98 // Check for a null pointer: 99 newFormatter.getClass(); 100 formatter = newFormatter; 101 } 102 103 /** 104 * Return the <tt>Formatter</tt> for this <tt>Handler</tt>. 105 * @return the <tt>Formatter</tt> (may be null). 106 */ 107 public Formatter getFormatter() { 108 return formatter; 109 } 110 111 /** 112 * Set the character encoding used by this <tt>Handler</tt>. 113 * <p> 114 * The encoding should be set before any <tt>LogRecords</tt> are written 115 * to the <tt>Handler</tt>. 116 * 117 * @param encoding The name of a supported character encoding. 118 * May be null, to indicate the default platform encoding. 119 * @exception SecurityException if a security manager exists and if 120 * the caller does not have <tt>LoggingPermission("control")</tt>. 121 * @exception UnsupportedEncodingException if the named encoding is 122 * not supported. 123 */ 124 public void setEncoding(String encoding) 125 throws SecurityException, java.io.UnsupportedEncodingException { 126 checkAccess(); 127 if (encoding != null) { 128 try { 129 if(!java.nio.charset.Charset.isSupported(encoding)) { 130 throw new UnsupportedEncodingException(encoding); 131 } 132 } catch (java.nio.charset.IllegalCharsetNameException e) { 133 throw new UnsupportedEncodingException(encoding); 134 } 135 } 136 this.encoding = encoding; 137 } 138 139 /** 140 * Return the character encoding for this <tt>Handler</tt>. 141 * 142 * @return The encoding name. May be null, which indicates the 143 * default encoding should be used. 144 */ 145 public String getEncoding() { 146 return encoding; 147 } 148 149 /** 150 * Set a <tt>Filter</tt> to control output on this <tt>Handler</tt>. 151 * <P> 152 * For each call of <tt>publish</tt> the <tt>Handler</tt> will call 153 * this <tt>Filter</tt> (if it is non-null) to check if the 154 * <tt>LogRecord</tt> should be published or discarded. 155 * 156 * @param newFilter a <tt>Filter</tt> object (may be null) 157 * @exception SecurityException if a security manager exists and if 158 * the caller does not have <tt>LoggingPermission("control")</tt>. 159 */ 160 public void setFilter(Filter newFilter) throws SecurityException { 161 checkAccess(); 162 filter = newFilter; 163 } 164 165 /** 166 * Get the current <tt>Filter</tt> for this <tt>Handler</tt>. 167 * 168 * @return a <tt>Filter</tt> object (may be null) 169 */ 170 public Filter getFilter() { 171 return filter; 172 } 173 174 /** 175 * Define an ErrorManager for this Handler. 176 * <p> 177 * The ErrorManager's "error" method will be invoked if any 178 * errors occur while using this Handler. 179 * 180 * @param em the new ErrorManager 181 * @exception SecurityException if a security manager exists and if 182 * the caller does not have <tt>LoggingPermission("control")</tt>. 183 */ 184 public void setErrorManager(ErrorManager em) { 185 checkAccess(); 186 if (em == null) { 187 throw new NullPointerException(); 188 } 189 errorManager = em; 190 } 191 192 /** 193 * Retrieves the ErrorManager for this Handler. 194 * 195 * @exception SecurityException if a security manager exists and if 196 * the caller does not have <tt>LoggingPermission("control")</tt>. 197 */ 198 public ErrorManager getErrorManager() { 199 checkAccess(); 200 return errorManager; 201 } 202 203 /** 204 * Protected convenience method to report an error to this Handler's 205 * ErrorManager. Note that this method retrieves and uses the ErrorManager 206 * without doing a security check. It can therefore be used in 207 * environments where the caller may be non-privileged. 208 * 209 * @param msg a descriptive string (may be null) 210 * @param ex an exception (may be null) 211 * @param code an error code defined in ErrorManager 212 */ 213 protected void reportError(String msg, Exception ex, int code) { 214 try { 215 errorManager.error(msg, ex, code); 216 } catch (Exception ex2) { 217 System.err.println("Handler.reportError caught:"); 218 ex2.printStackTrace(); 219 } 220 } 221 222 /** 223 * Set the log level specifying which message levels will be 224 * logged by this <tt>Handler</tt>. Message levels lower than this 225 * value will be discarded. 226 * <p> 227 * The intention is to allow developers to turn on voluminous 228 * logging, but to limit the messages that are sent to certain 229 * <tt>Handlers</tt>. 230 * 231 * @param newLevel the new value for the log level 232 * @exception SecurityException if a security manager exists and if 233 * the caller does not have <tt>LoggingPermission("control")</tt>. 234 */ 235 public synchronized void setLevel(Level newLevel) throws SecurityException { 236 if (newLevel == null) { 237 throw new NullPointerException(); 238 } 239 checkAccess(); 240 logLevel = newLevel; 241 } 242 243 /** 244 * Get the log level specifying which messages will be 245 * logged by this <tt>Handler</tt>. Message levels lower 246 * than this level will be discarded. 247 * @return the level of messages being logged. 248 */ 249 public synchronized Level getLevel() { 250 return logLevel; 251 } 252 253 /** 254 * Check if this <tt>Handler</tt> would actually log a given <tt>LogRecord</tt>. 255 * <p> 256 * This method checks if the <tt>LogRecord</tt> has an appropriate 257 * <tt>Level</tt> and whether it satisfies any <tt>Filter</tt>. It also 258 * may make other <tt>Handler</tt> specific checks that might prevent a 259 * handler from logging the <tt>LogRecord</tt>. It will return false if 260 * the <tt>LogRecord</tt> is Null. 261 * <p> 262 * @param record a <tt>LogRecord</tt> 263 * @return true if the <tt>LogRecord</tt> would be logged. 264 * 265 */ 266 public boolean isLoggable(LogRecord record) { 267 int levelValue = getLevel().intValue(); 268 if (record.getLevel().intValue() < levelValue || levelValue == offValue) { 269 return false; 270 } 271 Filter filter = getFilter(); 272 if (filter == null) { 273 return true; 274 } 275 return filter.isLoggable(record); 276 } 277 278 // Package-private support method for security checks. 279 // If "sealed" is true, we check that the caller has 280 // appropriate security privileges to update Handler 281 // state and if not throw a SecurityException. 282 void checkAccess() throws SecurityException { 283 if (sealed) { 284 manager.checkAccess(); 285 } 286 } 287 } 288