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

Java example source code file (ResultLogManager.java)

This example Java source code file (ResultLogManager.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

emitted, failed, file, illegalargumentexception, ioexception, log, log_file_changed, logging, management, mbeannotificationinfo, memory_log_max_capacity, objectname, outputstream, result_log_manager_name, resultlogconfig, resultrecord, string, util

The ResultLogManager.java Java example source code

/*
 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


package com.sun.jmx.examples.scandir;

import static com.sun.jmx.examples.scandir.ScanManager.getNextSeqNumber;
import com.sun.jmx.examples.scandir.config.ResultLogConfig;
import com.sun.jmx.examples.scandir.config.XmlConfigUtils;
import com.sun.jmx.examples.scandir.config.ResultRecord;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import javax.xml.bind.JAXBException;

/**
 * The <code>ResultLogManager is in charge of managing result logs.
 * {@link DirectoryScanner DirectoryScanners} can be configured to log a
 * {@link ResultRecord} whenever they take action upon a file that
 * matches their set of matching criteria.
 * The <code>ResultLogManagerMXBean is responsible for storing these
 * results in its result logs.
 * <p>The ResultLogManagerMXBean can be configured to log
 * these records to a flat file, or into a log held in memory, or both.
 * Both logs (file and memory) can be configured with a maximum capacity.
 * <br>When the maximum capacity of the memory log is reached - its first
 * entry (i.e. its eldest entry) is removed to make place for the latest.
 * <br>When the maximum capacity of the file log is reached, the file is
 * renamed by appending a tilde '~' to its name and a new result log is created.
 *
 *
 * @author Sun Microsystems, 2006 - All rights reserved.
 */
public class ResultLogManager extends NotificationBroadcasterSupport
        implements ResultLogManagerMXBean, MBeanRegistration {

    /**
     * The default singleton name of the {@link ResultLogManagerMXBean}.
     **/
    public static final ObjectName RESULT_LOG_MANAGER_NAME =
            ScanManager.makeSingletonName(ResultLogManagerMXBean.class);

    /**
     * A logger for this class.
     **/
    private static final Logger LOG =
            Logger.getLogger(ResultLogManager.class.getName());

    // The memory log
    //
    private final List<ResultRecord> memoryLog;

    // Whether the memory log capacity was reached. In that case every
    // new entry triggers the deletion of the eldest one.
    //
    private volatile boolean memCapacityReached = false;

    // The maximum number of record that the memory log can
    // contain.
    //
    private volatile int memCapacity;

    // The maximum number of record that the ResultLogManager can
    // log in the log file before creating a new file.
    //
    private volatile long fileCapacity;

    // The current log file.
    //
    private volatile File logFile;

    // The OutputStream of the current log file.
    //
    private volatile OutputStream logStream = null;

    // number of record that this object has logged in the log file
    // since the log file was created. Creating a new file or clearing
    // the log file reset this value to '0'
    //
    private volatile long logCount = 0;

    // The ResultLogManager config - modified whenever
    // ScanManager.applyConfiguration is called.
    //
    private volatile ResultLogConfig config;

    /**
     * Create a new ResultLogManagerMXBean. This constructor is package
     * protected: only the {@link ScanManager} can create a
     * <code>ResultLogManager.
     **/
    ResultLogManager() {
        // Instantiate the memory log - override the add() method so that
        // it removes the head of the list when the maximum capacity is
        // reached. Note that add() is the only method we will be calling,
        // otherwise we would have to override all the other flavors
        // of adding methods. Note also that this implies that the memoryLog
        // will *always* remain encapsulated in this object and is *never*
        // handed over (otherwise we wouldn't be able to ensure that
        // add() is the only method ever called to add a record).
        //
        memoryLog =
                Collections.synchronizedList(new LinkedList<ResultRecord>() {
            public synchronized boolean add(ResultRecord e) {
                final int max = getMemoryLogCapacity();
                while (max > 0 && size() >= max) {
                    memCapacityReached = true;
                    removeFirst();
                }
                return super.add(e);
            }
        });

        // default memory capacity
        memCapacity = 2048;

        // default file capacity: 0 means infinite ;-)
        fileCapacity = 0;

        // by default logging to file is disabled.
        logFile = null;

        // Until the ScanManager apply a new configuration, we're going to
        // work with a default ResultLogConfig object.
        config = new ResultLogConfig();
        config.setMemoryMaxRecords(memCapacity);
        config.setLogFileName(getLogFileName(false));
        config.setLogFileMaxRecords(fileCapacity);
    }


    /**
     * Allows the MBean to perform any operations it needs before being
     * registered in the MBean server.
     * <p>If the name of the MBean is not
     * specified, the MBean can provide a name for its registration. If
     * any exception is raised, the MBean will not be registered in the
     * MBean server.</p>
     * <p>The {@code ResultLogManager} uses this method to supply its own
     * default singleton ObjectName (if <var>name parameter is null).
     * @param server The MBean server in which the MBean will be registered.
     * @param name The object name of the MBean. This name is null if the
     * name parameter to one of the createMBean or registerMBean methods in
     * the MBeanServer interface is null. In that case, this method must
     * return a non-null ObjectName for the new MBean.
     * @return The name under which the MBean is to be registered. This value
     * must not be null. If the name parameter is not null, it will usually
     * but not necessarily be the returned value.
     * @throws Exception This exception will be caught by the MBean server and
     * re-thrown as an MBeanRegistrationException.
     */
    public ObjectName preRegister(MBeanServer server, ObjectName name)
    throws Exception {
        if (name == null)
            name = RESULT_LOG_MANAGER_NAME;
        objectName = name;
        mbeanServer = server;
        return name;
    }

    /**
     * Allows the MBean to perform any operations needed after having
     * been registered in the MBean server or after the registration has
     * failed.
     * <p>This implementation does nothing.

* @param registrationDone Indicates whether or not the MBean has been * successfully registered in the MBean server. The value false means * that the registration has failed. */ public void postRegister(Boolean registrationDone) { // Don't need to do anything here. } /** * Allows the MBean to perform any operations it needs before being * unregistered by the MBean server. * <p>This implementation does nothing.

* @throws Exception This exception will be caught by the MBean server and * re-thrown as an MBeanRegistrationException. */ public void preDeregister() throws Exception { // Don't need to do anything here. } /** * Allows the MBean to perform any operations needed after having been * unregistered in the MBean server. * <p>Closes the log file stream, if it is still open.

*/ public void postDeregister() { try { if (logStream != null) { synchronized(this) { logStream.flush(); logStream.close(); logFile = null; logStream = null; } } } catch (Exception x) { LOG.finest("Failed to close log properly: "+x); } } /** * Create a new empty log file from the given basename, renaming * previously existing file by appending '~' to its name. **/ private File createNewLogFile(String basename) throws IOException { return XmlConfigUtils.createNewXmlFile(basename); } /** * Check whether a new log file should be created. * If a new file needs to be created, creates it, renaming * previously existing file by appending '~' to its name. * Also reset the log count and file capacity. * Sends a notification indicating that the log file was changed. * Returns the new log stream; * Creation of a new file can be forced by passing force=true. **/ private OutputStream checkLogFile(String basename, long maxRecords, boolean force) throws IOException { final OutputStream newStream; synchronized(this) { if ((force==false) && (logCount < maxRecords)) return logStream; final OutputStream oldStream = logStream; // First close the stream. On some platforms you cannot rename // a file that has open streams... // if (oldStream != null) { oldStream.flush(); oldStream.close(); } final File newFile = (basename==null)?null:createNewLogFile(basename); newStream = (newFile==null)?null:new FileOutputStream(newFile,true); logStream = newStream; logFile = newFile; fileCapacity = maxRecords; logCount = 0; } sendNotification(new Notification(LOG_FILE_CHANGED,objectName, getNextSeqNumber(), basename)); return newStream; } // see ResultLogManagerMXBean public void log(ResultRecord record) throws IOException { if (memCapacity > 0) logToMemory(record); if (logFile != null) logToFile(record); } // see ResultLogManagerMXBean public ResultRecord[] getMemoryLog() { return memoryLog.toArray(new ResultRecord[0]); } // see ResultLogManagerMXBean public int getMemoryLogCapacity() { return memCapacity; } // see ResultLogManagerMXBean public void setMemoryLogCapacity(int maxRecords) { synchronized(this) { memCapacity = maxRecords; if (memoryLog.size() < memCapacity) memCapacityReached = false; config.setMemoryMaxRecords(maxRecords); } } // see ResultLogManagerMXBean public void setLogFileCapacity(long maxRecords) throws IOException { synchronized (this) { fileCapacity = maxRecords; config.setLogFileMaxRecords(maxRecords); } checkLogFile(getLogFileName(),fileCapacity,false); } // see ResultLogManagerMXBean public long getLogFileCapacity() { return fileCapacity; } // see ResultLogManagerMXBean public long getLoggedCount() { return logCount; } // see ResultLogManagerMXBean public void newLogFile(String logname, long maxRecord) throws IOException { checkLogFile(logname,maxRecord,true); config.setLogFileName(getLogFileName(false)); config.setLogFileMaxRecords(getLogFileCapacity()); } // see ResultLogManagerMXBean public String getLogFileName() { return getLogFileName(true); } // see ResultLogManagerMXBean public void clearLogs() throws IOException { clearMemoryLog(); clearLogFile(); } // Clear the memory log, sends a notification indicating that // the memory log was cleared. // private void clearMemoryLog()throws IOException { synchronized(this) { memoryLog.clear(); memCapacityReached = false; } sendNotification(new Notification(MEMORY_LOG_CLEARED, objectName, getNextSeqNumber(),"memory log cleared")); } // Clears the log file. // private void clearLogFile() throws IOException { // simply force the creation of a new log file. checkLogFile(getLogFileName(),fileCapacity,true); } // Log a record to the memory log. Send a notification if the // maximum capacity of the memory log is reached. // private void logToMemory(ResultRecord record) { final boolean before = memCapacityReached; final boolean after; synchronized(this) { memoryLog.add(record); after = memCapacityReached; } if (before==false && after==true) sendNotification(new Notification(MEMORY_LOG_MAX_CAPACITY, objectName, getNextSeqNumber(),"memory log capacity reached")); } // Log a record to the memory log. Send a notification if the // maximum capacity of the memory log is reached. // private void logToFile(ResultRecord record) throws IOException { final String basename; final long maxRecords; synchronized (this) { if (logFile == null) return; basename = getLogFileName(false); maxRecords = fileCapacity; } // Get the stream into which we should log. final OutputStream stream = checkLogFile(basename,maxRecords,false); // logging to file now disabled - too bad. if (stream == null) return; synchronized (this) { try { XmlConfigUtils.write(record,stream,true); stream.flush(); // don't increment logCount if we were not logging in logStream. if (stream == logStream) logCount++; } catch (JAXBException x) { final IllegalArgumentException iae = new IllegalArgumentException("bad record",x); LOG.finest("Failed to log record: "+x); throw iae; } } } /** * The notification type which indicates that the log file was switched: * <i>com.sun.jmx.examples.scandir.log.file.switched. * The message contains the name of the new file (or null if log to file * is now disabled). **/ public final static String LOG_FILE_CHANGED = "com.sun.jmx.examples.scandir.log.file.switched"; /** * The notification type which indicates that the memory log capacity has * been reached: * <i>com.sun.jmx.examples.scandir.log.memory.full. **/ public final static String MEMORY_LOG_MAX_CAPACITY = "com.sun.jmx.examples.scandir.log.memory.full"; /** * The notification type which indicates that the memory log was * cleared: * <i>com.sun.jmx.examples.scandir.log.memory.cleared. **/ public final static String MEMORY_LOG_CLEARED = "com.sun.jmx.examples.scandir.log.memory.cleared"; /** * This MBean emits three kind of notifications: * <pre> * <i>com.sun.jmx.examples.scandir.log.file.switched * <i>com.sun.jmx.examples.scandir.log.memory.full * <i>com.sun.jmx.examples.scandir.log.memory.cleared * </pre> **/ public MBeanNotificationInfo[] getNotificationInfo() { return new MBeanNotificationInfo[] { new MBeanNotificationInfo(new String[] { LOG_FILE_CHANGED}, Notification.class.getName(), "Emitted when the log file is switched") , new MBeanNotificationInfo(new String[] { MEMORY_LOG_MAX_CAPACITY}, Notification.class.getName(), "Emitted when the memory log capacity is reached") , new MBeanNotificationInfo(new String[] { MEMORY_LOG_CLEARED}, Notification.class.getName(), "Emitted when the memory log is cleared") }; } // Return the name of the log file, or null if logging to file is // disabled. private String getLogFileName(boolean absolute) { synchronized (this) { if (logFile == null) return null; if (absolute) return logFile.getAbsolutePath(); return logFile.getPath(); } } // This method is be called by the ScanManagerMXBean when a configuration // is applied. // void setConfig(ResultLogConfig logConfigBean) throws IOException { if (logConfigBean == null) throw new IllegalArgumentException("logConfigBean is null"); synchronized (this) { config = logConfigBean; setMemoryLogCapacity(config.getMemoryMaxRecords()); } final String filename = config.getLogFileName(); final String logname = getLogFileName(false); if ((filename != null && !filename.equals(logname)) || (filename == null && logname != null)) { newLogFile(config.getLogFileName(), config.getLogFileMaxRecords()); } else { setLogFileCapacity(config.getLogFileMaxRecords()); } } // This method is called by the ScanManagerMXBean when // applyCurrentResultLogConfig() is called. // ResultLogConfig getConfig() { return config; } // Set by preRegister(). private MBeanServer mbeanServer; private ObjectName objectName; }

Other Java examples (source code examples)

Here is a short list of links related to this Java ResultLogManager.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.