1. /*
  2. * @(#)SocketHandler.java 1.18 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.logging;
  8. import java.io.*;
  9. import java.net.*;
  10. /**
  11. * Simple network logging <tt>Handler</tt>.
  12. * <p>
  13. * <tt>LogRecords</tt> are published to a network stream connection. By default
  14. * the <tt>XMLFormatter</tt> class is used for formatting.
  15. * <p>
  16. * <b>Configuration:</b>
  17. * By default each <tt>SocketHandler</tt> is initialized using the following
  18. * <tt>LogManager</tt> configuration properties. If properties are not defined
  19. * (or have invalid values) then the specified default values are used.
  20. * <ul>
  21. * <li> java.util.logging.SocketHandler.level
  22. * specifies the default level for the <tt>Handler</tt>
  23. * (defaults to <tt>Level.ALL</tt>).
  24. * <li> java.util.logging.SocketHandler.filter
  25. * specifies the name of a <tt>Filter</tt> class to use
  26. * (defaults to no <tt>Filter</tt>).
  27. * <li> java.util.logging.SocketHandler.formatter
  28. * specifies the name of a <tt>Formatter</tt> class to use
  29. * (defaults to <tt>java.util.logging.XMLFormatter</tt>).
  30. * <li> java.util.logging.SocketHandler.encoding
  31. * the name of the character set encoding to use (defaults to
  32. * the default platform encoding).
  33. * <li> java.util.logging.SocketHandler.host
  34. * specifies the target host name to connect to (no default).
  35. * <li> java.util.logging.SocketHandler.port
  36. * specifies the target TCP port to use (no default).
  37. * </ul>
  38. * <p>
  39. * The output IO stream is buffered, but is flushed after each
  40. * <tt>LogRecord</tt> is written.
  41. *
  42. * @version 1.18, 12/19/03
  43. * @since 1.4
  44. */
  45. public class SocketHandler extends StreamHandler {
  46. private Socket sock;
  47. private String host;
  48. private int port;
  49. private String portProperty;
  50. // Private method to configure a SocketHandler from LogManager
  51. // properties and/or default values as specified in the class
  52. // javadoc.
  53. private void configure() {
  54. LogManager manager = LogManager.getLogManager();
  55. String cname = getClass().getName();
  56. setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
  57. setFilter(manager.getFilterProperty(cname +".filter", null));
  58. setFormatter(manager.getFormatterProperty(cname +".formatter", new XMLFormatter()));
  59. try {
  60. setEncoding(manager.getStringProperty(cname +".encoding", null));
  61. } catch (Exception ex) {
  62. try {
  63. setEncoding(null);
  64. } catch (Exception ex2) {
  65. // doing a setEncoding with null should always work.
  66. // assert false;
  67. }
  68. }
  69. port = manager.getIntProperty(cname + ".port", 0);
  70. host = manager.getStringProperty(cname + ".host", null);
  71. }
  72. /**
  73. * Create a <tt>SocketHandler</tt>, using only <tt>LogManager</tt> properties
  74. * (or their defaults).
  75. * @throws IllegalArgumentException if the host or port are invalid or
  76. * are not specified as LogManager properties.
  77. * @throws IOException if we are unable to connect to the target
  78. * host and port.
  79. */
  80. public SocketHandler() throws IOException {
  81. // We are going to use the logging defaults.
  82. sealed = false;
  83. configure();
  84. try {
  85. connect();
  86. } catch (IOException ix) {
  87. System.err.println("SocketHandler: connect failed to " + host + ":" + port);
  88. throw ix;
  89. }
  90. sealed = true;
  91. }
  92. /**
  93. * Construct a <tt>SocketHandler</tt> using a specified host and port.
  94. *
  95. * The <tt>SocketHandler</tt> is configured based on <tt>LogManager</tt>
  96. * properties (or their default values) except that the given target host
  97. * and port arguments are used. If the host argument is empty, but not
  98. * null String then the localhost is used.
  99. *
  100. * @param host target host.
  101. * @param port target port.
  102. *
  103. * @throws IllegalArgumentException if the host or port are invalid.
  104. * @throws IOException if we are unable to connect to the target
  105. * host and port.
  106. */
  107. public SocketHandler(String host, int port) throws IOException {
  108. sealed = false;
  109. configure();
  110. sealed = true;
  111. this.port = port;
  112. this.host = host;
  113. connect();
  114. }
  115. private void connect() throws IOException {
  116. // Check the arguments are valid.
  117. if (port == 0) {
  118. throw new IllegalArgumentException("Bad port: " + port);
  119. }
  120. if (host == null) {
  121. throw new IllegalArgumentException("Null host name: " + host);
  122. }
  123. // Try to open a new socket.
  124. sock = new Socket(host, port);
  125. OutputStream out = sock.getOutputStream();
  126. BufferedOutputStream bout = new BufferedOutputStream(out);
  127. setOutputStream(bout);
  128. }
  129. /**
  130. * Close this output stream.
  131. *
  132. * @exception SecurityException if a security manager exists and if
  133. * the caller does not have <tt>LoggingPermission("control")</tt>.
  134. */
  135. public synchronized void close() throws SecurityException {
  136. super.close();
  137. if (sock != null) {
  138. try {
  139. sock.close();
  140. } catch (IOException ix) {
  141. // drop through.
  142. }
  143. }
  144. sock = null;
  145. }
  146. /**
  147. * Format and publish a <tt>LogRecord</tt>.
  148. *
  149. * @param record description of the log event. A null record is
  150. * silently ignored and is not published
  151. */
  152. public synchronized void publish(LogRecord record) {
  153. if (!isLoggable(record)) {
  154. return;
  155. }
  156. super.publish(record);
  157. flush();
  158. }
  159. }