/*
 * Copyright 2003,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * 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 org.apache.pluto.core;

import java.io.IOException;

import javax.portlet.PortletException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pluto.Constants;
import org.apache.pluto.internal.InternalPortletWindow;
import org.apache.pluto.internal.impl.ActionRequestImpl;
import org.apache.pluto.internal.impl.ActionResponseImpl;
import org.apache.pluto.internal.impl.PortletRequestImpl;
import org.apache.pluto.internal.impl.PortletResponseImpl;
import org.apache.pluto.internal.impl.RenderRequestImpl;
import org.apache.pluto.internal.impl.RenderResponseImpl;
import org.apache.pluto.util.StringManager;

/**
 * Used internally to invoke/dispatch requests from the container to
 * the portlet application.
 *
 * @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a>
 * @author <a href="mailto:zheng@apache.org">ZHENG Zhong</a>
 */
class PortletInvoker {

    /** Logger.  */
    private static final Log LOG = LogFactory.getLog(PortletInvoker.class);

    /** Exception Messages. */
    private static final StringManager EXCEPTIONS = StringManager.getManager(
    		PortletInvoker.class.getPackage().getName());
    
    
    // Private Member Variables ------------------------------------------------
    
    /** Portlet Window for which we are invoking the portlet. */
    private InternalPortletWindow portletWindow = null;
    
    
    // Constructor -------------------------------------------------------------
    
    /**
     * Default Constructor.  Create a new invoker which
     * is initialized for the given <code>InternalPortletWindow</code>.
     *
     * @param portletWindow  the portlet window.
     */
    public PortletInvoker(InternalPortletWindow portletWindow) {
        this.portletWindow = portletWindow;
    }
    
    
    // Public Methods ----------------------------------------------------------
    
    /**
     * Invoke the portlet with an action request.
     *
     * @param request action request used for the invocation.
     * @param response action response used for the invocation.
     * @throws PortletException if a error occurs within the portlet.
     * @throws IOException if an IO error occurs writing the response.
     *
     * @see PortletServlet
     * @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
     */
    public void action(ActionRequestImpl request, ActionResponseImpl response)
    throws PortletException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Performing Action Invocation");
        }
        invoke(request, response, Constants.METHOD_ACTION);
    }

    /**
     * Invoke the portlet with a render request.
     *
     * @param request action request used for the invocation.
     * @param response action response used for the invocation.
     * @throws PortletException if a error occurs within the portlet.
     * @throws IOException if an IO error occurs writing the response.
     *
     * @see PortletServlet
     * @see javax.portlet.Portlet#render(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
     */
    public void render(RenderRequestImpl request, RenderResponseImpl response)
    throws PortletException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Performing Render Invocation");
        }
        invoke(request, response, Constants.METHOD_RENDER);
    }

    /**
     * Invoke the portlet with a load request.
     *
     * @param request action request used for the invocation.
     * @param response action response used for the invocation.
     * @throws PortletException if a error occurs within the portlet.
     *
     * @see PortletServlet
     */
    public void load(PortletRequestImpl request, PortletResponseImpl response)
    throws PortletException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Performing Load Invocation");
        }
        invoke(request, response, Constants.METHOD_NOOP);
    }
    
    
    // Private Invoke Method ---------------------------------------------------
    
    /**
     * Perform the invocation.
     *
     * @param request portlet request
     * @param response portlet response
     * @param methodID method identifier
     * @throws PortletException if a portlet exception occurs.
     * @throws IOException if an error occurs writing to the response.
     */
    private void invoke(PortletRequestImpl request,
                        PortletResponseImpl response,
                        Integer methodID)
    throws PortletException, IOException {

        String uri = portletWindow.getPortletEntity().getControllerServletUri();
        if (LOG.isDebugEnabled()) {
        	LOG.debug("Dispatching to portlet servlet at: " + uri);
        }
        
        ServletContext servletContext = portletWindow.getServletContext();
        RequestDispatcher dispatcher = servletContext.getRequestDispatcher(uri);

        if (dispatcher != null) {
            try {
                // Tomcat does not like to properly include wrapped requests
                // and responses. Thus we "unwrap" and then include.
                HttpServletRequest servletRequest =
                		request.getHttpServletRequest();
                HttpServletResponse servletResponse =
                		response.getHttpServletResponse();
                
                servletRequest.setAttribute(Constants.METHOD_ID, methodID);
                servletRequest.setAttribute(Constants.PORTLET_REQUEST, request);
                servletRequest.setAttribute(Constants.PORTLET_RESPONSE, response);
                
                dispatcher.include(servletRequest, servletResponse);

            } catch (javax.servlet.UnavailableException ex) {
                int seconds = ex.isPermanent()?-1:ex.getUnavailableSeconds();
                String message =  EXCEPTIONS.getString(
                    "error.portlet.invoker.unavailable",
                    uri, new String[] {String.valueOf(seconds)}
                );
                if (LOG.isErrorEnabled()) {
                    LOG.error(message, ex);
                }
                throw new javax.portlet.UnavailableException(
                        message, seconds);
                
            } catch (javax.servlet.ServletException ex) {
                String message = EXCEPTIONS.getString("error.portlet.invoker");
                if(LOG.isErrorEnabled()) {
                    LOG.error(message);
                }

                if (ex.getRootCause() != null &&
                    ex.getRootCause() instanceof PortletException) {
                        throw (PortletException) ex.getRootCause();
                }
                else if(ex.getRootCause() != null) {
                    throw new PortletException(ex.getRootCause());
                }
                else {
                    throw new PortletException(ex);
                }
                
            } finally {
                request.removeAttribute(Constants.METHOD_ID);
                request.removeAttribute(Constants.PORTLET_REQUEST);
                request.removeAttribute(Constants.PORTLET_RESPONSE);
            }
        } else {
            String msg = EXCEPTIONS.getString(
                "error.portlet.invoker.dispatcher",
                new String[] {servletContext.getServletContextName(), uri}
            );
            if (LOG.isErrorEnabled()) {
                LOG.error(msg);
            }
            throw new PortletException(msg);
        }
    }

}
