Handler.java 13 KB

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