/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.logging;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;

import org.jboss.logging.log4j.CategoryStream;

/** This is a JMX MBean that provides three features:
1., It initalizes the log4j framework from the log4j properties format file
    specified by the ConfigurationPath attribute to that the log4j may be
    used by JBoss components.

@author <a href="mailto:phox@galactica.it">Fulco Muriglio</a>
@author Scott.Stark@jboss.org
@author <a href="mailto:davidjencks@earthlink.net">David Jencks</a>
@version $Revision: 1.7.2.3 $
*/
public class Log4jService implements Log4jServiceMBean, MBeanRegistration
{

// Attributes ----------------------------------------------------
    private Category category;
    private String configurationPath;
    private int refreshPeriod;
    private boolean refreshFlag;
    /** The previous value of System.out. */
    private PrintStream out;
    /** The previous value of System.err. */
    private PrintStream err;

// Constructors --------------------------------------------------
    public Log4jService()
    {
        this("log4j.properties", 60);
    }
    public Log4jService(String path)
    {
        this(path, 60);
    }
    /**
    @param path, the path to the log4j.properties format file
    @param refreshPeriod, the refreshPeriod in seconds to wait between each check.
    */
    public Log4jService(String path, int refreshPeriod)
    {
        this.configurationPath = path;
        this.refreshPeriod = refreshPeriod;
        this.refreshFlag = true;
    }

    /** Get the log4j.properties format config file path
    */
    public String getConfigurationPath()
    {
        return configurationPath;
    }
    /** Set the log4j.properties format config file path
    */
    public void setConfigurationPath(String path)
    {
        this.configurationPath = path;
    }
    /** Get the refresh flag. This determines if the log4j.properties file
        is reloaded every refreshPeriod seconds or not.
    */
    public boolean getRefreshFlag()
    {
        return refreshFlag;
    }
    /** Set the refresh flag. This determines if the log4j.properties file
        is reloaded every refreshPeriod seconds or not.
    */
    public void setRefreshFlag(boolean flag)
    {
        this.refreshFlag = flag;
    }
    /** Configures the log4j framework using the current service properties
        and sets the service category to the log4j root Category. This method
        throws a FileNotFoundException exception if the current
        configurationPath cannot be located to avoid interaction problems
        between the log4j framework and the JBoss ConsoleLogging service.
    */
    public void start() throws Exception
    {
        // See if this is an xml configuration file
        boolean isXML = configurationPath.endsWith(".xml");
        // Make sure the config file can be found
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        URL url = loader.getResource(configurationPath);
        if( url == null )
            throw new FileNotFoundException("Failed to find logj4 props: "+configurationPath);
        if( refreshFlag )
        {
            // configurationPath is a file path
            String path = url.getFile();
            if( isXML )
                DOMConfigurator.configureAndWatch(path, 1000*refreshPeriod);
            else
                PropertyConfigurator.configureAndWatch(path, 1000*refreshPeriod);
        }
        else
        {
            if( isXML )
                DOMConfigurator.configure(url);
            else
                PropertyConfigurator.configure(url);
        }
        this.category = Category.getRoot();

        Category stdout = Category.getInstance("STDOUT");
        out = System.out;
        System.setOut(new CategoryStream(stdout, Priority.INFO, out));
        category.info("Installed System.out adapter");

        Category stderr = Category.getInstance("STDERR");
        err = System.err;
        System.setErr(new CategoryStream(stderr, Priority.INFO, err));
        category.info("Installed System.err adapter");

        category.info("Started Log4jService, config="+url);
    }
    /** Stops the log4j framework by calling the Category.shutdown() method.
    @see org.apache.log4j.Category#shutdown()
    */
    public void stop()
    {
        if( out != null )
        {
           System.out.flush();
           System.setOut(out);
           out = null;
        }
        if( err != null )
        {
           System.err.flush();
           System.setErr(err);
           err = null;
        }
        Category.shutdown();
        if( category != null )
            category.info("Stopped Log4jService");
    }


// --- Begin MBeanRegistration interface methods
    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
    {
        start();
        ObjectName logger = new ObjectName(server.getDefaultDomain(),"service","Log");
        return name == null ? new ObjectName(OBJECT_NAME) : name;
    }
    public void postRegister(Boolean b)
    {
    }
    public void preDeregister()
    {
    }
    public void postDeregister()
    {
    }
// --- End MBeanRegistration interface methods
}
