FileHandler.java revision 5f4d6070f856d0de82c1d16459b89233e2e81ff2
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: FileHandler.java,v 1.14 2009/07/27 19:50:55 bigfatrat Exp $
*
*/
/*
* Portions Copyrighted 2011-2014 ForgeRock AS
* Portions Copyrighted 2014 Nomura Research Institute, Ltd
*/
/**
* This <tt> FileHandler </tt> is very much similar to the
* <t> java.util.logging.FileHandler </tt>. <p> The <TT> FileHandler </TT>
* can either write to a specified file, or it can write to a rotating set
* of files. <P>
* For a rotating set of files, as each file reaches the limit
* (<i> LogConstants.MAX_FILE_SIZE</I>), it is closed, rotated out, and a
* new file opened. Successively older files and named by adding "-1", "-2",
* etc., * to the base filename. The Locking mechanism is much more relaxed
* (in JDK's FileHandler an exclusive lock is created on the file till the
* handler is closed which makes reading impossible)
*/
private OutputStream output;
private MeteredStream meteredStream;
private boolean headerWritten;
private int count; // count represent number of history files
private long maxFileSize;
private int recCountLimit;
private LinkedList recordBuffer;
private TimeBufferingTask bufferTask;
private boolean timeBufferingEnabled = false;
private boolean rotateEnabled = true;
private int rotationInterval = -1;
private long lastRotation;
/**
* By default the size based rotation is enabled
*/
private boolean rotatingBySize = true;
private class MeteredStream extends OutputStream {
}
/**
* writes a single integer to the outputstream and increments
* the number of bytes written by one.
* @param b integer value to be written.
* @throws IOException if it fails to write out.
*/
public void write(int b) throws IOException {
}
/**
* Writes the array of bytes to the output stream and increments
* the number of bytes written by the size of the array.
* @param b the byte array to be written.
* @throws IOException if it fails to write out.
*/
public void write(byte[] b) throws IOException {
}
/**
* Writes the array of bytes to the output stream and increments
* the number of bytes written by the size of the array.
* @param b the byte array to be written.
* @param offset the offset of array to be written.
* @param length the length of bytes to be written.
* @throws IOException if it fails to write out.
*/
throws IOException {
}
/**
* Flush any buffered messages.
* @throws IOException if it fails to write out.
*/
public void flush() throws IOException {
}
/**
* close the current output stream.
* @throws IOException if it fails to close output stream.
*/
public void close() throws IOException {
}
}
/**
* sets the output stream to the specified output stream ..picked up from
* StreamHandler.
*/
if (Debug.warningEnabled()) {
}
}
headerWritten = false;
} else {
try {
} catch (UnsupportedEncodingException e) {
throw new UnsupportedEncodingException(e.getMessage());
}
}
}
/**
* Set (or change) the character encoding used by this <tt>Handler</tt>.
* The encoding should be set before any <tt>LogRecords</tt> are written
* to the <tt>Handler</tt>.
*
* @param encoding The name of a supported character encoding.
* May be null, to indicate the default platform encoding.
* @exception SecurityException if a security manager exists and if
* the caller does not have
* <tt>LoggingPermission("control")</tt>.
* @exception UnsupportedEncodingException if the named encoding is
* not supported.
*/
super.setEncoding(encoding);
return;
}
// Replace the current writer with a writer for the new encoding.
cleanup();
} else {
}
}
/**
* This method is used for getting the properties from LogManager
* and setting the private variables count, maxFileSize etc.
*/
private void configure()
throws NullLocationException, FormatterInitException {
try {
} catch (NumberFormatException nfe) {
":FileHandler: NumberFormatException ", nfe);
if (Debug.messageEnabled()) {
":FileHandler: Setting buffer size to 1");
}
recCountLimit = 1;
}
} else {
":FileHandler: Invalid buffer size: " + bufferSize);
if (Debug.messageEnabled()) {
":FileHandler: Setting buffer size to 1");
}
recCountLimit = 1;
}
timeBufferingEnabled = true;
}
count = 0;
} else {
}
maxFileSize = 0L;
} else {
}
throw new NullLocationException(
"Location Not Specified"); //localize
}
}
try {
} catch (Exception e) {
throw new FormatterInitException(
"Unable to initialize Formatter Class" + e);
}
}
if (rotateEnabled) {
try {
}
} catch (NumberFormatException nfe) {
//if we cannot parse it, then we use the size based rotation
rotationInterval = -1;
}
if (rotationInterval > 0) {
rotatingBySize = false;
}
}
}
if (rotateEnabled && rotatingBySize) {
// make sure that we have a valid maxFileSize
if (maxFileSize < 0) {
+ ":FileHandler: maxFileSize cannot be negative");
maxFileSize = 0L;
}
}
// make sure that we have a valid history count
if (count < 0) {
+ ":FileHandler: no. of history files negative " + count);
count = 0;
}
if (i != 0) {
} else {
}
}
}
/**
* Algorithm: Check how many bytes have already been written to to that file
* Get an instance of MeteredStream and assign it as the output stream.
* Create a file of the name of FileOutputStream.
*/
}
/**
* Creates a new FileHandler. It takes a string parameter which represents
* file name. When this constructor is called a new file to be created.
* Assuming that the fileName logger provides is the timestamped fileName.
* @param fileName The filename associate with file handler.
*/
return;
}
try {
configure();
} catch (NullLocationException nle) {
} catch (FormatterInitException fie) {
":FileHandler: could not instantiate Formatter", fie);
}
if (rotateEnabled && !rotatingBySize) {
}
try {
} catch (IOException ioe) {
ioe);
}
}
recordBuffer = new LinkedList();
if (timeBufferingEnabled) {
}
if (MonitoringUtil.isRunning()) {
}
}
}
try {
} catch (IllegalArgumentException iae) {
}
}
//fallback to a default dateformat, so the logfilenames will differ
}
if (suffixDateFormat != null) {
}
return newFileName.toString();
}
private void cleanup() {
try {
":FileHandler: Could not Flush Output", ex);
}
}
}
/**
* Flush any buffered messages and Close all the files.
*/
public void close() {
flush();
try {
} catch (IOException e) {
}
}
}
/**
* Format and publish a LogRecord.
* <p>
* This FileHandler is associated with a Formatter, which has to format the
* LogRecord according to ELF and return back the string formatted as per
* ELF. This method first checks if the header is already written to the
* file, if not, gets the header from the Formatter and writes it at the
* beginning of the file.
* @param lrecord the log record to be published.
*/
}
if (maxFileSize <= 0) {
return;
}
if (!isLoggable(lrecord)) {
return;
}
synchronized (this) {
if (Debug.messageEnabled()) {
}
}
}
}
private String getHeaderString() {
if (headerString == null) {
}
return headerString;
}
/**
* Flush any buffered messages.
*/
protected void nonBlockingFlush() {
synchronized (this) {
if (Debug.messageEnabled()) {
":FileHandler.flush: no records in buffer to write");
}
return;
}
recordBuffer = new LinkedList();
}
try {
// Get an instance as required otherwise it can cause issues on container restart.
} catch (ThreadPoolException ex) {
// use current thread to flush the data if ThreadPool is shutdown
synchronized (this) {
}
}
}
public void flush() {
synchronized (this) {
return;
}
null) {
}
return;
}
if (needsRotation(message)) {
rotate();
}
try {
if (!headerWritten) {
headerWritten = true;
}
if (MonitoringUtil.isRunning() &&
}
} catch (IOException ex) {
}
cleanup();
}
}
}
if (rotateEnabled) {
if (rotatingBySize) {
return true;
}
} else {
return true;
}
}
}
return false;
}
private void rotate() {
try {
"Error closing writer", ex);
}
}
if (rotatingBySize) {
//
// delete file<n>; file<n-1> becomes file<n>; and so on.
//
try {
} catch (SecurityException secex) {
+ ":FileHandler: could not delete file. msg = "
+ secex.getMessage());
}
}
// In case renaming fails, copy the contents of source file
// to destination file.
if (!renameSuccess) {
}
}
}
} else {
// remember when we last rotated
// Delete the oldest file if it exists
try {
} catch (SecurityException secex) {
+ ":FileHandler: could not delete file. msg = "
+ secex.getMessage());
}
}
// Move each file up a slot and then replace 0th one with new file
}
// generate a new timestamp based filename
if (newLogFile.exists()) {
+ ":FileHandler: could not rotate file. msg = "
+ "file already exists!");
} else {
// swap across to the new file
}
}
if (Debug.messageEnabled()) {
}
try {
} catch (IOException ix) {
}
}
if (Debug.messageEnabled()) {
}
try {
//input file
int s;
//output file
}
} catch (FileNotFoundException fnfe) {
fnfe);
} catch (IOException ioex) {
ioex);
} finally {
try {
}
} catch (IOException ex) {
}
try {
}
} catch (IOException ex) {
}
}
}
byte[] bytes = new byte[1024];
try {
} catch (IOException ioe) {
ioe);
} finally {
try {
} catch (IOException ex) {
":FileHandler: could not close file.", ex);
}
}
}
headerWritten = true;
} else {
headerWritten = false;
}
}
private LinkedList buffer;
}
public void run() {
null) {
}
return;
}
if (Debug.messageEnabled()) {
"buffered records (" +
}
if (needsRotation(message)) {
rotate();
}
try {
if (!headerWritten) {
headerWritten = true;
}
if (MonitoringUtil.isRunning() &&
}
} catch (IOException ex) {
":FileHandler: could not write to file: ", ex);
}
cleanup();
}
}
}
private class TimeBufferingTask extends GeneralTaskRunnable {
private long runPeriod;
public TimeBufferingTask(long runPeriod) {
}
/**
* The method which implements the GeneralTaskRunnable.
*/
public void run() {
if (Debug.messageEnabled()) {
":FileHandler:TimeBufferingTask.run() called");
}
}
/**
* Methods that need to be implemented from GeneralTaskRunnable.
*/
public boolean isEmpty() {
return true;
}
return false;
}
return false;
}
public long getRunPeriod() {
return runPeriod;
}
}
private void startTimeBufferingThread() {
long interval;
} else {
}
interval *= 1000;
if (bufferTask == null) {
try {
SystemTimer.getTimer().schedule(bufferTask, new Date(((System.currentTimeMillis() + interval) / 1000) * 1000));
} catch (IllegalArgumentException e) {
e.getMessage());
} catch (IllegalStateException e) {
if (Debug.messageEnabled()) {
e.getMessage());
}
}
if (Debug.messageEnabled()) {
":FileHandler: Time Buffering Thread Started");
}
}
}
private void stopBufferTimer() {
if (bufferTask != null) {
bufferTask.cancel();
bufferTask = null;
if (Debug.messageEnabled()) {
}
}
}
}