|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  |  | 
|  | package java.util.logging; | 
|  |  | 
|  | import java.io.*; | 
|  | import java.net.*; | 
|  |  | 
|  | /** | 
|  |  * Simple network logging {@code Handler}. | 
|  |  * <p> | 
|  |  * {@code LogRecords} are published to a network stream connection.  By default | 
|  |  * the {@code XMLFormatter} class is used for formatting. | 
|  |  * <p> | 
|  |  * <b>Configuration:</b> | 
|  |  * By default each {@code SocketHandler} is initialized using the following | 
|  |  * {@code LogManager} configuration properties where {@code <handler-name>} | 
|  |  * refers to the fully-qualified class name of the handler. | 
|  |  * If properties are not defined | 
|  |  * (or have invalid values) then the specified default values are used. | 
|  |  * <ul> | 
|  |  * <li>   <handler-name>.level | 
|  |  *        specifies the default level for the {@code Handler} | 
|  |  *        (defaults to {@code Level.ALL}). </li> | 
|  |  * <li>   <handler-name>.filter | 
|  |  *        specifies the name of a {@code Filter} class to use | 
|  |  *        (defaults to no {@code Filter}). </li> | 
|  |  * <li>   <handler-name>.formatter | 
|  |  *        specifies the name of a {@code Formatter} class to use | 
|  |  *        (defaults to {@code java.util.logging.XMLFormatter}). </li> | 
|  |  * <li>   <handler-name>.encoding | 
|  |  *        the name of the character set encoding to use (defaults to | 
|  |  *        the default platform encoding). </li> | 
|  |  * <li>   <handler-name>.host | 
|  |  *        specifies the target host name to connect to (no default). </li> | 
|  |  * <li>   <handler-name>.port | 
|  |  *        specifies the target TCP port to use (no default). </li> | 
|  |  * </ul> | 
|  |  * <p> | 
|  |  * For example, the properties for {@code SocketHandler} would be: | 
|  |  * <ul> | 
|  |  * <li>   java.util.logging.SocketHandler.level=INFO </li> | 
|  |  * <li>   java.util.logging.SocketHandler.formatter=java.util.logging.SimpleFormatter </li> | 
|  |  * </ul> | 
|  |  * <p> | 
|  |  * For a custom handler, e.g. com.foo.MyHandler, the properties would be: | 
|  |  * <ul> | 
|  |  * <li>   com.foo.MyHandler.level=INFO </li> | 
|  |  * <li>   com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> | 
|  |  * </ul> | 
|  |  * <p> | 
|  |  * The output IO stream is buffered, but is flushed after each | 
|  |  * {@code LogRecord} is written. | 
|  |  * | 
|  |  * @since 1.4 | 
|  |  */ | 
|  |  | 
|  | public class SocketHandler extends StreamHandler { | 
|  |     private Socket sock; | 
|  |     private String host; | 
|  |     private int port; | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public SocketHandler() throws IOException { | 
|  |          | 
|  |         super(Level.ALL, new XMLFormatter(), null); | 
|  |  | 
|  |         LogManager manager = LogManager.getLogManager(); | 
|  |         String cname = getClass().getName(); | 
|  |         port = manager.getIntProperty(cname + ".port", 0); | 
|  |         host = manager.getStringProperty(cname + ".host", null); | 
|  |  | 
|  |         try { | 
|  |             connect(); | 
|  |         } catch (IOException ix) { | 
|  |             System.err.println("SocketHandler: connect failed to " + host + ":" + port); | 
|  |             throw ix; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public SocketHandler(String host, int port) throws IOException { | 
|  |          | 
|  |         super(Level.ALL, new XMLFormatter(), null); | 
|  |  | 
|  |         this.port = port; | 
|  |         this.host = host; | 
|  |  | 
|  |         connect(); | 
|  |     } | 
|  |  | 
|  |     private void connect() throws IOException { | 
|  |          | 
|  |         if (port == 0) { | 
|  |             throw new IllegalArgumentException("Bad port: " + port); | 
|  |         } | 
|  |         if (host == null) { | 
|  |             throw new IllegalArgumentException("Null host name: " + host); | 
|  |         } | 
|  |  | 
|  |          | 
|  |         sock = new Socket(host, port); | 
|  |         OutputStream out = sock.getOutputStream(); | 
|  |         BufferedOutputStream bout = new BufferedOutputStream(out); | 
|  |         setOutputStreamPrivileged(bout); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public synchronized void close() throws SecurityException { | 
|  |         super.close(); | 
|  |         if (sock != null) { | 
|  |             try { | 
|  |                 sock.close(); | 
|  |             } catch (IOException ix) { | 
|  |                 // drop through. | 
|  |             } | 
|  |         } | 
|  |         sock = null; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public synchronized void publish(LogRecord record) { | 
|  |         if (!isLoggable(record)) { | 
|  |             return; | 
|  |         } | 
|  |         super.publish(record); | 
|  |         flush(); | 
|  |     } | 
|  | } |