/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.util.logging; import java.io.BufferedOutputStream; import java.io.IOException; import java.net.Socket; /** * A handler that writes log messages to a socket connection. * <p> * This handler reads the following properties from the log manager to * initialize itself: * <ul> * <li>java.util.logging.ConsoleHandler.level specifies the logging level, * defaults to {@code Level.ALL} if this property is not found or has an invalid * value. * <li>java.util.logging.SocketHandler.filter specifies the name of the filter * class to be associated with this handler, defaults to {@code null} if this * property is not found or has an invalid value. * <li>java.util.logging.SocketHandler.formatter specifies the name of the * formatter class to be associated with this handler, defaults to * {@code java.util.logging.XMLFormatter} if this property is not found or has * an invalid value. * <li>java.util.logging.SocketHandler.encoding specifies the encoding this * handler will use to encode log messages, defaults to {@code null} if this * property is not found or has an invalid value. * <li>java.util.logging.SocketHandler.host specifies the name of the host that * this handler should connect to. There's no default value for this property. * <li>java.util.logging.SocketHandler.encoding specifies the port number that * this handler should connect to. There's no default value for this property. * </ul> * <p> * This handler buffers the outgoing messages, but flushes each time a log * record has been published. * <p> * This class is not thread-safe. */ public class SocketHandler extends StreamHandler { // default level private static final String DEFAULT_LEVEL = "ALL"; // default formatter private static final String DEFAULT_FORMATTER = "java.util.logging.XMLFormatter"; // the socket connection private Socket socket; /** * Constructs a {@code SocketHandler} object using the properties read by * the log manager, including the host name and port number. Default * formatting uses the XMLFormatter class and level is set to ALL. * * @throws IOException * if failed to connect to the specified host and port. * @throws IllegalArgumentException * if the host name or port number is illegal. */ public SocketHandler() throws IOException { super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); initSocket(LogManager.getLogManager().getProperty( "java.util.logging.SocketHandler.host"), LogManager .getLogManager().getProperty( "java.util.logging.SocketHandler.port")); } /** * Constructs a {@code SocketHandler} object using the specified host name * and port number together with other properties read by the log manager. * Default formatting uses the XMLFormatter class and level is set to ALL. * * @param host * the host name * @param port * the port number * @throws IOException * if failed to connect to the specified host and port. * @throws IllegalArgumentException * if the host name or port number is illegal. */ public SocketHandler(String host, int port) throws IOException { super(DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null); initSocket(host, String.valueOf(port)); } // Initialize the socket connection and prepare the output stream private void initSocket(String host, String port) throws IOException { // check the validity of the host name if (host == null || host.isEmpty()) { throw new IllegalArgumentException("host == null || host.isEmpty()"); } // check the validity of the port number int p = 0; try { p = Integer.parseInt(port); } catch (NumberFormatException e) { throw new IllegalArgumentException("Illegal port argument"); } if (p <= 0) { throw new IllegalArgumentException("Illegal port argument"); } // establish the network connection try { this.socket = new Socket(host, p); } catch (IOException e) { getErrorManager().error("Failed to establish the network connection", e, ErrorManager.OPEN_FAILURE); throw e; } super.internalSetOutputStream(new BufferedOutputStream(this.socket.getOutputStream())); } /** * Closes this handler. The network connection to the host is also closed. */ @Override public void close() { try { super.close(); if (this.socket != null) { this.socket.close(); this.socket = null; } } catch (Exception e) { getErrorManager().error("Exception occurred when closing the socket handler", e, ErrorManager.CLOSE_FAILURE); } } /** * Logs a record if necessary. A flush operation will be done afterwards. * * @param record * the log record to be logged. */ @Override public void publish(LogRecord record) { super.publish(record); super.flush(); } }