001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.util.logging;
019:
020: import java.io.BufferedOutputStream;
021: import java.io.IOException;
022: import java.net.Socket;
023:
024: import org.apache.harmony.logging.internal.nls.Messages;
025:
026: /**
027: * A handler that writes log messages to a socket connection.
028: * <p>
029: * This handler reads the following properties from the log manager to
030: * initialize itself:
031: * <ul>
032: * <li>java.util.logging.ConsoleHandler.level specifies the logging level,
033: * defaults to <code>Level.ALL</code> if this property is not found or has an
034: * invalid value;
035: * <li>java.util.logging.SocketHandler.filter specifies the name of the filter
036: * class to be associated with this handler, defaults to <code>null</code> if
037: * this property is not found or has an invalid value;
038: * <li>java.util.logging.SocketHandler.formatter specifies the name of the
039: * formatter class to be associated with this handler, defaults to
040: * <code>java.util.logging.XMLFormatter</code> if this property is not found
041: * or has an invalid value;
042: * <li>java.util.logging.SocketHandler.encoding specifies the encoding this
043: * handler will use to encode log messages, defaults to <code>null</code> if
044: * this property is not found or has an invalid value.
045: * <li>java.util.logging.SocketHandler.host specifies the name of the host that
046: * this handler should connect to. There's no default value for this property.
047: * <li>java.util.logging.SocketHandler.encoding specifies the port number that
048: * this handler should connect to. There's no default value for this property.
049: * </ul>
050: * </p>
051: * <p>
052: * This handler buffers the outgoing messages, but flushes each time a log
053: * record has been published.
054: * </p>
055: * <p>
056: * This class is not thread-safe.
057: * </p>
058: */
059: public class SocketHandler extends StreamHandler {
060:
061: // default level
062: private static final String DEFAULT_LEVEL = "ALL"; //$NON-NLS-1$
063:
064: // default formatter
065: private static final String DEFAULT_FORMATTER = "java.util.logging.XMLFormatter"; //$NON-NLS-1$
066:
067: // the socket connection
068: private Socket socket;
069:
070: /**
071: * Constructs a <code>SocketHandler</code> object using the properties
072: * read by the log manager, including the host name and port number.
073: *
074: * @throws IOException
075: * If failed to connect to the specified host and port.
076: * @throws IllegalArgumentException
077: * If the host name or port number is illegal.
078: * @throws SecurityException
079: * If a security manager determines that the caller does not
080: * have the required permission to control this handler.
081: */
082: public SocketHandler() throws IOException {
083: super (DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null);
084: initSocket(LogManager.getLogManager().getProperty(
085: "java.util.logging.SocketHandler.host"), LogManager //$NON-NLS-1$
086: .getLogManager().getProperty(
087: "java.util.logging.SocketHandler.port")); //$NON-NLS-1$
088: }
089:
090: /**
091: * Constructs a <code>SocketHandler</code> object using the specified host
092: * name and port number together with other properties read by the log
093: * manager.
094: *
095: * @param host
096: * the host name
097: * @param port
098: * the port number
099: * @throws IOException
100: * If failed to connect to the specified host and port.
101: * @throws IllegalArgumentException
102: * If the host name or port number is illegal.
103: * @throws SecurityException
104: * If a security manager determines that the caller does not
105: * have the required permission to control this handler.
106: */
107: public SocketHandler(String host, int port) throws IOException {
108: super (DEFAULT_LEVEL, null, DEFAULT_FORMATTER, null);
109: initSocket(host, String.valueOf(port));
110: }
111:
112: // Initialize the socket connection and prepare the output stream
113: private void initSocket(String host, String port)
114: throws IOException {
115: // check the validity of the host name
116: if (null == host || "".equals(host)) { //$NON-NLS-1$
117: // logging.C=Illegal host argument.
118: throw new IllegalArgumentException(Messages
119: .getString("logging.C")); //$NON-NLS-1$
120: }
121: // check the validity of the port number
122: int p = 0;
123: try {
124: p = Integer.parseInt(port);
125: } catch (NumberFormatException e) {
126: // logging.D=Illegal port argument.
127: throw new IllegalArgumentException(Messages
128: .getString("logging.D")); //$NON-NLS-1$
129: }
130: if (p <= 0) {
131: // logging.D=Illegal port argument.
132: throw new IllegalArgumentException(Messages
133: .getString("logging.D")); //$NON-NLS-1$
134: }
135: // establish the network connection
136: try {
137: this .socket = new Socket(host, p);
138: } catch (IOException e) {
139: // logging.E=Failed to establish the network connection.
140: getErrorManager().error(Messages.getString("logging.E"), e, //$NON-NLS-1$
141: ErrorManager.OPEN_FAILURE);
142: throw e;
143: }
144: super .internalSetOutputStream(new BufferedOutputStream(
145: this .socket.getOutputStream()));
146: }
147:
148: /**
149: * Closes this handler. The network connection to the host is also closed.
150: *
151: * @throws SecurityException
152: * If a security manager determines that the caller does not
153: * have the required permission to control this handler.
154: */
155: @Override
156: public void close() {
157: try {
158: super .close();
159: if (null != this .socket) {
160: this .socket.close();
161: this .socket = null;
162: }
163: } catch (Exception e) {
164: // logging.F=Exception occurred when closing the socket handler.
165: getErrorManager().error(Messages.getString("logging.F"), e, //$NON-NLS-1$
166: ErrorManager.CLOSE_FAILURE);
167: }
168: }
169:
170: /**
171: * Logs a record if necessary. A flush operation will be done afterwards.
172: *
173: * @param record
174: * the log record to be logged
175: */
176: @Override
177: public void publish(LogRecord record) {
178: super.publish(record);
179: super.flush();
180: }
181: }
|