blob: 85a9e6cb94797ec3409bb465be02282b99356e45 [file] [log] [blame]
/*
* 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();
}
}