/**
* High Availability Service (HA) for JOnAS
*
* Copyright (C) 2007,2008 Bull S.A.S.
* Copyright (C) 2006 Distributed Systems Lab.
* Universidad Polit??cnica de Madrid (Spain)
* Contact: http://lsd.ls.fi.upm.es/lsd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id$
* --------------------------------------------------------------------------
*/

package org.ow2.jonas.lib.ejb21.ha.interceptors.jrmp;

import java.io.IOException;
import java.util.Stack;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.carol.rmi.jrmp.interceptor.api.JServerRequestInfo;
import org.ow2.carol.rmi.jrmp.interceptor.spi.JServerRequestInterceptor;
import org.ow2.cmi.ha.RequestId;
import org.ow2.cmi.ha.interceptor.HAContext;
import org.ow2.cmi.ha.interceptor.HACurrent;
import org.ow2.jonas.lib.util.Log;

/**
 * This class represents the server side of the interceptor mechanism
 * implemented to transfer replication related information between client
 * and server sides
 * @author Francisco Perez-Sorrosal (fpsorrosal@no-spam@fi.upm.es)
 * @author Alberto Paz-Jimenez (apaz@no-spam@fi.upm.es)
 */
public class HAServerInterceptor implements JServerRequestInterceptor {

    /**
     * Interceptor name
     */
    private String interceptorName = "HAServerInterceptor";

    /**
     * Logger for traces
     */
    private static Logger logger = Log.getLogger("org.ow2.jonas.lib.ejb21.ha.interceptors.jrmp");

    /**
     * Constructor
     */
    public HAServerInterceptor() {
    }

    /**
     * Get the name of this interceptor
     * @return name
     */
    public String name() {
        return interceptorName;
    }

    /**
     * Analyzes the HAContext received and constructs the required
     * context on the HA current context (the thread associated class) on
     * the server side.
     */
    public void receive_request(final JServerRequestInfo jri) throws IOException {
        logger.log(BasicLevel.DEBUG, "");
        // Get the HAContext from the received info
        HAServiceContext receivedCtx = (HAServiceContext) jri.get_request_service_context(HAServiceContext.HA_CTX_ID);

        if(receivedCtx == null) {
            return;
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, receivedCtx.toString());
        }
        // Get the current Thread/HAContext association class
        HACurrent current = HACurrent.getHACurrent();

        HAContext haContext = receivedCtx.getHaContext();

        Stack<RequestId> requests = haContext.getRequests();
        current.setRequests(requests);

        boolean onFailover = haContext.isOnFailover();
        current.setOnFailover(onFailover);

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "HACtx asocciated to Thread");
        }
    }

    public void send_reply(final JServerRequestInfo jri) throws IOException {
        logger.log(BasicLevel.DEBUG, "");
        putHAContext(jri);
    }

    public void send_exception(final JServerRequestInfo jri) throws IOException {
        logger.log(BasicLevel.DEBUG, "");
        putHAContext(jri);
    }

    public void send_other(final JServerRequestInfo jri) throws IOException {
        logger.log(BasicLevel.DEBUG, "");
        putHAContext(jri);
    }

    private void putHAContext(final JServerRequestInfo jri) {

        // Get the current HA Context info associated to the thread
        HACurrent current = HACurrent.getHACurrent();

        HAContext haContext = new HAContext();

        Stack<RequestId> requests = current.getRequests();
        haContext.setRequests(requests);

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "newHACtx: " + haContext);
        }

        // Create the new HAContext to propagate between interceptors
        HAServiceContext haServiceContext = new HAServiceContext(haContext);

        // Finally, include the new HAContext created to be propagated through
        // the interceptor
        jri.add_reply_service_context(haServiceContext);
    }
}
