com.l2jserver.service.core.logging.TruncateToZipFileAppender.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jserver.service.core.logging.TruncateToZipFileAppender.java

Source

/*
 * This file is part of l2jserver <l2jserver.com>.
 *
 * l2jserver 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * l2jserver 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 l2jserver.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jserver.service.core.logging;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.LogLog;

/**
 * This class is appender that zips old file instead of appending it.<br>
 * File is recognized as old if it's lastModified() is < JVM startup time.<br>
 * So we can have per-run appending. <br>
 * 
 * Unfortunately, UNIX systems doesn't support file creation date, so we have to
 * use lastModified(), windows only solution is not good.
 * 
 * @author <a href="http://www.rogiel.com">Rogiel</a>
 */
public class TruncateToZipFileAppender extends FileAppender {
    /**
     * String that points to root directory for backups
     */
    private String backupDir = "log/backup";

    /**
     * String that represents date format for backup files
     */
    private String backupDateFormat = "yyyy-MM-dd HH-mm-ss";

    /**
     * Sets and <i>opens</i> the file where the log output will go. The
     * specified file must be writable.
     * <p>
     * If there was already an opened file, then the previous file is closed
     * first.
     * <p/>
     * <p>
     * <b>Do not use this method directly. To configure a FileAppender or one of
     * its subclasses, set its properties one by one and then call
     * activateOptions.</b>
     * <p/>
     * <br>
     * Truncation is done by {@link #truncate(java.io.File)}
     * 
     * @param fileName
     *            The path to the log file.
     * @param append
     *            If true will append to fileName. Otherwise will truncate
     *            fileName.
     */
    @Override
    public void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException {

        if (!append) {
            truncate(new File(fileName));
        }

        super.setFile(fileName, append, bufferedIO, bufferSize);
    }

    /**
     * This method creates archive with file instead of deleting it.
     * 
     * @param file
     *            file to truncate
     */
    protected void truncate(File file) {
        LogLog.debug("Compression of file: " + file.getAbsolutePath() + " started.");

        // Linux systems doesn't provide file creation time, so we have to hope
        // that log files
        // were not modified manually after server starup
        // We can use here Windowns-only solution but that suck :(
        if (FileUtils.isFileOlder(file, ManagementFactory.getRuntimeMXBean().getStartTime())) {
            File backupRoot = new File(getBackupDir());
            if (!backupRoot.exists() && !backupRoot.mkdirs()) {
                throw new Error("Can't create backup dir for backup storage");
            }

            SimpleDateFormat df;
            try {
                df = new SimpleDateFormat(getBackupDateFormat());
            } catch (Exception e) {
                throw new Error("Invalid date formate for backup files: " + getBackupDateFormat(), e);
            }
            String date = df.format(new Date(file.lastModified()));

            File zipFile = new File(backupRoot, file.getName() + "." + date + ".zip");

            ZipOutputStream zos = null;
            FileInputStream fis = null;
            try {
                zos = new ZipOutputStream(new FileOutputStream(zipFile));
                ZipEntry entry = new ZipEntry(file.getName());
                entry.setMethod(ZipEntry.DEFLATED);
                entry.setCrc(FileUtils.checksumCRC32(file));
                zos.putNextEntry(entry);
                fis = FileUtils.openInputStream(file);

                byte[] buffer = new byte[1024];
                int readed;
                while ((readed = fis.read(buffer)) != -1) {
                    zos.write(buffer, 0, readed);
                }

            } catch (Exception e) {
                throw new Error("Can't create zip file", e);
            } finally {
                if (zos != null) {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        // not critical error
                        LogLog.warn("Can't close zip file", e);
                    }
                }

                if (fis != null) {
                    try {
                        // not critical error
                        fis.close();
                    } catch (IOException e) {
                        LogLog.warn("Can't close zipped file", e);
                    }
                }
            }

            if (!file.delete()) {
                throw new Error("Can't delete old log file " + file.getAbsolutePath());
            }
        }
    }

    /**
     * Returns root directory for backups
     * 
     * @return root directory for backups
     */
    public String getBackupDir() {
        return backupDir;
    }

    /**
     * Sets root directory for backups
     * 
     * @param backupDir
     *            new root directory for backups
     */
    public void setBackupDir(String backupDir) {
        this.backupDir = backupDir;
    }

    /**
     * Returns date format that should be used for backup files represented as
     * string
     * 
     * @return date formate for backup files
     */
    public String getBackupDateFormat() {
        return backupDateFormat;
    }

    /**
     * Sets date format for bakcup files represented as string
     * 
     * @param backupDateFormat
     *            date format for backup files
     */
    public void setBackupDateFormat(String backupDateFormat) {
        this.backupDateFormat = backupDateFormat;
    }
}