SocketHandler.java revision 8454d3c5b9778ae359d11cd98ed81c589e951d0a
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 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 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 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 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final String DEFAULT_LEVEL = "ALL"; //$NON-NLS-1$ 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default formatter 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final String DEFAULT_FORMATTER = "java.util.logging.XMLFormatter"; //$NON-NLS-1$ 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 * @throws SecurityException 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a security manager determines that the caller does not 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * have the required permission to control this handler. 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SocketHandler() throws IOException { 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project initSocket(LogManager.getLogManager().getProperty( 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "java.util.logging.SocketHandler.host"), LogManager //$NON-NLS-1$ 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getLogManager().getProperty( 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "java.util.logging.SocketHandler.port")); //$NON-NLS-1$ 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a {@code SocketHandler} object using the specified host name 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and port number together with other properties read by the log manager. 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Default formatting uses the XMLFormatter class and level is set to ALL. 909a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if failed to connect to the specified host and port. 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the host name or port number is illegal. 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SecurityException 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a security manager determines that the caller does not 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * have the required permission to control this handler. 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SocketHandler(String host, int port) throws IOException { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project initSocket(host, String.valueOf(port)); 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Initialize the socket connection and prepare the output stream 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void initSocket(String host, String port) throws IOException { 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the validity of the host name 1118454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (host == null || host.isEmpty()) { 1128454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("host == null || host.isEmpty()"); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check the validity of the port number 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int p = 0; 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project p = Integer.parseInt(port); 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (NumberFormatException e) { 1198454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("Illegal port argument"); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (p <= 0) { 1228454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("Illegal port argument"); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // establish the network connection 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = new Socket(host, p); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 1288454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes getErrorManager().error("Failed to establish the network connection", e, 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ErrorManager.OPEN_FAILURE); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes super.internalSetOutputStream(new BufferedOutputStream(this.socket.getOutputStream())); 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes this handler. The network connection to the host is also closed. 1379a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SecurityException 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If a security manager determines that the caller does not 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * have the required permission to control this handler. 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() { 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.close(); 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null != this.socket) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket.close(); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = null; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 1518454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes getErrorManager().error("Exception occurred when closing the socket handler", e, 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ErrorManager.CLOSE_FAILURE); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Logs a record if necessary. A flush operation will be done afterwards. 1589a0fbe99031759393563ee69ac4640f66f182686Jesse Wilson * 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param record 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the log record to be logged. 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void publish(LogRecord record) { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.publish(record); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.flush(); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 168