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