1f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.logging; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.BufferedOutputStream; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 229a0fbe99031759393563ee69ac4640f66f182686Jesse Wilsonimport java.net.Socket; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A handler that writes log messages to a socket connection. 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This handler reads the following properties from the log manager to 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * initialize itself: 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.ConsoleHandler.level specifies the logging level, 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * defaults to {@code Level.ALL} if this property is not found or has an invalid 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * value. 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.SocketHandler.filter specifies the name of the filter 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * class to be associated with this handler, defaults to {@code null} if this 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * property is not found or has an invalid value. 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.SocketHandler.formatter specifies the name of the 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * formatter class to be associated with this handler, defaults to 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code java.util.logging.XMLFormatter} if this property is not found or has 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * an invalid value. 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.SocketHandler.encoding specifies the encoding this 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handler will use to encode log messages, defaults to {@code null} if this 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * property is not found or has an invalid value. 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.SocketHandler.host specifies the name of the host that 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this handler should connect to. There's no default value for this property. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>java.util.logging.SocketHandler.encoding specifies the port number that 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this handler should connect to. There's no default value for this property. 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This handler buffers the outgoing messages, but flushes each time a log 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * record has been published. 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class is not thread-safe. 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class SocketHandler extends StreamHandler { 559a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default level 57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String DEFAULT_LEVEL = "ALL"; 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default formatter 60f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String DEFAULT_FORMATTER = "java.util.logging.XMLFormatter"; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the socket connection 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socket socket; 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a {@code SocketHandler} object using the properties read by 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the log manager, including the host name and port number. Default 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * formatting uses the XMLFormatter class and level is set to ALL. 699a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if failed to connect to the specified host and port. 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the host name or port number is illegal. 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SocketHandler() throws IOException { 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project initSocket(LogManager.getLogManager().getProperty( 78f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes "java.util.logging.SocketHandler.host"), LogManager 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getLogManager().getProperty( 80f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes "java.util.logging.SocketHandler.port")); 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a {@code SocketHandler} object using the specified host name 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and port number together with other properties read by the log manager. 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Default formatting uses the XMLFormatter class and level is set to ALL. 879a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if failed to connect to the specified host and port. 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the host name or port number is illegal. 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SocketHandler(String host, int port) throws IOException { 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project initSocket(host, String.valueOf(port)); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Initialize the socket connection and prepare the output stream 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void initSocket(String host, String port) throws IOException { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the validity of the host name 1058454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (host == null || host.isEmpty()) { 1068454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("host == null || host.isEmpty()"); 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the validity of the port number 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int p = 0; 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project p = Integer.parseInt(port); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NumberFormatException e) { 1138454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("Illegal port argument"); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (p <= 0) { 1168454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("Illegal port argument"); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // establish the network connection 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = new Socket(host, p); 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 1228454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes getErrorManager().error("Failed to establish the network connection", e, 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ErrorManager.OPEN_FAILURE); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 126b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes super.internalSetOutputStream(new BufferedOutputStream(this.socket.getOutputStream())); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes this handler. The network connection to the host is also closed. 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.close(); 136b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (this.socket != null) { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket.close(); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = null; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 1418454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes getErrorManager().error("Exception occurred when closing the socket handler", e, 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ErrorManager.CLOSE_FAILURE); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Logs a record if necessary. A flush operation will be done afterwards. 1489a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param record 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the log record to be logged. 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void publish(LogRecord record) { 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.publish(record); 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.flush(); 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 158