Package org.gatein.wsrp.consumer.handlers

Source Code of org.gatein.wsrp.consumer.handlers.InvocationHandler$RequestPrecursor

/*
* JBoss, a division of Red Hat
* Copyright 2011, Red Hat Middleware, LLC, and individual
* contributors as indicated by the @authors tag. See the
* copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This 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 (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.gatein.wsrp.consumer.handlers;

import org.gatein.common.util.ContentInfo;
import org.gatein.common.util.ParameterValidation;
import org.gatein.pc.api.PortletInvokerException;
import org.gatein.pc.api.StateString;
import org.gatein.pc.api.invocation.PortletInvocation;
import org.gatein.pc.api.invocation.response.ErrorResponse;
import org.gatein.pc.api.invocation.response.PortletInvocationResponse;
import org.gatein.pc.api.spi.InstanceContext;
import org.gatein.pc.api.spi.PortletInvocationContext;
import org.gatein.pc.api.spi.SecurityContext;
import org.gatein.pc.api.spi.WindowContext;
import org.gatein.wsrp.WSRPConstants;
import org.gatein.wsrp.WSRPTypeFactory;
import org.gatein.wsrp.WSRPUtils;
import org.gatein.wsrp.consumer.ProducerInfo;
import org.gatein.wsrp.consumer.WSRPConsumerImpl;
import org.gatein.wsrp.consumer.portlet.info.WSRPPortletInfo;
import org.gatein.wsrp.consumer.spi.WSRPConsumerSPI;
import org.gatein.wsrp.spec.v2.WSRP2RewritingConstants;
import org.oasis.wsrp.v2.InvalidCookie;
import org.oasis.wsrp.v2.InvalidRegistration;
import org.oasis.wsrp.v2.InvalidSession;
import org.oasis.wsrp.v2.MarkupParams;
import org.oasis.wsrp.v2.ModifyRegistrationRequired;
import org.oasis.wsrp.v2.NavigationalContext;
import org.oasis.wsrp.v2.OperationFailed;
import org.oasis.wsrp.v2.PortletContext;
import org.oasis.wsrp.v2.RegistrationContext;
import org.oasis.wsrp.v2.RuntimeContext;
import org.oasis.wsrp.v2.UserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.RemoteException;
import java.util.Collections;
import java.util.Map;

/**
* @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
* @version $Revision: 13121 $
* @since 2.4 (May 31, 2006)
*/
public abstract class InvocationHandler<Invocation extends PortletInvocation, Request, Response>
{
   protected final WSRPConsumerSPI consumer;

   protected static Logger log = LoggerFactory.getLogger(InvocationHandler.class);
   protected static boolean debug = log.isDebugEnabled();
   protected static boolean trace = log.isTraceEnabled();

   /**
    * Value indicating that we should not try further (unrecoverable error) for getMarkup and
    * processBlockingInteraction
    */
   private static final int DO_NOT_RETRY = -1;

   /** Maximum number of tries before giving up. */
   private static final int MAXIMUM_RETRY_NUMBER = 3;

   protected InvocationHandler(WSRPConsumerSPI consumer)
   {
      this.consumer = consumer;
   }

   public PortletInvocationResponse handle(Invocation invocation) throws PortletInvokerException
   {
      // Extracts basic required information from invocation
      RequestPrecursor<Invocation> requestPrecursor = new RequestPrecursor<Invocation>(consumer, invocation);

      // create the specific request
      Request request = prepareRequest(requestPrecursor, invocation);

      // Perform the request
      try
      {
         Response response = performRequest(request, invocation);
         return processResponse(response, invocation, requestPrecursor);
      }
      catch (Exception e)
      {
         if (!(e instanceof PortletInvokerException))
         {
            ErrorResponse errorResponse = dealWithError(e, invocation, getRuntimeContextFrom(request));
            if (errorResponse != null)
            {
               return unwrapWSRPError(errorResponse);
            }
            else
            {
               return new ErrorResponse(e);
            }
         }
         else
         {
            throw (PortletInvokerException)e;
         }
      }
      /*if (response instanceof ErrorResponse)
      {
         return unwrapWSRPError((ErrorResponse)response);
      }*/
   }

