/*
 * 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.modules.services.ejb;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.modules.services.utils.log.AbstractLogHandler;
import com.queplix.core.modules.services.utils.log.AbstractLogRecord;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;

import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.HashMap;
import java.util.Map;

/**
 * Message Driven Bean for asynchronous JDBC logging.
 *
 * @author [ONZ] Oleg N. Zhovtanyuk
 * @author [ALB] Andrey Baranov
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:30:59 $
 */

public class LogMDB
        implements MessageDrivenBean, MessageListener {

    // ================================================================== Fields

    // Runtime MDB context reference
    protected MessageDrivenContext ctx;

    // Logger
    private AbstractLogger logger;

    // Map of log handlers
    private Map logHndMap;

    // ============================================================= API methods

    /**
     * Sets MDB context.
     *
     * @param ctx MDB context to set
     */
    public void setMessageDrivenContext(MessageDrivenContext ctx) {
        this.ctx = ctx;
    }

    /**
     * Creates MDB.
     */
    public void ejbCreate() {
        logger = Log.getLog(getClass());
        logHndMap = new HashMap();

        logger.INFO("LogMDB [" + hashCode() + "] created");
    }

    /**
     * Removes MDB.
     */
    public void ejbRemove() {
    }

    /**
     * Gets a message.
     *
     * @param msg message
     */
    public void onMessage(Message msg) {

        // Message type check.
        if(!(msg instanceof ObjectMessage)) {
            logger.ERROR(
                    "LogMDB [" + hashCode() + "] got unknown message: " + msg);
            return;
        }

        // Retrieve the log record and log it.
        // Rollback transaction on error.
        try {

            // Retrieve LogRecord object.
            Object o = ((ObjectMessage) msg).getObject();
            if(o == null || !(o instanceof AbstractLogRecord)) {
                logger.ERROR("Can't get log record from message: " + msg);
                return;
            }

            AbstractLogRecord lr = (AbstractLogRecord) o;

            if(logger.getLogger().isDebugEnabled()) {
                logger.DEBUG("LogMDB [" + hashCode()
                        + "] received new log record: " + lr);
            }

            // Log the record.
            AbstractLogHandler logHnd = getLogHandler(lr.getHndClassName());
            logHnd.insert(lr);

        } catch (Throwable t) {

            /*
                     Commented by [ALB]. WAS shutdowns JMS listeners because of that.
                     @see AsyncMDB
                     try {
                         ctx.setRollbackOnly();
                     } catch( java.lang.IllegalStateException isex ) {
                         logger.ERROR( "Can't rollback transaction: " + isex.getMessage() );
                     }
             */

            try {
                logger.ERROR(t);
            } catch (Exception ex) {
            }

        } finally {
            try {
                if(logger.getLogger().isDebugEnabled()) {
                    logger.DEBUG(
                            "LogMDB [" + hashCode() + "] finished process");
                }
            } catch (Exception __ex) {
            }
        }

    } // onMessage()

    // ============================================================= Private methods

    //
    // Get Handler by the name
    //

    private synchronized AbstractLogHandler getLogHandler(String hndClassName) {

        AbstractLogHandler logHnd = (AbstractLogHandler) logHndMap.get(
                hndClassName);
        if(logHnd == null) {
            logger.DEBUG("Create new Log Handler: " + hndClassName);

            try {
                logHnd = (AbstractLogHandler) Class.forName(hndClassName)
                        .newInstance();
                logHndMap.put(hndClassName, logHnd);
            } catch (Exception ex) {
                logger.ERROR(ex);
                throw new GenericSystemException(ex);
            }
        }

        return logHnd;
    }

} // end of class
