1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 28 package java.util.logging; 29 30 import java.io.*; 31 import java.net.*; 32 import libcore.net.NetworkSecurityPolicy; 33 34 /** 35 * Simple network logging <tt>Handler</tt>. 36 * <p> 37 * <tt>LogRecords</tt> are published to a network stream connection. By default 38 * the <tt>XMLFormatter</tt> class is used for formatting. 39 * <p> 40 * <b>Configuration:</b> 41 * By default each <tt>SocketHandler</tt> is initialized using the following 42 * <tt>LogManager</tt> configuration properties. If properties are not defined 43 * (or have invalid values) then the specified default values are used. 44 * <ul> 45 * <li> java.util.logging.SocketHandler.level 46 * specifies the default level for the <tt>Handler</tt> 47 * (defaults to <tt>Level.ALL</tt>). 48 * <li> java.util.logging.SocketHandler.filter 49 * specifies the name of a <tt>Filter</tt> class to use 50 * (defaults to no <tt>Filter</tt>). 51 * <li> java.util.logging.SocketHandler.formatter 52 * specifies the name of a <tt>Formatter</tt> class to use 53 * (defaults to <tt>java.util.logging.XMLFormatter</tt>). 54 * <li> java.util.logging.SocketHandler.encoding 55 * the name of the character set encoding to use (defaults to 56 * the default platform encoding). 57 * <li> java.util.logging.SocketHandler.host 58 * specifies the target host name to connect to (no default). 59 * <li> java.util.logging.SocketHandler.port 60 * specifies the target TCP port to use (no default). 61 * </ul> 62 * <p> 63 * The output IO stream is buffered, but is flushed after each 64 * <tt>LogRecord</tt> is written. 65 * 66 * @since 1.4 67 */ 68 69 public class SocketHandler extends StreamHandler { 70 private Socket sock; 71 private String host; 72 private int port; 73 private String portProperty; 74 75 // Private method to configure a SocketHandler from LogManager 76 // properties and/or default values as specified in the class 77 // javadoc. configure()78 private void configure() { 79 LogManager manager = LogManager.getLogManager(); 80 String cname = getClass().getName(); 81 82 setLevel(manager.getLevelProperty(cname +".level", Level.ALL)); 83 setFilter(manager.getFilterProperty(cname +".filter", null)); 84 setFormatter(manager.getFormatterProperty(cname +".formatter", new XMLFormatter())); 85 try { 86 setEncoding(manager.getStringProperty(cname +".encoding", null)); 87 } catch (Exception ex) { 88 try { 89 setEncoding(null); 90 } catch (Exception ex2) { 91 // doing a setEncoding with null should always work. 92 // assert false; 93 } 94 } 95 port = manager.getIntProperty(cname + ".port", 0); 96 host = manager.getStringProperty(cname + ".host", null); 97 } 98 99 100 /** 101 * Create a <tt>SocketHandler</tt>, using only <tt>LogManager</tt> properties 102 * (or their defaults). 103 * @throws IllegalArgumentException if the host or port are invalid or 104 * are not specified as LogManager properties. 105 * @throws IOException if we are unable to connect to the target 106 * host and port. 107 */ SocketHandler()108 public SocketHandler() throws IOException { 109 // We are going to use the logging defaults. 110 sealed = false; 111 configure(); 112 113 try { 114 connect(); 115 } catch (IOException ix) { 116 System.err.println("SocketHandler: connect failed to " + host + ":" + port); 117 throw ix; 118 } 119 sealed = true; 120 } 121 122 /** 123 * Construct a <tt>SocketHandler</tt> using a specified host and port. 124 * 125 * The <tt>SocketHandler</tt> is configured based on <tt>LogManager</tt> 126 * properties (or their default values) except that the given target host 127 * and port arguments are used. If the host argument is empty, but not 128 * null String then the localhost is used. 129 * 130 * @param host target host. 131 * @param port target port. 132 * 133 * @throws IllegalArgumentException if the host or port are invalid. 134 * @throws IOException if we are unable to connect to the target 135 * host and port. 136 */ SocketHandler(String host, int port)137 public SocketHandler(String host, int port) throws IOException { 138 sealed = false; 139 configure(); 140 sealed = true; 141 this.port = port; 142 this.host = host; 143 connect(); 144 } 145 connect()146 private void connect() throws IOException { 147 // Check the arguments are valid. 148 if (port == 0) { 149 throw new IllegalArgumentException("Bad port: " + port); 150 } 151 if (host == null) { 152 throw new IllegalArgumentException("Null host name: " + host); 153 } 154 155 if (!NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted()) { 156 throw new IOException("Cleartext traffic not permitted"); 157 } 158 159 // Try to open a new socket. 160 sock = new Socket(host, port); 161 OutputStream out = sock.getOutputStream(); 162 BufferedOutputStream bout = new BufferedOutputStream(out); 163 setOutputStream(bout); 164 } 165 166 /** 167 * Close this output stream. 168 * 169 * @exception SecurityException if a security manager exists and if 170 * the caller does not have <tt>LoggingPermission("control")</tt>. 171 */ close()172 public synchronized void close() throws SecurityException { 173 super.close(); 174 if (sock != null) { 175 try { 176 sock.close(); 177 } catch (IOException ix) { 178 // drop through. 179 } 180 } 181 sock = null; 182 } 183 184 /** 185 * Format and publish a <tt>LogRecord</tt>. 186 * 187 * @param record description of the log event. A null record is 188 * silently ignored and is not published 189 */ publish(LogRecord record)190 public synchronized void publish(LogRecord record) { 191 if (!isLoggable(record)) { 192 return; 193 } 194 super.publish(record); 195 flush(); 196 } 197 } 198