   protected Response performRequest(Request request, PortletInvocation invocation) throws Exception
   {
      int retryCount = 0;
      Response response = null;

      // as long as we don't get a non-null response and we're allowed to try again, try to perform the request
      while (response == null && retryCount++ <= MAXIMUM_RETRY_NUMBER)
      {
         if (debug)
         {
            log.debug("performRequest: " + retryCount + " attempt(s) out of " + MAXIMUM_RETRY_NUMBER + " possible");
         }
         SessionHandler sessionHandler = consumer.getSessionHandler();

         // prepare everything for the request
         RuntimeContext runtimeContext = getRuntimeContextFrom(request);

         if (runtimeContext != null)
         {
            WindowContext windowContext = invocation.getWindowContext();
            runtimeContext.setNamespacePrefix(WSRPTypeFactory.getNamespaceFrom(windowContext));

            InstanceContext instanceContext = invocation.getInstanceContext();
            runtimeContext.setPortletInstanceKey(instanceContext == null ? null : instanceContext.getId());
         }

         try
         {
            sessionHandler.initCookieIfNeeded(invocation);

            // if we need cookies, set the current group id
            sessionHandler.initProducerSessionInformation(invocation);

            response = performRequest(request);

            sessionHandler.updateCookiesIfNeeded(invocation);
         }
         /*catch (Exception e)
         {
            ErrorResponse errorResponse = dealWithError(e, invocation, runtimeContext);
            if (errorResponse != null)
            {
               return errorResponse;
            }
         }*/
         finally
         {
            // we're done: reset currently held information
            sessionHandler.resetCurrentlyHeldInformation();
         }
      }

      if (retryCount >= MAXIMUM_RETRY_NUMBER)
      {
         /*return new ErrorResponse(new RuntimeException("Tried to perform request " + MAXIMUM_RETRY_NUMBER
            + " times before giving up. This usually happens if an error in the WS stack prevented the messages to be " +
            "properly transmitted. Look at server.log for clues as to what happened..."));*/
         throw new RuntimeException("Tried to perform request " + MAXIMUM_RETRY_NUMBER
            + " times before giving up. This usually happens if an error in the WS stack prevented the messages to be " +
            "properly transmitted. Look at server.log for clues as to what happened...");
      }

      if (debug)
      {
         log.debug("performRequest finished. Response is " + (response != null ? response.getClass().getName() : null));
      }
      return response;
   }

   /**
    * Deals with common error conditions.
    *
    * @param error          the error that is to be dealt with
    * @param invocation     the invocation that caused the error to occur
    * @param runtimeContext the current WSRP RuntimeContext
    * @return an ErrorResponse if the error couldn't be dealt with or <code>null</code> if the error was correctly
    *         handled
    */
   private ErrorResponse dealWithError(Exception error, Invocation invocation, RuntimeContext runtimeContext)
      throws PortletInvokerException
   {
      log.error("The portlet threw an exception", error);

      SessionHandler sessionHandler = consumer.getSessionHandler();

      // recoverable errors
      if (error instanceof InvalidCookie)
      {
         // we need to re-init the cookies
         log.debug("Re-initializing cookies after InvalidCookieFault.");
         // force a producer info refresh because the invalid cookie might be due to a change of cookie policy on the producer
         consumer.refreshProducerInfo();
         try
         {
            sessionHandler.initCookieIfNeeded(invocation);
         }
         catch (Exception e)
         {
            log.debug("Couldn't init cookie: " + e.getLocalizedMessage());
            return new ErrorResponse(e);
         }
      }
      else if (error instanceof InvalidSession)
      {
         log.debug("Session invalidated after InvalidSessionFault, will re-send session-stored information.");
         sessionHandler.handleInvalidSessionFault(invocation, runtimeContext);
      }
      else if (error instanceof InvalidRegistration)
      {
         log.debug("Invalid registration");
         consumer.handleInvalidRegistrationFault();
      }
      else if (error instanceof ModifyRegistrationRequired)
      {
         ProducerInfo producerInfo = consumer.getProducerInfo();

         log.debug("Producer " + producerInfo.getId() + " indicated that modifyRegistration should be called.");

         producerInfo.setModifyRegistrationRequired(true);
         producerInfo.setActiveAndSave(false);

         return new ErrorResponse(error);
      }
      else
      {
         // other errors cannot be dealt with: we have an error condition
         return new ErrorResponse(error);
      }
      return null;
   }

