8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: FileHandler.java,v 1.14 2009/07/27 19:50:55 bigfatrat Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura * Portions Copyrighted 2011-2014 ForgeRock AS
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura * Portions Copyrighted 2014 Nomura Research Institute, Ltd
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.sun.identity.log.handlers;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.BufferedOutputStream;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.File;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.FileInputStream;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.FileOutputStream;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.IOException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.OutputStream;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.OutputStreamWriter;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.UnsupportedEncodingException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.Writer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.text.SimpleDateFormat;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Iterator;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.LinkedList;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Date;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.logging.Formatter;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.logging.Level;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.logging.LogRecord;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.am.util.ThreadPoolException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.log.NullLocationException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.common.GeneralTaskRunnable;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.common.SystemTimer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.log.LogConstants;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.log.LogManager;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.log.LogManagerUtil;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.log.Logger;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.log.spi.Debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.monitoring.Agent;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.monitoring.MonitoringUtil;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.monitoring.SsoServerLoggingHdlrEntryImpl;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.monitoring.SsoServerLoggingSvcImpl;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.io.FileNotFoundException;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Calendar;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This <tt> FileHandler </tt> is very much similar to the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <t> java.util.logging.FileHandler </tt>. <p> The <TT> FileHandler </TT>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * can either write to a specified file, or it can write to a rotating set
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of files. <P>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * For a rotating set of files, as each file reaches the limit
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (<i> LogConstants.MAX_FILE_SIZE</I>), it is closed, rotated out, and a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * new file opened. Successively older files and named by adding "-1", "-2",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * etc., * to the base filename. The Locking mechanism is much more relaxed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (in JDK's FileHandler an exclusive lock is created on the file till the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * handler is closed which makes reading impossible)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class FileHandler extends java.util.logging.Handler {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private LogManager lmanager = LogManagerUtil.getLogManager();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private OutputStream output;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Writer writer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private MeteredStream meteredStream;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private File files[];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean headerWritten;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int count; // count represent number of history files
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura private long maxFileSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String location;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Formatter formatter;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String fileName;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int recCountLimit;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private LinkedList recordBuffer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private TimeBufferingTask bufferTask;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean timeBufferingEnabled = false;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura private boolean rotateEnabled = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String headerString = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private SsoServerLoggingSvcImpl logServiceImplForMonitoring = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private SsoServerLoggingHdlrEntryImpl fileLogHandlerForMonitoring = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int rotationInterval = -1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private long lastRotation;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * By default the size based rotation is enabled
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean rotatingBySize = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static final String DEFAULT_LOG_SUFFIX_FORMAT = "-MM.dd.yy-kk.mm";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private class MeteredStream extends OutputStream {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster OutputStream out;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura String filename = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura MeteredStream(File fileName, boolean append) throws IOException {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura this.filename = fileName.toString();
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura FileOutputStream fout = new FileOutputStream(filename, append);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura this.out = new BufferedOutputStream(fout);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * writes a single integer to the outputstream and increments
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the number of bytes written by one.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param b integer value to be written.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws IOException if it fails to write out.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void write(int b) throws IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster out.write(b);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Writes the array of bytes to the output stream and increments
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the number of bytes written by the size of the array.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param b the byte array to be written.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws IOException if it fails to write out.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void write(byte[] b) throws IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster out.write(b);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Writes the array of bytes to the output stream and increments
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the number of bytes written by the size of the array.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param b the byte array to be written.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param offset the offset of array to be written.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param length the length of bytes to be written.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws IOException if it fails to write out.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void write(byte[] b, int offset, int length)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throws IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster out.write(b, offset, length);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Flush any buffered messages.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws IOException if it fails to write out.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void flush() throws IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster out.flush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * close the current output stream.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws IOException if it fails to close output stream.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void close() throws IOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster out.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * sets the output stream to the specified output stream ..picked up from
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * StreamHandler.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void setOutputStream(OutputStream out) throws SecurityException,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster UnsupportedEncodingException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (out == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.warningEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.warning(fileName + ":FileHandler: OutputStream is null");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster output = out;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerWritten = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String encoding = getEncoding();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (encoding == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer = new OutputStreamWriter(output);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer = new OutputStreamWriter(output, encoding);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (UnsupportedEncodingException e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: Unsupported Encoding", e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new UnsupportedEncodingException(e.getMessage());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Set (or change) the character encoding used by this <tt>Handler</tt>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The encoding should be set before any <tt>LogRecords</tt> are written
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * to the <tt>Handler</tt>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param encoding The name of a supported character encoding.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * May be null, to indicate the default platform encoding.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception SecurityException if a security manager exists and if
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the caller does not have
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <tt>LoggingPermission("control")</tt>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception UnsupportedEncodingException if the named encoding is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * not supported.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void setEncoding(String encoding) throws SecurityException,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster UnsupportedEncodingException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster super.setEncoding(encoding);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (output == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Replace the current writer with a writer for the new encoding.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cleanup();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (encoding == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer = new OutputStreamWriter(output);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer = new OutputStreamWriter(output, encoding);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method is used for getting the properties from LogManager
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and setting the private variables count, maxFileSize etc.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void configure()
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throws NullLocationException, FormatterInitException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String bufferSize = lmanager.getProperty(LogConstants.BUFFER_SIZE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (bufferSize != null && bufferSize.length() > 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recCountLimit = Integer.parseInt(bufferSize);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (NumberFormatException nfe) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.warning(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: NumberFormatException ", nfe);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: Setting buffer size to 1");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recCountLimit = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.warning(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: Invalid buffer size: " + bufferSize);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: Setting buffer size to 1");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recCountLimit = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String status = lmanager.getProperty(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogConstants.TIME_BUFFERING_STATUS);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (status != null && status.equalsIgnoreCase("ON")) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster timeBufferingEnabled = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String strCount = lmanager.getProperty(LogConstants.NUM_HISTORY_FILES);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((strCount == null) || (strCount.length() == 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster count = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster count = Integer.parseInt(strCount);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String strMaxFileSize = lmanager.getProperty(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogConstants.MAX_FILE_SIZE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((strMaxFileSize == null) || (strMaxFileSize.length() == 0)) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura maxFileSize = 0L;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura maxFileSize = Long.parseLong(strMaxFileSize);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster location = lmanager.getProperty(LogConstants.LOG_LOCATION);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((location == null) || (location.length() == 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new NullLocationException(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "Location Not Specified"); //localize
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!location.endsWith(File.separator)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster location += File.separator;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String strFormatter = lmanager.getProperty(LogConstants.ELF_FORMATTER);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Class clz = Class.forName(strFormatter);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster formatter = (Formatter) clz.newInstance();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new FormatterInitException(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "Unable to initialize Formatter Class" + e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura String strRotateEnabled = lmanager.getProperty(LogConstants.ENABLE_ROTATION);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (strRotateEnabled != null && !strRotateEnabled.isEmpty()) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura rotateEnabled = Boolean.parseBoolean(strRotateEnabled);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotateEnabled) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura String rotation = lmanager.getProperty(LogConstants.LOGFILE_ROTATION);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura try {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotation != null) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura rotationInterval = Integer.parseInt(rotation);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura } catch (NumberFormatException nfe) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura //if we cannot parse it, then we use the size based rotation
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura rotationInterval = -1;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotationInterval > 0) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura lastRotation = System.currentTimeMillis();
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura rotatingBySize = false;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void openFiles(String fileName) throws IOException {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotateEnabled && rotatingBySize) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // make sure that we have a valid maxFileSize
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (maxFileSize < 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + ":FileHandler: maxFileSize cannot be negative");
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura maxFileSize = 0L;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // make sure that we have a valid history count
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper if (count < 0) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper Debug.error(fileName
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper + ":FileHandler: no. of history files negative " + count);
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper count = 0;
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper files = new File[count + 1]; // count is the number of history files
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper for (int i = 0; i < count + 1; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (i != 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster files[i] = new File(fileName + "-" + i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster files[0] = new File(fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster open(files[0], true);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Algorithm: Check how many bytes have already been written to to that file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Get an instance of MeteredStream and assign it as the output stream.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Create a file of the name of FileOutputStream.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void open(File fileName, boolean append) throws IOException {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura meteredStream = new MeteredStream(fileName, append);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setOutputStream(meteredStream);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster checkForHeaderWritten(fileName.toString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Creates a new FileHandler. It takes a string parameter which represents
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * file name. When this constructor is called a new file to be created.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Assuming that the fileName logger provides is the timestamped fileName.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param fileName The filename associate with file handler.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public FileHandler(String fileName) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((fileName == null) || (fileName.length() == 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.fileName = fileName;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster configure();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (NullLocationException nle) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: Location not specified", nle);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (FormatterInitException fie) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: could not instantiate Formatter", fie);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotateEnabled && !rotatingBySize) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileName = wrapFilename(fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileName = location + fileName;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Logger logger = (Logger) Logger.getLogger(this.fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (logger.getLevel() != Level.OFF) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster openFiles(fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ioe) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: Unable to open Files",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ioe);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster logger.setCurrentFile(this.fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer = new LinkedList();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (timeBufferingEnabled) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster startTimeBufferingThread();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster logServiceImplForMonitoring =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Agent.getLoggingSvcMBean();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster logServiceImplForMonitoring.getHandler(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SsoServerLoggingSvcImpl.FILE_HANDLER_NAME);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String wrapFilename(String fileName) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String prefix = lmanager.getProperty(LogConstants.LOGFILE_PREFIX);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String suffixFormat = lmanager.getProperty(LogConstants.LOGFILE_SUFFIX);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringBuilder newFileName = new StringBuilder();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (prefix != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster newFileName.append(prefix);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster newFileName.append(fileName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SimpleDateFormat suffixDateFormat = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (suffixFormat != null && suffixFormat.trim().length() > 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster suffixDateFormat = new SimpleDateFormat(suffixFormat);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IllegalArgumentException iae) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error("Date format invalid; " + suffixFormat, iae);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rotationInterval > 0 && suffixDateFormat == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //fallback to a default dateformat, so the logfilenames will differ
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster suffixDateFormat = new SimpleDateFormat(DEFAULT_LOG_SUFFIX_FORMAT);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (suffixDateFormat != null) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura newFileName.append(suffixDateFormat.format(new Date()));
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return newFileName.toString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void cleanup() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (writer != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.flush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName +
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper ":FileHandler: Could not Flush Output", ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Flush any buffered messages and Close all the files.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void close() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster flush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (writer != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: Error closing writer", e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster stopBufferTimer();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Format and publish a LogRecord.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This FileHandler is associated with a Formatter, which has to format the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * LogRecord according to ELF and return back the string formatted as per
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * ELF. This method first checks if the header is already written to the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * file, if not, gets the header from the Formatter and writes it at the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * beginning of the file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param lrecord the log record to be published.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void publish(LogRecord lrecord) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning() && fileLogHandlerForMonitoring != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring.incHandlerRequestCount(1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (maxFileSize <= 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!isLoggable(lrecord)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Formatter formatter = getFormatter();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String message = formatter.format(lrecord);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer.add(message);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (recordBuffer.size() >= recCountLimit) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName + ":FileHandler.publish(): got " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer.size() + " records, writing all");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster nonBlockingFlush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String getHeaderString() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (headerString == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerString = getFormatter().getHead(this);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return headerString;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Flush any buffered messages.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void nonBlockingFlush() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LinkedList writeBuffer = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (recordBuffer.size() <= 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler.flush: no records in buffer to write");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writeBuffer = recordBuffer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer = new LinkedList();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogTask task = new LogTask(writeBuffer);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de Reeper // Get an instance as required otherwise it can cause issues on container restart.
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de Reeper LoggingThread.getInstance().run(task);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (ThreadPoolException ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // use current thread to flush the data if ThreadPool is shutdown
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster task.run();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void flush() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (recordBuffer.size() <= 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (writer == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int recordsToBeDropped = recordBuffer.size();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning() && fileLogHandlerForMonitoring !=
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring.incHandlerDroppedCount(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordsToBeDropped);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer.clear();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator iter = recordBuffer.iterator(); iter.hasNext();) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String message = (String) iter.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (needsRotation(message)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rotate();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!headerWritten) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.write(getHeaderString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerWritten = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.write(message);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning() &&
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring.incHandlerSuccessCount(1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cleanup();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordBuffer.clear();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean needsRotation(String message) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotateEnabled) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (rotatingBySize) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (!message.isEmpty()
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura && new File(meteredStream.filename).length() >= maxFileSize
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura - message.length()) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura return true;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura } else {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura Calendar now = Calendar.getInstance();
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura Calendar then = Calendar.getInstance();
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura then.setTimeInMillis(lastRotation);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura then.add(Calendar.MINUTE, rotationInterval);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if (now.after(then)) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura return true;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void rotate() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (writer != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.flush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "Error closing writer", ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rotatingBySize) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // delete file<n>; file<n-1> becomes file<n>; and so on.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper for (int i = count - 1; i >= 0; i--) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster File f1 = files[i];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster File f2 = files[i + 1];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (f1.exists()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (f2.exists()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster f2.delete();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (SecurityException secex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + ":FileHandler: could not delete file. msg = "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + secex.getMessage());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean renameSuccess = f1.renameTo(f2);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // In case renaming fails, copy the contents of source file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // to destination file.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!renameSuccess) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster copyFile(f1.toString(), f2.toString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // remember when we last rotated
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper lastRotation = System.currentTimeMillis();
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // Delete the oldest file if it exists
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper if (files[count].exists()) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper try {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper files[count].delete();
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper } catch (SecurityException secex) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper Debug.error(fileName
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper + ":FileHandler: could not delete file. msg = "
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper + secex.getMessage());
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // Move each file up a slot and then replace 0th one with new file
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper for (int i = count - 1; i >= 0; i--) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper files[i + 1] = files[i];
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper // generate a new timestamp based filename
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper String wrappedFilename = wrapFilename(this.fileName);
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper File newLogFile = new File(location, wrappedFilename);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper if (newLogFile.exists()) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper Debug.error(newLogFile.getName()
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + ":FileHandler: could not rotate file. msg = "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "file already exists!");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // swap across to the new file
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper files[0] = newLogFile;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper if (Debug.messageEnabled()) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper Debug.message(fileName
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper + ":FileHandler: rotate to file " + files[0].getName());
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper try {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper open(files[0], false);
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper } catch (IOException ix) {
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper Debug.error(fileName + ":FileHandler: error opening file" + ix);
2a1b2eaa3abf12d3825147bd3a6c72394cbc7c77Mark de Reeper }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void copyFile(String input, String output) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName + ":FileHandler: CopyFile Method called");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FileInputStream fis = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FileOutputStream fos = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //input file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fis = new FileInputStream(input);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int s;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //output file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fos = new FileOutputStream(output);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ((s = fis.read()) > -1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fos.write(s);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (FileNotFoundException fnfe) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: copyFile: File not found: ",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fnfe);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ioex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: copyFile: IOException",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ioex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (fis != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fis.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura } catch (IOException ex) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura Debug.error(fileName + ":FileHandler: copyFile: IOException while closing file", ex);
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura }
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (fos != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fos.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ex) {
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura Debug.error(fileName + ":FileHandler: copyFile: IOException while closing file", ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void checkForHeaderWritten(String fileName) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster byte[] bytes = new byte[1024];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FileInputStream fins = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fins = new FileInputStream(new File(fileName));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fins.read(bytes);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ioe) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: couldnot read file content",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ioe);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (fins != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fins.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: could not close file.", ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String fileContent = new String(bytes);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileContent = fileContent.trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (fileContent.startsWith("#Version")) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerWritten = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerWritten = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private class LogTask implements Runnable {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private LinkedList buffer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public LogTask(LinkedList buffer) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.buffer = buffer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void run() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (writer == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler: Writer is null");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int recordsToBeDropped = buffer.size();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning() && fileLogHandlerForMonitoring !=
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring.incHandlerDroppedCount(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster recordsToBeDropped);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buffer.clear();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName + ":FileHandler.flush: writing " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "buffered records (" +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buffer.size() + " records)");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator iter = buffer.iterator(); iter.hasNext();) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String message = (String) iter.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (needsRotation(message)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rotate();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!headerWritten) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.write(getHeaderString());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster headerWritten = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster writer.write(message);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (MonitoringUtil.isRunning() &&
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fileLogHandlerForMonitoring.incHandlerSuccessCount(1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IOException ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: could not write to file: ", ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cleanup();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private class TimeBufferingTask extends GeneralTaskRunnable {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private long runPeriod;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public TimeBufferingTask(long runPeriod) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.runPeriod = runPeriod;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The method which implements the GeneralTaskRunnable.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void run() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler:TimeBufferingTask.run() called");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster nonBlockingFlush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Methods that need to be implemented from GeneralTaskRunnable.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean isEmpty() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean addElement(Object obj) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean removeElement(Object obj) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public long getRunPeriod() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return runPeriod;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void startTimeBufferingThread() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String period = lmanager.getProperty(LogConstants.BUFFER_TIME);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster long interval;
5f4d6070f856d0de82c1d16459b89233e2e81ff2Kohei Tamura if ((period != null) && (period.length() != 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster interval = Long.parseLong(period);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster interval = LogConstants.BUFFER_TIME_DEFAULT;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster interval *= 1000;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (bufferTask == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bufferTask = new TimeBufferingTask(interval);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SystemTimer.getTimer().schedule(bufferTask, new Date(((System.currentTimeMillis() + interval) / 1000) * 1000));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IllegalArgumentException e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.error(fileName + ":FileHandler:BuffTimeArg: " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster e.getMessage());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (IllegalStateException e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName + ":FileHandler:BuffTimeState: " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster e.getMessage());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ":FileHandler: Time Buffering Thread Started");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void stopBufferTimer() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (bufferTask != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bufferTask.cancel();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bufferTask = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (Debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Debug.message(fileName + ":FileHandler: Buffer Timer Stopped");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}