/**
* High Availability Service (HA) for JOnAS
*
* 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.objectweb.jonas.ha.interceptor;

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

import org.objectweb.carol.cmi.configuration.TraceCmi;
import org.objectweb.carol.cmi.ha.Constants;
import org.objectweb.carol.rmi.jrmp.interceptor.JClientRequestInfo;
import org.objectweb.carol.rmi.jrmp.interceptor.JClientRequestInterceptor;

/**
 * This class represents the client side of the interceptor mechanism
 * implemented to transfer replication related information between client
 * and server sides.
 */
public class HAClientInterceptor implements
        JClientRequestInterceptor {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

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

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

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

    /**
     * Constructs the HAContext with the required replication information on
     * the client side
     */
    public void send_request(JClientRequestInfo jri) throws IOException {

        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
            TraceCmi.debugCmiHA("HAClientInterceptor: send_request");
        }
        // Get the current HA Context info associated to the thread
        HACurrentDelegateImpl current = HACurrentDelegateImpl.getCurrent();
        // Create the new HAContext to propagate between interceptors
        HAContext newHACtx = new HAContext();
        // Fill the "req_id" field to propagate through the interceptor if the
        // nextReq has been included in the HA current context (held in the
        // thread-local variable) by the stub

        Stack requests = current.getRequests();
        newHACtx.setRequests(requests);
        newHACtx.setViewIdWrapper(current.getClientViewIdWrapper());
        newHACtx.setOnFailover(current.isOnFailover());
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("Propagating requests chain: " + newHACtx);
        }

        // Finally, include the new HAContext created to be propagated through
        // the interceptor
        jri.add_request_service_context(newHACtx);
        if (TraceCmi.isDebugCmiHA()) {
               TraceCmi.debugCmiHA("----------------------------------");
        }
    }

    public void receive_reply(JClientRequestInfo jri) throws IOException {
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
            TraceCmi.debugCmiHA("HAClientInterceptor: receive_reply");
        }
        getHAContext(jri);
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
        }
    }

    public void receive_exception(JClientRequestInfo jri) throws IOException {
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
            TraceCmi.debugCmiHA("HAClientInterceptor: receive_exception");
        }
        getHAContext(jri);
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
        }
    }

    public void receive_other(JClientRequestInfo jri) throws IOException {
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
            TraceCmi.debugCmiHA("HAClientInterceptor: receive_other");
        }
        getHAContext(jri);
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("----------------------------------");
        }
    }

    //-------------------------------------------------------------------------
    // Other public unused methods
    //-------------------------------------------------------------------------

    public void destroy() {
    }

    public void send_poll(JClientRequestInfo jri) throws IOException {
    }

    private void getHAContext(JClientRequestInfo jri) {
        // Get the HAContext from the received info
        HAContext receivedCtx = (HAContext) jri.get_request_service_context(Constants.HA_CTX_ID);
        if (TraceCmi.isDebugCmiHA()) {
            TraceCmi.debugCmiHA("receivedCtx: " + receivedCtx);
        }

        // Get the current Thread/HAContext association class
        HACurrentDelegateImpl current = HACurrentDelegateImpl.getCurrent();
        if (receivedCtx != null) {
            Stack requests = receivedCtx.getRequests();
            current.setRequests(requests);
            current.pushClientViewIdWrapper(receivedCtx.getViewIdWrapper());
        } else {
            if (TraceCmi.isDebugCmiHA()) {
                TraceCmi.debugCmiHA("No HA context");
            }
        }
    }
}