   protected ErrorResponse unwrapWSRPError(ErrorResponse errorResponse)
   {
      Throwable cause = errorResponse.getCause();
      if (cause != null)
      {
         // unwrap original exception...
         if (cause instanceof OperationFailed && cause.getCause() != null)
         {
            cause = cause.getCause();
         }
         else if (cause instanceof RemoteException)
         {
            cause = ((RemoteException)cause).detail;
         }
         log.debug("Invocation of action failed: " + cause.getMessage(), cause); // fix-me?
         return new ErrorResponse(cause);
      }
      else
      {
         log.debug("Invocation of action failed: " + errorResponse.getMessage());
         return errorResponse;
      }
   }

//   protected abstract void updateUserContext(Request request, UserContext userContext);

//   protected abstract void updateRegistrationContext(Request request) throws PortletInvokerException;

   protected abstract RuntimeContext getRuntimeContextFrom(Request request);

   protected abstract Response performRequest(Request request) throws Exception;

   protected abstract Request prepareRequest(RequestPrecursor<Invocation> requestPrecursor, Invocation invocation);

   protected abstract PortletInvocationResponse processResponse(Response response, Invocation invocation, RequestPrecursor<Invocation> requestPrecursor) throws PortletInvokerException;

   /**
    * Extracts basic required elements for all invocation requests.
    *
    * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
    * @version $Revision: 13121 $
    * @since 2.4
    */
   protected static class RequestPrecursor<Invocation extends PortletInvocation>
   {
      private final static Logger log = LoggerFactory.getLogger(RequestPrecursor.class);

      private final PortletContext portletContext;
      private final RuntimeContext runtimeContext;
      private final MarkupParams markupParams;
      private final RegistrationContext registrationContext;
      private final UserContext userContext;
      private static final String PORTLET_HANDLE = "portlet handle";
      private static final String SECURITY_CONTEXT = "security context";
      private static final String USER_CONTEXT = "user context";
      private static final String INVOCATION_CONTEXT = "invocation context";
      private static final String STREAM_INFO = "stream info in invocation context";
      private static final String USER_AGENT = "User-Agent";

