alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MemoryHandler.java)

This example Java source code file (MemoryHandler.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

classnotfoundexception, default_size, illegalaccessexception, illegalargumentexception, instantiationexception, level, logmanager, logrecord, memoryhandler, nullpointerexception, override, runtimeexception, securityexception, string

The MemoryHandler.java Java example source code

/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.util.logging;

/**
 * <tt>Handler that buffers requests in a circular buffer in memory.
 * <p>
 * Normally this <tt>Handler simply stores incoming LogRecords
 * into its memory buffer and discards earlier records.  This buffering
 * is very cheap and avoids formatting costs.  On certain trigger
 * conditions, the <tt>MemoryHandler will push out its current buffer
 * contents to a target <tt>Handler, which will typically publish
 * them to the outside world.
 * <p>
 * There are three main models for triggering a push of the buffer:
 * <ul>
 * <li>
 * An incoming <tt>LogRecord has a type that is greater than
 * a pre-defined level, the <tt>pushLevel. 
 * <li>
 * An external class calls the <tt>push method explicitly. 
 * <li>
 * A subclass overrides the <tt>log method and scans each incoming
 * <tt>LogRecord and calls push if a record matches some
 * desired criteria. </li>
 * </ul>
 * <p>
 * <b>Configuration:
 * By default each <tt>MemoryHandler is initialized using the following
 * <tt>LogManager configuration properties where <handler-name>
 * refers to the fully-qualified class name of the handler.
 * If properties are not defined
 * (or have invalid values) then the specified default values are used.
 * If no default value is defined then a RuntimeException is thrown.
 * <ul>
 * <li>   <handler-name>.level
 *        specifies the level for the <tt>Handler
 *        (defaults to <tt>Level.ALL). 
 * <li>   <handler-name>.filter
 *        specifies the name of a <tt>Filter class to use
 *        (defaults to no <tt>Filter). 
 * <li>   <handler-name>.size
 *        defines the buffer size (defaults to 1000). </li>
 * <li>   <handler-name>.push
 *        defines the <tt>pushLevel (defaults to level.SEVERE). 
 * <li>   <handler-name>.target
 *        specifies the name of the target <tt>Handler  class.
 *        (no default). </li>
 * </ul>
 * <p>
 * For example, the properties for {@code MemoryHandler} would be:
 * <ul>
 * <li>   java.util.logging.MemoryHandler.level=INFO 
 * <li>   java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter 
 * </ul>
 * <p>
 * For a custom handler, e.g. com.foo.MyHandler, the properties would be:
 * <ul>
 * <li>   com.foo.MyHandler.level=INFO 
 * <li>   com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter 
 * </ul>
 * <p>
 * @since 1.4
 */

public class MemoryHandler extends Handler {
    private final static int DEFAULT_SIZE = 1000;
    private volatile Level pushLevel;
    private int size;
    private Handler target;
    private LogRecord buffer[];
    int start, count;

    // Private method to configure a MemoryHandler from LogManager
    // properties and/or default values as specified in the class
    // javadoc.
    private void configure() {
        LogManager manager = LogManager.getLogManager();
        String cname = getClass().getName();

        pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
        size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
        if (size <= 0) {
            size = DEFAULT_SIZE;
        }
        setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
        setFilter(manager.getFilterProperty(cname +".filter", null));
        setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
    }

    /**
     * Create a <tt>MemoryHandler and configure it based on
     * <tt>LogManager configuration properties.
     */
    public MemoryHandler() {
        sealed = false;
        configure();
        sealed = true;

        LogManager manager = LogManager.getLogManager();
        String handlerName = getClass().getName();
        String targetName = manager.getProperty(handlerName+".target");
        if (targetName == null) {
            throw new RuntimeException("The handler " + handlerName
                    + " does not specify a target");
        }
        Class<?> clz;
        try {
            clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
            target = (Handler) clz.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
        }
        init();
    }

    // Initialize.  Size is a count of LogRecords.
    private void init() {
        buffer = new LogRecord[size];
        start = 0;
        count = 0;
    }

    /**
     * Create a <tt>MemoryHandler.
     * <p>
     * The <tt>MemoryHandler is configured based on LogManager
     * properties (or their default values) except that the given <tt>pushLevel
     * argument and buffer size argument are used.
     *
     * @param target  the Handler to which to publish output.
     * @param size    the number of log records to buffer (must be greater than zero)
     * @param pushLevel  message level to push on
     *
     * @throws IllegalArgumentException if {@code size is <= 0}
     */
    public MemoryHandler(Handler target, int size, Level pushLevel) {
        if (target == null || pushLevel == null) {
            throw new NullPointerException();
        }
        if (size <= 0) {
            throw new IllegalArgumentException();
        }
        sealed = false;
        configure();
        sealed = true;
        this.target = target;
        this.pushLevel = pushLevel;
        this.size = size;
        init();
    }

    /**
     * Store a <tt>LogRecord in an internal buffer.
     * <p>
     * If there is a <tt>Filter, its isLoggable
     * method is called to check if the given log record is loggable.
     * If not we return.  Otherwise the given record is copied into
     * an internal circular buffer.  Then the record's level property is
     * compared with the <tt>pushLevel. If the given level is
     * greater than or equal to the <tt>pushLevel then push
     * is called to write all buffered records to the target output
     * <tt>Handler.
     *
     * @param  record  description of the log event. A null record is
     *                 silently ignored and is not published
     */
    @Override
    public synchronized void publish(LogRecord record) {
        if (!isLoggable(record)) {
            return;
        }
        int ix = (start+count)%buffer.length;
        buffer[ix] = record;
        if (count < buffer.length) {
            count++;
        } else {
            start++;
            start %= buffer.length;
        }
        if (record.getLevel().intValue() >= pushLevel.intValue()) {
            push();
        }
    }

    /**
     * Push any buffered output to the target <tt>Handler.
     * <p>
     * The buffer is then cleared.
     */
    public synchronized void push() {
        for (int i = 0; i < count; i++) {
            int ix = (start+i)%buffer.length;
            LogRecord record = buffer[ix];
            target.publish(record);
        }
        // Empty the buffer.
        start = 0;
        count = 0;
    }

    /**
     * Causes a flush on the target <tt>Handler.
     * <p>
     * Note that the current contents of the <tt>MemoryHandler
     * buffer are <b>not written out.  That requires a "push".
     */
    @Override
    public void flush() {
        target.flush();
    }

    /**
     * Close the <tt>Handler and free all associated resources.
     * This will also close the target <tt>Handler.
     *
     * @exception  SecurityException  if a security manager exists and if
     *             the caller does not have <tt>LoggingPermission("control").
     */
    @Override
    public void close() throws SecurityException {
        target.close();
        setLevel(Level.OFF);
    }

    /**
     * Set the <tt>pushLevel.  After a LogRecord is copied
     * into our internal buffer, if its level is greater than or equal to
     * the <tt>pushLevel, then push will be called.
     *
     * @param newLevel the new value of the <tt>pushLevel
     * @exception  SecurityException  if a security manager exists and if
     *             the caller does not have <tt>LoggingPermission("control").
     */
    public synchronized void setPushLevel(Level newLevel) throws SecurityException {
        if (newLevel == null) {
            throw new NullPointerException();
        }
        checkPermission();
        pushLevel = newLevel;
    }

    /**
     * Get the <tt>pushLevel.
     *
     * @return the value of the <tt>pushLevel
     */
    public Level getPushLevel() {
        return pushLevel;
    }

    /**
     * Check if this <tt>Handler would actually log a given
     * <tt>LogRecord into its internal buffer.
     * <p>
     * This method checks if the <tt>LogRecord has an appropriate level and
     * whether it satisfies any <tt>Filter.  However it does not
     * check whether the <tt>LogRecord would result in a "push" of the
     * buffer contents. It will return false if the <tt>LogRecord is null.
     * <p>
     * @param record  a <tt>LogRecord
     * @return true if the <tt>LogRecord would be logged.
     *
     */
    @Override
    public boolean isLoggable(LogRecord record) {
        return super.isLoggable(record);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MemoryHandler.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.