Package rb.trinidad.logging

Source Code of rb.trinidad.logging.FileHandler

/*
* Copyright (c) 2012 Team Trinidad and contributors http://github.com/trinidad
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package rb.trinidad.logging;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.nio.channels.FileChannel;


/**
* FileHandler improvements for logging into a file (with JUL).
*
* @author kares
*/
public class FileHandler extends org.apache.juli.FileHandler {
   
    private static final Field directoryField;
    private static final Field prefixField;
    private static final Field suffixField;
    private static final Field rotatableField;
    private static final Field bufferSizeField;
    // current date string e.g. "2012-09-24"
    private static final Field dateField; // FileHandler impl internals
   
    static {
        try {
            Class<?> klass = org.apache.juli.FileHandler.class;
            directoryField = klass.getDeclaredField("directory");
            directoryField.setAccessible(true);
            prefixField = klass.getDeclaredField("prefix");
            prefixField.setAccessible(true);
            suffixField = klass.getDeclaredField("suffix");
            suffixField.setAccessible(true);
            rotatableField = klass.getDeclaredField("rotatable");
            rotatableField.setAccessible(true);
            bufferSizeField = klass.getDeclaredField("bufferSize");
            bufferSizeField.setAccessible(true);
            dateField = klass.getDeclaredField("date");
            dateField.setAccessible(true);
        }
        catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
   
    public FileHandler() {
        this(null, null, null);
    }
   
    public FileHandler(String directory, String prefix, String suffix) {
        super(directory, prefix, suffix);
        setField(dateField, null); // self._date = nil
    }
   
    @Override
    protected void openWriter() {
        // NOTE: following code is heavily based on super's internals !
        synchronized(this) {
            // we're normally in the lock here (from #publish)
            // thus we do not perform any more synchronization           
            Boolean rotatable = (Boolean) getField(rotatableField);
            try {
                setField(rotatableField, Boolean.FALSE);
                // thus current file name will be always {prefix}{suffix} :
                // due super's `prefix + (rotatable ? _date : "") + suffix`
                super.openWriter();
            }
            finally {
                setField(rotatableField, rotatable);
            }
        }
    }
   
    private boolean closing = false;
   
    @Override
    public void close() {
        closing = true;
        super.close(); // closeWriter()
        closing = false;
    }

    @Override
    protected void closeWriter() {
        String date = (String) getField(dateField);
        super.closeWriter(); // sets `date = null`
        boolean rotatable = isRotatable();
        if ( ! rotatable || closing ) return; // no rotation ...
        // the additional trick here is to rotate the closed file
        synchronized(this) {
            // we're normally in the lock here (from #publish)
            // thus we do not perform any more synchronization
            final File dir = new File( getDirectory() ).getAbsoluteFile();
            final File log = new File( dir, getPrefix() + "" + getSuffix() );
            if ( log.exists() ) {
                if ( date == null || date.isEmpty() ) {
                    final long lastMod = log.lastModified();
                    // we abuse Timestamp to get a date formatted !
                    // just like super does internally (to be sure)
                    date = new java.sql.Timestamp(lastMod).toString().substring(0, 10);
                }
                final long todayMS = System.currentTimeMillis();
                String today = new java.sql.Timestamp(todayMS).toString().substring(0, 10);
                if ( date.equals(today) ) return; // no need to rotate just yet
                File toFile = new File(dir, getPrefix() + date + getSuffix());
                if ( toFile.exists() ) {
                    try {
                        RandomAccessFile file = new RandomAccessFile(toFile, "rw");
                        file.seek( file.length() );
                        FileChannel logChannel = new FileInputStream(log).getChannel();
                        logChannel.transferTo(0, logChannel.size(), file.getChannel());
                        file.close();
                        logChannel.close();
                        log.delete();  
                    }
                    catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                else {
                    log.renameTo(toFile);
                }
            }
        }
    }
   
    public String getDirectory() {
        return (String) getField(directoryField);
    }

    public void setDirectory(String directory) {
        setField(directoryField, directory);
    }
   
    public String getPrefix() {
        return (String) getField(prefixField);
    }

    public void setPrefix(String prefix) {
        setField(prefixField, prefix);
    }
   
    public String getSuffix() {
        return (String) getField(suffixField);
    }

    public void setSuffix(String suffix) {
        setField(suffixField, suffix);
    }
   
    public boolean isRotatable() {
        Boolean rotatable = (Boolean) getField(rotatableField);
        return Boolean.TRUE.equals(rotatable);
    }
   
    public void setRotatable(boolean rotate) {
        setField(rotatableField, rotate);
    }
   
    public Integer getBufferSize() {
        return (Integer) getField(bufferSizeField);
    }

    public void setBufferSize(Integer bufferSize) {
        setField(bufferSizeField, bufferSize);
    }
   
    private void setField(Field field, Object value) {
        try {
            field.set(this, value);
        }
        catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private Object getField(Field field) {
        try {
            return field.get(this);
        }
        catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
   
}
TOP

Related Classes of rb.trinidad.logging.FileHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.