      public RequestPrecursor(WSRPConsumerSPI wsrpConsumer, Invocation invocation) throws PortletInvokerException
      {
         // retrieve handle
         portletContext = WSRPUtils.convertToWSRPPortletContext(WSRPConsumerImpl.getPortletContext(invocation));
         ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(getPortletHandle(), PORTLET_HANDLE, null);
         if (log.isDebugEnabled())
         {
            log.debug("About to invoke on portlet: " + getPortletHandle());
         }

         // registration context
         registrationContext = wsrpConsumer.getRegistrationContext();


         // create runtime context
         SecurityContext securityContext = invocation.getSecurityContext();
         ParameterValidation.throwIllegalArgExceptionIfNull(securityContext, SECURITY_CONTEXT);
         String authType = WSRPUtils.convertRequestAuthTypeToWSRPAuthType(securityContext.getAuthType());

         String portletInstanceKey = WSRPTypeFactory.getPortletInstanceKey(invocation.getInstanceContext());

         String namespacePrefix = WSRPTypeFactory.getNamespacePrefix(invocation.getWindowContext(), getPortletHandle());

         runtimeContext = WSRPTypeFactory.createRuntimeContext(authType, portletInstanceKey, namespacePrefix);

         WSRPPortletInfo info = wsrpConsumer.getPortletInfo(invocation);

         // user context
         userContext = wsrpConsumer.getUserContextFrom(info, invocation, runtimeContext);

         // templates
         wsrpConsumer.setTemplatesIfNeeded(info, invocation, getRuntimeContext());

         // set the session id if needed
         wsrpConsumer.getSessionHandler().setSessionIdIfNeeded(invocation, getRuntimeContext(), getPortletHandle());

         // create markup params
         org.gatein.pc.api.spi.UserContext userContext = invocation.getUserContext();
         ParameterValidation.throwIllegalArgExceptionIfNull(userContext, USER_CONTEXT);
         PortletInvocationContext context = invocation.getContext();
         ParameterValidation.throwIllegalArgExceptionIfNull(context, INVOCATION_CONTEXT);
         ContentInfo streamInfo = context.getMarkupInfo();
         ParameterValidation.throwIllegalArgExceptionIfNull(streamInfo, STREAM_INFO);

         String mode;
         try
         {
            mode = WSRPUtils.getWSRPNameFromJSR168PortletMode(invocation.getMode());
         }
         catch (Exception e)
         {
            log.debug("Mode was null in context.");
            mode = WSRPConstants.VIEW_MODE;
         }

         String windowState;
         try
         {
            windowState = WSRPUtils.getWSRPNameFromJSR168WindowState(invocation.getWindowState());
         }
         catch (Exception e)
         {
            log.debug("WindowState was null in context.");
            windowState = WSRPConstants.NORMAL_WINDOW_STATE;
         }

         this.markupParams = WSRPTypeFactory.createMarkupParams(securityContext.isSecure(),
            WSRPUtils.convertLocalesToRFC3066LanguageTags(userContext.getLocales()),
            Collections.singletonList(streamInfo.getMediaType().getValue()), mode, windowState);
         String userAgent = WSRPConsumerImpl.getHttpRequest(invocation).getHeader(USER_AGENT);
         getMarkupParams().setClientData(WSRPTypeFactory.createClientData(userAgent));

         // navigational state
         StateString navigationalState = invocation.getNavigationalState();
         Map<String, String[]> publicNavigationalState = invocation.getPublicNavigationalState();

         // it is possible to get additional public navigational state from the invocation attributes if the producer used templates:
         String publicNS = (String)invocation.getAttribute(WSRP2RewritingConstants.NAVIGATIONAL_VALUES);
         if (!ParameterValidation.isNullOrEmpty(publicNS))
         {
            publicNavigationalState.putAll(WSRPUtils.decodePublicNS(publicNS));
         }

         NavigationalContext navigationalContext = WSRPTypeFactory.createNavigationalContextOrNull(navigationalState, publicNavigationalState);
         getMarkupParams().setNavigationalContext(navigationalContext);

         if (log.isDebugEnabled())
         {
            log.debug(WSRPUtils.toString(getMarkupParams()));
         }
      }

      public String getPortletHandle()
      {
         return portletContext.getPortletHandle();
      }


      public PortletContext getPortletContext()
      {
         return portletContext;
      }

      public RegistrationContext getRegistrationContext()
      {
         return registrationContext;
      }

      public UserContext getUserContext()
      {
         return userContext;
      }

      public RuntimeContext getRuntimeContext()
      {
         return runtimeContext;
      }

      public MarkupParams getMarkupParams()
      {
         return markupParams;
      }
   }
}
TOP

Related Classes of org.gatein.wsrp.consumer.handlers.InvocationHandler$RequestPrecursor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.