/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.queplix.core.utils.log;

import com.queplix.core.utils.StringHelper;
import com.queplix.core.utils.dao.AbstractPropertyFactory;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import java.io.InputStream;
import java.util.Properties;

/**
 * Abstract logger class.
 * Encapsulates <b>Jakarta Log4j<sup>TM</sup></b> logging system functionality.
 *
 * @author [ALB] Baranov Andrey
 * @author [ONZ] Oleg N. Zhovtanyuk
 * @author [MVT] Michael Trofimov
 * @version $Revision: 1.3 $ $Date: 2005/12/14 10:12:41 $4
 */

public abstract class AbstractLogger
        implements java.io.Serializable {

    // ------------------------------------------------------- Constants

    /**
     * Property Log4J external file.
     * Use JVM parameter to set it. Ex.: -Dlogj4.configuration=/path/to/log4j.*
     */
    public static final String log4jConfig = System.getProperty(
            "log4j.configuration");

    /**
     * Property Log4J inner file.
     */
    public static final String PROPERTY = "log4j.properties";
    private static Properties props;

    static {
        // If external file is absent -
        // Load file from classpath.
        if(StringHelper.isEmpty(log4jConfig)) {
            try {
                InputStream is = AbstractPropertyFactory
                        .loadSysPropertiesAsStream(AbstractLogger.class,
                                PROPERTY);
                props = new Properties();
                props.load(is);
            } catch (Exception e) {
                props = null;
                // e.printStackTrace();
            }
        }
    }

    // ------------------------------------------------------- Fields

    // Class object
    private final Class cl;

    // Logger-related reference.
    private transient Logger logger;

    // ------------------------------------------------------- Public methods

    /**
     * Constructor
     */
    public AbstractLogger() {
        cl = getClass();
    }

    /**
     * Constructor
     *
     * @param cl class (if <code>class</code> is null takes root logger)
     */
    public AbstractLogger(Class cl) {
        this.cl = cl;
    }

    /**
     * Get logger.
     *
     * @return Logger object
     */
    public Logger getLogger() {
        // already synchronized (see org.apache.log4j.Hierarchy.getLogger())
        if(logger == null) {
            if(cl == null) {
                logger = Logger.getRootLogger();
            } else {
                logger = Logger.getLogger(cl);
            }
            if(!StringHelper.isEmpty(log4jConfig)) {
                // Specified external log4j.properties!
                PropertyConfigurator.configure(log4jConfig);
            } else if(props != null) {
                // Use log4j.properties from classpath!
                PropertyConfigurator.configure(props);
            }
        }
        return logger;
    }

    // ERROR level.
    // ------------

    /**
     * Print error message.
     *
     * @param msg Message string
     */
    public void ERROR(String msg) {
        getLogger().error(msg);
    }

    /**
     * Print error message.
     *
     * @param tr Exception
     */
    public void ERROR(Throwable tr) {
        if(tr != null) {
            getLogger().error(tr.getMessage(), tr);
        } else {
            getLogger().error("Some exception");
        }
    }

    /**
     * Print error message.
     *
     * @param msg Message string
     * @param tr  Exception
     */
    public void ERROR(String msg, Throwable tr) {
//        getLogger().error( "[EXCEPTION TRACE]" );
//        getLogger().error( tr );
//        getLogger().error( "[EXCEPTION MESSAGE]" );
        getLogger().error(msg, tr);
    }

    // WARNING level.
    // --------------

    /**
     * Print error message.
     *
     * @param tr Exception
     */
    public void WARN(Throwable tr) {
        if(tr != null) {
            getLogger().warn(tr.getMessage(), tr);
        } else {
            getLogger().warn("Some exception");
        }
    }

    /**
     * Print warning message.
     *
     * @param msg Message string
     */
    public void WARN(String msg) {
        getLogger().warn(msg);
    }

    /**
     * Print warning message.
     *
     * @param msg Message string
     * @param tr  Exception
     */
    public void WARN(String msg, Throwable tr) {
        getLogger().warn(msg, tr);
    }

    // INFO level.
    // -----------

    /**
     * Print information message.
     *
     * @param msg Message string
     */
    public void INFO(String msg) {
        getLogger().info(msg);
    }

    // DEBUG level.
    // ------------

    /**
     * Print debug message.
     *
     * @param msg Message string
     */
    public void DEBUG(String msg) {
        getLogger().debug(msg);
    }

    /**
     * Print debug message.
     *
     * @param tr Exception
     */
    public void DEBUG(Throwable tr) {
        if(tr != null) {
            getLogger().debug(tr.getMessage(), tr);
        } else {
            getLogger().debug("Some exception");
        }
    }

    /**
     * Print debug message.
     *
     * @param msg Message string
     * @param tr  Exception
     */
    public void DEBUG(String msg, Throwable tr) {
        getLogger().debug(msg, tr);
    }

} // end of class
