diff options
Diffstat (limited to 'base/common/src/com/netscape/cms/logging/RollingLogFile.java')
-rw-r--r-- | base/common/src/com/netscape/cms/logging/RollingLogFile.java | 650 |
1 files changed, 0 insertions, 650 deletions
diff --git a/base/common/src/com/netscape/cms/logging/RollingLogFile.java b/base/common/src/com/netscape/cms/logging/RollingLogFile.java deleted file mode 100644 index 0a7a9f098..000000000 --- a/base/common/src/com/netscape/cms/logging/RollingLogFile.java +++ /dev/null @@ -1,650 +0,0 @@ -// --- BEGIN COPYRIGHT BLOCK --- -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; version 2 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// (C) 2007 Red Hat, Inc. -// All rights reserved. -// --- END COPYRIGHT BLOCK --- -package com.netscape.cms.logging; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Hashtable; -import java.util.Locale; -import java.util.Vector; - -import javax.servlet.ServletException; - -import com.netscape.certsrv.apps.CMS; -import com.netscape.certsrv.base.EBaseException; -import com.netscape.certsrv.base.IConfigStore; -import com.netscape.certsrv.base.IExtendedPluginInfo; -import com.netscape.certsrv.common.NameValuePairs; -import com.netscape.certsrv.logging.ConsoleError; -import com.netscape.certsrv.logging.ELogException; -import com.netscape.certsrv.logging.ILogEvent; -import com.netscape.certsrv.logging.ILogger; -import com.netscape.certsrv.logging.SystemEvent; -import com.netscape.cmsutil.util.Utils; - -/** - * A rotating log file for Certificate log events. This class loosely follows - * the Netscape Common Log API implementing rollover interval, size and file - * naming conventions. It does not yet implement Disk Usage. - * - * @version $Revision$, $Date$ - */ -public class RollingLogFile extends LogFile { - public static final String PROP_MAX_FILE_SIZE = "maxFileSize"; - public static final String PROP_ROLLOVER_INTERVAL = "rolloverInterval"; - public static final String PROP_EXPIRATION_TIME = "expirationTime"; - - /** - * The default max file size in bytes - */ - static final int MAX_FILE_SIZE = 100; - - /** - * The default rollover interval in seconds - */ - static final String ROLLOVER_INTERVAL = "2592000"; - - /** - * The default expiration time in seconds - */ - static final String EXPIRATION_TIME = "2592000"; - - /** - * The maximum file size in bytes - */ - protected int mMaxFileSize = 0; - - /** - * The amount of time in miniseconds between log rotations - */ - protected long mRolloverInterval = 0; - - /** - * The thread responsible for rotating the log - */ - private Thread mRolloverThread = null; - - /** - * The amount of time before a backed up log is removed in milliseconds - */ - protected long mExpirationTime = 0; - - /** - * The thread responsible for removing expired log files - */ - private Thread mExpirationThread = null; - - /** - * The object used as a lock for expiration thread synchronization - */ - private Object mExpLock = new Object(); - - private final static String LOGGING_SIGNED_AUDIT_LOG_DELETE = - "LOGGING_SIGNED_AUDIT_LOG_DELETE_3"; - - /** - * Construct a RollingLogFile - */ - public RollingLogFile() { - } - - /** - * Initialize and open a RollingLogFile using the prop config store - * - * @param config The property config store to find values in - */ - public void init(IConfigStore config) throws IOException, - EBaseException { - super.init(config); - - rl_init(config.getInteger(PROP_MAX_FILE_SIZE, MAX_FILE_SIZE), - config.getString(PROP_ROLLOVER_INTERVAL, ROLLOVER_INTERVAL), - config.getString(PROP_EXPIRATION_TIME, EXPIRATION_TIME)); - } - - /** - * Convenience routine to initialized the RollingLogFile specific - * attributes. - */ - protected void rl_init(int maxFileSize, String rolloverInterval, - String expirationTime) { - mMaxFileSize = maxFileSize * 1024; - setRolloverTime(rolloverInterval); - setExpirationTime(expirationTime); - } - - public void startup() throws EBaseException { - super.startup(); - } - - /** - * Shutdown this log file. - */ - public synchronized void shutdown() { - setRolloverTime("0"); - setExpirationTime("0"); - super.shutdown(); - } - - /** - * Set the rollover interval - * - * @param rolloverSeconds The amount of time in seconds until the log - * is rotated. A value of 0 will disable log rollover. - **/ - public synchronized void setRolloverTime(String rolloverSeconds) { - mRolloverInterval = Long.valueOf(rolloverSeconds).longValue() * 1000; - - if ((mRolloverThread == null) && (mRolloverInterval > 0)) { - mRolloverThread = new RolloverThread(); - mRolloverThread.setDaemon(true); - mRolloverThread.start(); - } - - this.notify(); - } - - /** - * Get the rollover interval - * - * @return The interval in seconds in which the log is rotated - **/ - public synchronized int getRolloverTime() { - return (int) (mRolloverInterval / 1000); - } - - /** - * Set the file expiration time - * - * @param expirationSeconds The amount of time in seconds until log files - * are deleted - **/ - public void setExpirationTime(String expirationSeconds) { - - // Need to completely protect changes to mExpiration time - // and make sure they only happen while the thread is sleeping - synchronized (mExpLock) { - mExpirationTime = Long.valueOf(expirationSeconds).longValue() * 1000; - - if (mExpirationThread == null) { - if (mExpirationTime > 0) { - mExpirationThread = new ExpirationThread(); - mExpirationThread.setDaemon(true); - mExpirationThread.start(); - } - } else { - mExpLock.notify(); - } - } - } - - /** - * Get the expiration time - * - * @return The age in seconds in which log files are delete - **/ - public int getExpirationTime() { - return (int) (mExpirationTime / 1000); - } - - /** - * Rotate the log file to a backup file with timestamp - **/ - public synchronized void rotate() - throws IOException { - - File backupFile = new File(mFileName + "." + mLogFileDateFormat.format(mDate)); - - // close, backup, and reopen the log file zeroizing its contents - super.close(); - try { - if (Utils.isNT()) { - // NT is very picky on the path - Utils.exec("copy " + - mFile.getCanonicalPath().replace('/', '\\') + - " " + - backupFile.getCanonicalPath().replace('/', - '\\')); - } else { - // Create a copy of the original file which - // preserves the original file permissions. - Utils.exec("cp -p " + mFile.getCanonicalPath() + " " + - backupFile.getCanonicalPath()); - } - - // Zeroize the original file if and only if - // the backup copy was successful. - if (backupFile.exists()) { - - // Make certain that the backup file has - // the correct permissions. - if (!Utils.isNT()) { - Utils.exec("chmod 00640 " + backupFile.getCanonicalPath()); - } - - try { - // Open and close the original file - // to zeroize its contents. - PrintWriter pw = new PrintWriter(mFile); - pw.close(); - - // Make certain that the original file retains - // the correct permissions. - if (!Utils.isNT()) { - Utils.exec("chmod 00640 " + mFile.getCanonicalPath()); - } - } catch (FileNotFoundException e) { - CMS.debug("Unable to zeroize " - + mFile.toString()); - } - } else { - CMS.debug("Unable to backup " - + mFile.toString() + " to " - + backupFile.toString()); - } - } catch (Exception e) { - CMS.debug("Unable to backup " - + mFile.toString() + " to " - + backupFile.toString()); - } - super.open(); // will reset mBytesWritten - } - - /** - * Remove any log files which have not been modified in the specified - * time - * <P> - * - * NOTE: automatic removal of log files is currently NOT supported! - * <P> - * - * <ul> - * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_DELETE used AFTER audit log expires (authorization should not allow, - * but in case authorization gets compromised make sure it is written AFTER the log expiration happens) - * </ul> - * - * @param expirationSeconds The number of seconds since the expired files - * have been modified. - * @return the time in milliseconds when the next file expires - **/ - public long expire(long expirationSeconds) throws ELogException { - String auditMessage = null; - - if (expirationSeconds <= 0) - throw new ELogException(CMS.getUserMessage("CMS_LOG_EXPIRATION_TIME_ZERO")); - - long expirationTime = expirationSeconds * 1000; - long currentTime = System.currentTimeMillis(); - long oldestFile = currentTime; - - String dirName = mFile.getParent(); - - if (dirName == null) - dirName = "."; - File dir = new File(dirName); - - // Get just the base name, minus the .date extension - //int len = mFile.getName().length() - LogFile.DATE_PATTERN.length() - 1; - //String baseName = mFile.getName().substring(0, len); - String fileName = mFile.getName(); - String baseName = null, pathName = null; - int index = fileName.lastIndexOf("/"); - - if (index != -1) { // "/" exist in fileName - pathName = fileName.substring(0, index); - baseName = fileName.substring(index + 1); - dirName = dirName.concat("/" + pathName); - } else { // "/" NOT exist in fileName - baseName = fileName; - } - - fileFilter ff = new fileFilter(baseName + "."); - String[] filelist = dir.list(ff); - - if (filelist == null) { // Crap! Something is wrong. - throw new ELogException(CMS.getUserMessage("CMS_LOG_DIRECTORY_LIST_FAILED", - dirName, ff.toString())); - } - - // Walk through the list of files which match this log file name - // and delete the old ones. - for (int i = 0; i < filelist.length; i++) { - if (pathName != null) { - filelist[i] = pathName + "/" + filelist[i]; - } else { - filelist[i] = dirName + "/" + filelist[i]; - } - - String fullname = dirName + File.separatorChar + filelist[i]; - File file = new File(fullname); - long fileTime = file.lastModified(); - - // Java documentation on File says lastModified() should not - // be interpeted. The doc is wrong. See JavaSoft bug #4094538 - if ((currentTime - fileTime) > expirationTime) { - file.delete(); - - if (file.exists()) { - // log failure in deleting an expired signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_LOG_DELETE, - ILogger.SYSTEM_UID, - ILogger.FAILURE, - fullname); - } else { - // log success in deleting an expired signed audit log file - auditMessage = CMS.getLogMessage( - LOGGING_SIGNED_AUDIT_LOG_DELETE, - ILogger.SYSTEM_UID, - ILogger.SUCCESS, - fullname); - } - - audit(auditMessage); - } else if (fileTime < oldestFile) { - oldestFile = fileTime; - } - } - return oldestFile + expirationTime; - } - - // - // Rollover and Expiration threads - // - // At first glance you may think it's a waste of thread resources to have - // two threads for every log file, but the truth is that these threads are - // sleeping 99% of the time. NxN thread implementations (Solaris, NT, - // IRIX 6.4, Unixware, etc...) will handle these in user space. - // - // You may be able to join these into one thread, and deal with - // multiple wakeup times, but the code would sure look ugly, and the race - // conditions are numerous as is. Furthermore, this is what user space - // threads will do for you anyways. - // - - /** - * Log rotation thread. Sleep for the rollover interval and rotate the - * log. Changing rollover interval to 0 will cause this thread to exit. - */ - final class RolloverThread extends Thread { - - /** - * Rollover thread constructor including thread name - */ - public RolloverThread() { - super(); - super.setName(mFileName + ".rollover-" + (Thread.activeCount() + 1)); - } - - public void run() { - while (mRolloverInterval > 0) { - // Sleep for the interval and then rotate the log - synchronized (RollingLogFile.this) { - try { - RollingLogFile.this.wait(mRolloverInterval); - } catch (InterruptedException e) { - // This shouldn't happen very often - CMS.getLogger().getLogQueue().log(new - SystemEvent(CMS.getUserMessage("CMS_LOG_THREAD_INTERRUPT", "rollover"))); - } - } - - if (mRolloverInterval == 0) { - break; - } - - if (mBytesWritten > 0) { - try { - rotate(); - } catch (IOException e) { - ConsoleError.send(new - SystemEvent(CMS.getUserMessage("CMS_LOG_ROTATE_LOG_FAILED", mFile.getName(), - e.toString()))); - break; - } - } - // else - // Don't rotate empty logs - // flag in log summary file? - } - mRolloverThread = null; - } - } - - /** - * Log expiration thread. Sleep for the expiration interval and - * delete any files which are too old. - * Changing expiration interval to 0 will cause this thread to exit. - */ - final class ExpirationThread extends Thread { - - /** - * ExpirationThread thread constructor including thread name - */ - public ExpirationThread() { - super(); - super.setName(mFileName + ".expiration-" + (Thread.activeCount() + 1)); - } - - public void run() { - synchronized (mExpLock) { - while (mExpirationTime > 0) { - long wakeupTime = 0; - long sleepTime = 0; - - // First, remove any old log files and figure out when the - // next one expires - try { - wakeupTime = expire(mExpirationTime / 1000); - } catch (SecurityException e) { - ConsoleError.send(new - SystemEvent(CMS.getUserMessage("CMS_LOG_EXPIRE_LOG_FAILED", e.toString()))); - break; - } catch (ELogException e) { - ConsoleError.send(new - SystemEvent(CMS.getUserMessage("CMS_LOG_EXPIRE_LOG_FAILED", e.toString()))); - break; - } - - sleepTime = wakeupTime - System.currentTimeMillis(); - //System.out.println("wakeup " + wakeupTime); - //System.out.println("current "+System.currentTimeMillis()); - //System.out.println("sleep " + sleepTime); - // Sleep for the interval and then check the directory - // Note: mExpirationTime can only change while we're - // sleeping - if (sleepTime > 0) { - try { - mExpLock.wait(sleepTime); - } catch (InterruptedException e) { - // This shouldn't happen very often - ConsoleError.send(new - SystemEvent(CMS.getUserMessage("CMS_LOG_THREAD_INTERRUPT", "expiration"))); - } - } - } - } - mExpirationThread = null; - } - } - - /** - * Write an event to the log file - * - * @param ev The event to be logged. - **/ - public synchronized void log(ILogEvent ev) throws ELogException { - //xxx, Shall we log first without checking if it exceed the maximum? - super.log(ev); // Will increment mBytesWritten - - if ((0 != mMaxFileSize) && (mBytesWritten > mMaxFileSize)) { - flush(); - try { - rotate(); - } catch (IOException e) { - throw new ELogException(CMS.getUserMessage("CMS_LOG_ROTATE_LOG_FAILED", mFile.getName(), e.toString())); - } - } - } - - /** - * Retrieve log file list. - */ - public synchronized NameValuePairs retrieveLogList(Hashtable<String, String> req - ) throws ServletException, - IOException, EBaseException { - NameValuePairs params = new NameValuePairs(); - String[] files = null; - - files = fileList(); - for (int i = 0; i < files.length; i++) { - params.put(files[i], ""); - } - return params; - } - - /** - * Get the log file list in the log directory - * - * @return an array of filenames with related path to cert server root - */ - protected String[] fileList() { - String pathName = null, baseName = null; - - String dirName = mFile.getParent(); - String fileName = mFile.getName(); - int index = fileName.lastIndexOf("/"); - - if (index != -1) { // "/" exist in fileName - pathName = fileName.substring(0, index); - baseName = fileName.substring(index + 1); - if (dirName == null) { - dirName = pathName; - } else { - dirName = dirName.concat("/" + pathName); - } - } else { // "/" NOT exist in fileName - baseName = fileName; - } - - File dir = new File(dirName); - - fileFilter ff = new fileFilter(baseName + "."); - //There are some difference here. both should work - //error,logs,logs/error jdk115 - //logs/system,., logs/system jdk116 - //System.out.println(mFile.getName()+","+dirName+","+mFile.getPath()); //log/system,. - - String[] filelist = dir.list(ff); - - for (int i = 0; i < filelist.length; i++) { - if (pathName != null) { - filelist[i] = pathName + "/" + filelist[i]; - } else { - filelist[i] = dirName + "/" + filelist[i]; - } - } - return filelist; - } - - public String getImplName() { - return "RollingLogFile"; - } - - public String getDescription() { - return "RollingLogFile"; - } - - public Vector<String> getDefaultParams() { - Vector<String> v = super.getDefaultParams(); - - v.addElement(PROP_MAX_FILE_SIZE + "="); - v.addElement(PROP_ROLLOVER_INTERVAL + "="); - //v.addElement(PROP_EXPIRATION_TIME + "="); - return v; - } - - public Vector<String> getInstanceParams() { - Vector<String> v = super.getInstanceParams(); - - try { - v.addElement(PROP_MAX_FILE_SIZE + "=" + mMaxFileSize / 1024); - if (mRolloverInterval / 1000 <= 60 * 60) - v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Hourly"); - else if (mRolloverInterval / 1000 <= 60 * 60 * 24) - v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Daily"); - else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 7) - v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Weekly"); - else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 30) - v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Monthly"); - else if (mRolloverInterval / 1000 <= 60 * 60 * 24 * 366) - v.addElement(PROP_ROLLOVER_INTERVAL + "=" + "Yearly"); - - //v.addElement(PROP_EXPIRATION_TIME + "=" + mExpirationTime / 1000); - } catch (Exception e) { - } - return v; - } - - public String[] getExtendedPluginInfo(Locale locale) { - String[] p = super.getExtendedPluginInfo(locale); - Vector<String> info = new Vector<String>(); - - for (int i = 0; i < p.length; i++) { - if (!p[i].startsWith(IExtendedPluginInfo.HELP_TOKEN) && !p[i].startsWith(IExtendedPluginInfo.HELP_TEXT)) - info.addElement(p[i]); - } - info.addElement(PROP_MAX_FILE_SIZE - + ";integer;If the current log file size if bigger than this parameter in kilobytes(KB), the file will be rotated."); - info.addElement(PROP_ROLLOVER_INTERVAL - + ";choice(Hourly,Daily,Weekly,Monthly,Yearly);The frequency of the log being rotated."); - info.addElement(PROP_EXPIRATION_TIME - + ";integer;The amount of time before a backed up log is removed in seconds"); - info.addElement(IExtendedPluginInfo.HELP_TOKEN + - //";configuration-logrules-rollinglogfile"); - ";configuration-adminbasics"); - info.addElement(IExtendedPluginInfo.HELP_TEXT + - ";Write the log messages to a file which will be rotated automatically."); - String[] params = new String[info.size()]; - - info.copyInto(params); - return params; - - } -} - -/** - * A file filter to select the file with a given prefix - */ -class fileFilter implements FilenameFilter { - String patternToMatch = null; - - public fileFilter(String pattern) { - patternToMatch = pattern; - } - - public boolean accept(File dir, String name) { - if (name.startsWith(patternToMatch)) - return true; - else - return false; - } -} |