FileDocCategorySizeDatePackage
MemoryHandler.javaAPI DocAndroid 1.5 API10608Wed May 06 22:41:04 BST 2009java.util.logging

MemoryHandler

public class MemoryHandler extends Handler
A {@code Handler} put the description of log events into a cycled memory buffer.

Mostly this {@code MemoryHandler} just puts the given {@code LogRecord} into the internal buffer and doesn't perform any formatting or any other process. When the buffer is full, the earliest buffered records will be discarded.

Every {@code MemoryHandler} has a target handler, and push action can be triggered so that all buffered records will be output to the target handler and normally the latter will publish the records. After the push action, the buffer will be cleared.

The push action can be triggered in three ways:

  • The push method is called explicitly
  • When a new {@code LogRecord} is put into the internal buffer, and it has a level which is not less than the specified push level.
  • A subclass extends this {@code MemoryHandler} and call push method implicitly according to some criteria.

{@code MemoryHandler} will read following {@code LogManager} properties for initialization, if given properties are not defined or has invalid values, default value will be used.

  • java.util.logging.MemoryHandler.level specifies the level for this {@code Handler}, defaults to {@code Level.ALL}.
  • java.util.logging.MemoryHandler.filter specifies the {@code Filter} class name, defaults to no {@code Filter}.
  • java.util.logging.MemoryHandler.size specifies the buffer size in number of {@code LogRecord}, defaults to 1000.
  • java.util.logging.MemoryHandler.push specifies the push level, defaults to level.SEVERE.
  • java.util.logging.MemoryHandler.target specifies the class of the target {@code Handler}, no default value, which means this property must be specified either by property setting or by constructor.

Fields Summary
private static final int
DEFAULT_SIZE
private Handler
target
private int
size
private Level
push
private final LogManager
manager
private LogRecord[]
buffer
private int
cursor
Constructors Summary
public MemoryHandler()
Default constructor, construct and init a {@code MemoryHandler} using {@code LogManager} properties or default values.

throws
RuntimeException if property value are invalid and no default value could be used.

    
                                                               
      
        super();
        String className = this.getClass().getName();
        //init target
        final String targetName = manager.getProperty(className+".target"); //$NON-NLS-1$
        try {
            Class<?> targetClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>(){
                public Class<?> run() throws Exception{
                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
                    if(loader == null){
                        loader = ClassLoader.getSystemClassLoader();
                    }
                    return loader.loadClass(targetName);
                }
            });
            target = (Handler) targetClass.newInstance();
        } catch (Exception e) {
            // logging.10=Cannot load target handler:{0}
            throw new RuntimeException(Messages.getString("logging.10", //$NON-NLS-1$
                    targetName));
        }
        //init size
        String sizeString = manager.getProperty(className+".size"); //$NON-NLS-1$
        if (null != sizeString) {
            try {
                size = Integer.parseInt(sizeString);
                if(size <= 0){
                    size = DEFAULT_SIZE;
                }
            } catch (Exception e) {
                printInvalidPropMessage(className+".size", sizeString, e); //$NON-NLS-1$
            }
        }
        //init push level
        String pushName = manager.getProperty(className+".push"); //$NON-NLS-1$
        if (null != pushName) {
            try {
                push = Level.parse(pushName);
            } catch (Exception e) {
                printInvalidPropMessage(className+".push", pushName, e); //$NON-NLS-1$
            }
        }
        //init other properties which are common for all Handler
        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null);  //$NON-NLS-1$//$NON-NLS-2$
        buffer = new LogRecord[size];
    
public MemoryHandler(Handler target, int size, Level pushLevel)
Construct and init a {@code MemoryHandler} using given target, size and push level, other properties using {@code LogManager} properties or default values.

param
target the given {@code Handler} to output
param
size the maximum number of buffered {@code LogRecord}, greater than zero
param
pushLevel the push level
throws
IllegalArgumentException if {@code size}<=0
throws
RuntimeException if property value are invalid and no default value could be used.

        if (size <= 0) {
            // logging.11=Size must be positive.
            throw new IllegalArgumentException(Messages.getString("logging.11")); //$NON-NLS-1$
        }
        target.getLevel();
        pushLevel.intValue();
        this.target = target;
        this.size = size;
        this.push = pushLevel;
        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null);  //$NON-NLS-1$//$NON-NLS-2$
        buffer = new LogRecord[size];
    
Methods Summary
public voidclose()
Close this handler and target handler, free all associated resources.

throws
SecurityException if security manager exists and it determines that caller does not have the required permissions to control this handler.

        manager.checkAccess();
        target.close();
        setLevel(Level.OFF);
    
public voidflush()
Call target handler to flush any buffered output. Note that this doesn't cause this {@code MemoryHandler} to push.

        target.flush();
    
public java.util.logging.LevelgetPushLevel()
Return the push level.

return
the push level

        return push;
    
public booleanisLoggable(java.util.logging.LogRecord record)

Check if given {@code LogRecord} would be put into this {@code MemoryHandler}'s internal buffer.

The given {@code LogRecord} is loggable if and only if it has appropriate level and it pass any associated filter's check.

Note that the push level is not used for this check.

param
record the given {@code LogRecord}
return
the given {@code LogRecord} if it should be logged, {@code false} if {@code LogRecord} is {@code null}.

        return super.isLoggable(record);
    
public synchronized voidpublish(java.util.logging.LogRecord record)
Put a given {@code LogRecord} into internal buffer. If given record is not loggable, just return. Otherwise it is stored in the buffer. Furthermore if the record's level is not less than the push level, the push action is triggered to output all the buffered records to the target handler, and the target handler will publish them.

param
record the log record

        if (!isLoggable(record)) {
            return;
        }
        if (cursor >= size) {
            cursor = 0;
        }
        buffer[cursor++] = record;
        if (record.getLevel().intValue() >= push.intValue()) {
            push();
        }
        return;
    
public voidpush()
Triggers a push action to output all buffered records to the target handler, and the target handler will publish them. Then the buffer is cleared.

        for (int i = cursor; i < size; i++) {
            if(null != buffer[i]) {
                target.publish(buffer[i]);
            }
            buffer[i] = null;
        }
        for (int i = 0; i < cursor; i++) {
            if(null != buffer[i]) {
                target.publish(buffer[i]);
            }
            buffer[i] = null;
        }
        cursor = 0;
    
public voidsetPushLevel(java.util.logging.Level newLevel)
Set the push level. The push level is used to check the push action triggering. When a new {@code LogRecord} is put into the internal buffer and its level is not less than the push level, the push action will be triggered. Note that set new push level won't trigger push action.

param
newLevel the new level to set.
throws
SecurityException if security manager exists and it determines that caller does not have the required permissions to control this handler.

        manager.checkAccess();
        newLevel.intValue();
        this.push = newLevel;