1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package java.util.logging; 28 29 import java.io.UnsupportedEncodingException; 30 /** 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> 76 * The <tt>Handler</tt> is responsible for formatting the message, when and 77 * if necessary. The formatting should include localization. 78 * 79 * @param record description of the log event. A null record is 80 * silently ignored and is not published 81 */ 82 public abstract void publish(LogRecord record); 83 84 /** 85 * Flush any buffered output. 86 */ 87 public abstract void flush(); 88 89 /** 90 * Close the <tt>Handler</tt> and free all associated resources. 91 * <p> 92 * The close method will perform a <tt>flush</tt> and then close the 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 }