1. /*
  2. * @(#)SocketHandler.java 1.13 03/01/23
  3. *
  4. * Copyright 2003 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.13, 01/23/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 = SocketHandler.class.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.
  98. *
  99. * @param host target host.
  100. * @param port target port.
  101. *
  102. * @throws IllegalArgumentException if the host or port are invalid.
  103. * @throws IOException if we are unable to connect to the target
  104. * host and port.
  105. */
  106. public SocketHandler(String host, int port) throws IOException {
  107. sealed = false;
  108. configure();
  109. sealed = true;
  110. this.port = port;
  111. this.host = host;
  112. connect();
  113. }
  114. private void connect() throws IOException {
  115. // Check the arguments are valid.
  116. if (port == 0) {
  117. throw new IllegalArgumentException("Bad port: " + port);
  118. }
  119. if (host == null) {
  120. throw new IllegalArgumentException("Null host name: " + host);
  121. }
  122. // Try to open a new socket.
  123. sock = new Socket(host, port);
  124. OutputStream out = sock.getOutputStream();
  125. BufferedOutputStream bout = new BufferedOutputStream(out);
  126. setOutputStream(bout);
  127. }
  128. /**
  129. * Close this output stream.
  130. *
  131. * @exception SecurityException if a security manager exists and if
  132. * the caller does not have <tt>LoggingPermission("control")</tt>.
  133. */
  134. public synchronized void close() throws SecurityException {
  135. super.close();
  136. if (sock != null) {
  137. try {
  138. sock.close();
  139. } catch (IOException ix) {
  140. // drop through.
  141. }
  142. }
  143. sock = null;
  144. }
  145. /**
  146. * Format and publish a <tt>LogRecord</tt>.
  147. *
  148. * @param record description of the log event
  149. */
  150. public synchronized void publish(LogRecord record) {
  151. if (!isLoggable(record)) {
  152. return;
  153. }
  154. super.publish(record);
  155. flush();
  156. }
  157. }