1 /* 2 * Copyright (c) 2000, 2012, 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.*; 30 import java.net.*; 31 32 /** 33 * Simple network logging <tt>Handler</tt>. 34 * <p> 35 * <tt>LogRecords</tt> are published to a network stream connection. By default 36 * the <tt>XMLFormatter</tt> class is used for formatting. 37 * <p> 38 * <b>Configuration:</b> 39 * By default each <tt>SocketHandler</tt> is initialized using the following 40 * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> 41 * refers to the fully-qualified class name of the handler. 42 * If properties are not defined 43 * (or have invalid values) then the specified default values are used. 44 * <ul> 45 * <li> <handler-name>.level 46 * specifies the default level for the <tt>Handler</tt> 47 * (defaults to <tt>Level.ALL</tt>). </li> 48 * <li> <handler-name>.filter 49 * specifies the name of a <tt>Filter</tt> class to use 50 * (defaults to no <tt>Filter</tt>). </li> 51 * <li> <handler-name>.formatter 52 * specifies the name of a <tt>Formatter</tt> class to use 53 * (defaults to <tt>java.util.logging.XMLFormatter</tt>). </li> 54 * <li> <handler-name>.encoding 55 * the name of the character set encoding to use (defaults to 56 * the default platform encoding). </li> 57 * <li> <handler-name>.host 58 * specifies the target host name to connect to (no default). </li> 59 * <li> <handler-name>.port 60 * specifies the target TCP port to use (no default). </li> 61 * </ul> 62 * <p> 63 * For example, the properties for {@code SocketHandler} would be: 64 * <ul> 65 * <li> java.util.logging.SocketHandler.level=INFO </li> 66 * <li> java.util.logging.SocketHandler.formatter=java.util.logging.SimpleFormatter </li> 67 * </ul> 68 * <p> 69 * For a custom handler, e.g. com.foo.MyHandler, the properties would be: 70 * <ul> 71 * <li> com.foo.MyHandler.level=INFO </li> 72 * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> 73 * </ul> 74 * <p> 75 * The output IO stream is buffered, but is flushed after each 76 * <tt>LogRecord</tt> is written. 77 * 78 * @since 1.4 79 */ 80 81 public class SocketHandler extends StreamHandler { 82 private Socket sock; 83 private String host; 84 private int port; 85 86 // Package-private support for configuring various properties 87 // with specified/configured/default values 88 89 @Override 90 Level getDefaultLevel() { return Level.ALL; } 91 92 @Override 93 Formatter getDefaultFormatter() { return new XMLFormatter(); } 94 95 /** 96 * Create a <tt>SocketHandler</tt>, using only <tt>LogManager</tt> properties 97 * (or their defaults). 98 * @throws IllegalArgumentException if the host or port are invalid or 99 * are not specified as LogManager properties. 100 * @throws IOException if we are unable to connect to the target 101 * host and port. 102 */ 103 public SocketHandler() throws IOException { 104 // We are going to use the logging defaults. 105 LogManager manager = LogManager.getLogManager(); 106 String cname = getClass().getName(); 107 port = manager.getIntProperty(cname + ".port", 0); 108 host = manager.getStringProperty(cname + ".host", null); 109 110 try { 111 connect(); 112 } catch (IOException ix) { 113 System.err.println("SocketHandler: connect failed to " + host + ":" + port); 114 throw ix; 115 } 116 } 117 118 /** 119 * Construct a <tt>SocketHandler</tt> using a specified host and port. 120 * 121 * The <tt>SocketHandler</tt> is configured based on <tt>LogManager</tt> 122 * properties (or their default values) except that the given target host 123 * and port arguments are used. If the host argument is empty, but not 124 * null String then the localhost is used. 125 * 126 * @param host target host. 127 * @param port target port. 128 * 129 * @throws IllegalArgumentException if the host or port are invalid. 130 * @throws IOException if we are unable to connect to the target 131 * host and port. 132 */ 133 public SocketHandler(String host, int port) throws IOException { 134 this.port = port; 135 this.host = host; 136 connect(); 137 } 138 139 private void connect() throws IOException { 140 // Check the arguments are valid. 141 if (port == 0) { 142 throw new IllegalArgumentException("Bad port: " + port); 143 } 144 if (host == null) { 145 throw new IllegalArgumentException("Null host name: " + host); 146 } 147 148 // Try to open a new socket. 149 sock = new Socket(host, port); 150 OutputStream out = sock.getOutputStream(); 151 BufferedOutputStream bout = new BufferedOutputStream(out); 152 setOutputStreamPrivileged(bout); 153 } 154 155 /** 156 * Close this output stream. 157 * 158 * @exception SecurityException if a security manager exists and if 159 * the caller does not have <tt>LoggingPermission("control")</tt>. 160 */ 161 @Override 162 public synchronized void close() throws SecurityException { 163 super.close(); 164 if (sock != null) { 165 try { 166 sock.close(); 167 } catch (IOException ix) { 168 // drop through. 169 } 170 } 171 sock = null; 172 } 173 174 /** 175 * Format and publish a <tt>LogRecord</tt>. 176 * 177 * @param record description of the log event. A null record is 178 * silently ignored and is not published 179 */ 180 @Override 181 public synchronized void publish(LogRecord record) { 182 if (!isLoggable(record)) { 183 return; 184 } 185 super.publish(record); 186 flush(); 187 } 188 }