/* * 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 org.apache.juli; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.sql.Timestamp; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.ErrorManager; import java.util.logging.Filter; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; /** * Implementation of Handler that appends log messages to a file * named {prefix}{date}{suffix} in a configured directory. * *
The following configuration properties are available:
* *directory - The directory where to create the log file.
* If the path is not absolute, it is relative to the current working
* directory of the application. The Apache Tomcat configuration files usually
* specify an absolute path for this property,
* ${catalina.base}/logs
* Default value: logsrotatable - If true, the log file will be
* rotated on the first write past midnight and the filename will be
* {prefix}{date}{suffix}, where date is yyyy-MM-dd. If false,
* the file will not be rotated and the filename will be {prefix}{suffix}.
* Default value: trueprefix - The leading part of the log file name.
* Default value: juli.suffix - The trailing part of the log file name. Default value: .logbufferSize - Configures buffering. The value of 0
* uses system default buffering (typically an 8K buffer will be used). A
* value of <0 forces a writer flush upon each log write. A
* value >0 uses a BufferedOutputStream with the defined
* value but note that the system default buffering will also be
* applied. Default value: -1encoding - Character set used by the log file. Default value:
* empty string, which means to use the system default character set.level - The level threshold for this Handler. See the
* java.util.logging.Level class for the possible levels.
* Default value: ALLfilter - The java.util.logging.Filter
* implementation class name for this Handler. Default value: unsetformatter - The java.util.logging.Formatter
* implementation class name for this Handler. Default value:
* java.util.logging.SimpleFormatterLogManager properties.
*/
private void configure() {
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
date = tsString.substring(0, 10);
String className = this.getClass().getName(); //allow classes to override
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Retrieve configuration of logging file name
rotatable = Boolean.parseBoolean(getProperty(className + ".rotatable", "true"));
if (directory == null)
directory = getProperty(className + ".directory", "logs");
if (prefix == null)
prefix = getProperty(className + ".prefix", "juli.");
if (suffix == null)
suffix = getProperty(className + ".suffix", ".log");
String sBufferSize = getProperty(className + ".bufferSize", String.valueOf(bufferSize));
try {
bufferSize = Integer.parseInt(sBufferSize);
} catch (NumberFormatException ignore) {
//no op
}
// Get encoding for the logging file
String encoding = getProperty(className + ".encoding", null);
if (encoding != null && encoding.length() > 0) {
try {
setEncoding(encoding);
} catch (UnsupportedEncodingException ex) {
// Ignore
}
}
// Get logging level for the handler
setLevel(Level.parse(getProperty(className + ".level", "" + Level.ALL)));
// Get filter configuration
String filterName = getProperty(className + ".filter", null);
if (filterName != null) {
try {
setFilter((Filter) cl.loadClass(filterName).newInstance());
} catch (Exception e) {
// Ignore
}
}
// Set formatter
String formatterName = getProperty(className + ".formatter", null);
if (formatterName != null) {
try {
setFormatter((Formatter) cl.loadClass(formatterName).newInstance());
} catch (Exception e) {
// Ignore and fallback to defaults
setFormatter(new OneLineFormatter());
}
} else {
setFormatter(new OneLineFormatter());
}
// Set error manager
setErrorManager(new ErrorManager());
}
private String getProperty(String name, String defaultValue) {
String value = LogManager.getLogManager().getProperty(name);
if (value == null) {
value = defaultValue;
} else {
value = value.trim();
}
return value;
}
/**
* Open the new log file for the date specified by date.
*/
protected void open() {
openWriter();
}
protected void openWriter() {
// Create the directory if necessary
File dir = new File(directory);
if (!dir.mkdirs() && !dir.isDirectory()) {
reportError("Unable to create [" + dir + "]", null,
ErrorManager.OPEN_FAILURE);
writer = null;
return;
}
// Open the current log file
writerLock.writeLock().lock();
FileOutputStream fos = null;
OutputStream os = null;
try {
File pathname = new File(dir.getAbsoluteFile(), prefix
+ (rotatable ? date : "") + suffix);
File parent = pathname.getParentFile();
if (!parent.mkdirs() && !parent.isDirectory()) {
reportError("Unable to create [" + parent + "]", null,
ErrorManager.OPEN_FAILURE);
writer = null;
return;
}
String encoding = getEncoding();
fos = new FileOutputStream(pathname, true);
os = bufferSize>0?new BufferedOutputStream(fos,bufferSize):fos;
writer = new PrintWriter(
(encoding != null) ? new OutputStreamWriter(os, encoding)
: new OutputStreamWriter(os), false);
writer.write(getFormatter().getHead(this));
} catch (Exception e) {
reportError(null, e, ErrorManager.OPEN_FAILURE);
writer = null;
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
// Ignore
}
}
if (os != null) {
try {
os.close();
} catch (IOException e1) {
// Ignore
}
}
} finally {
writerLock.writeLock().unlock();
}
}
}