Package org.jboss.portletbridge

Source Code of org.jboss.portletbridge.AjaxPortletBridge$ParameterFunction

/******************************************************************************
* JBoss, a division of Red Hat                                               *
* Copyright 2006, 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.jboss.portletbridge;


import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.el.ELContext;
import javax.el.ELContextEvent;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.render.RenderKitFactory;
import javax.faces.webapp.FacesServlet;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletMode;
import javax.portlet.PortletModeException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.StateAwareResponse;
import javax.portlet.WindowState;
import javax.portlet.WindowStateException;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeEventHandler;
import javax.portlet.faces.BridgeException;
import javax.portlet.faces.BridgePublicRenderParameterHandler;
import javax.portlet.faces.event.EventNavigationResult;

import org.jboss.portletbridge.context.InitFacesContext;
import org.jboss.portletbridge.context.PortalActionURL;
import org.jboss.portletbridge.context.PortletBridgeContext;
import org.jboss.portletbridge.util.BridgeLogger;
import org.jboss.portletbridge.util.FacesConfig;
import org.jboss.portletbridge.util.WebXML;

/**
* @author asmirnov
*/
public class AjaxPortletBridge implements Bridge,
    BridgeConfig {

  public static final String VIEWID_HISTORY_PREFIX = Bridge.VIEWID_HISTORY
      + ".";
  private static final Logger log = BridgeLogger.BRIDGE.getLogger();
  private static final String EXCEPTION_HANDLER_CLASS_PARAMETER = ExceptionHandler.class
      .getName();
  public static final String AJAX_NAMESPACE_PARAMETER = "org.ajax4jsf.portlet.NAMESPACE";
  public static final String VIEW_ID_PARAMETERS = "org.jboss.portletbridge.VIEW_ID_PARAMETERS";
  /**
   * Flag indicates what bridge has been initialized.
   */
  private boolean initialized = false;
  /**
   * Saved portlet configuration.
   */
  private PortletConfig portletConfig;
  /**
   *
   */
  private ExceptionHandler exceptionHandler;
  /**
   *
   */
  private Lifecycle lifecycle;
  /**
   *
   */
  private FacesContextFactory facesContextFactory;
  /**
   *
   */
  private List<String> facesServletMappings;

  Map<String, Map<String,String>> filterInitParams;
 
  /**
   *
   */
  private Set<ExcludedRequestAttribute> excludedAttributes;
  /**
   *
   */
  private boolean preserveActionParams;
 
  private int numberOfRequestScopes = RequestScopeManager.DEFAULT_MAX_MANAGED_SCOPES;
  /**
   *
   */
  private Map<String, String> defaultViewIdMap;
  /**
   *
   */
  private Map<Class<? extends Throwable>, String> errorPages;

  // public RichFacesHelper richFacesHelper;
  // public boolean RICHFACES_ENABLED;
  /**
   *
   */
  private Application application;
  /**
   *
   */
  private BridgeEventHandler eventHandler;
  /**
   *
   */
  private BridgePublicRenderParameterHandler publicParameterHandler;
  /**
   *
   */
  private BridgeStrategy strategy;
  private Map<String, String> publicParameterMapping;


  /*
   * (non-Javadoc)
   *
   * @see javax.portlet.faces.Bridge#destroy()
   */
  public void destroy() {
    if (log.isLoggable(Level.FINE)) {
      log.fine("Destroy portletbridge "
          + getPortletConfig().getPortletName());
    }
    this.lifecycle = null;
    this.facesContextFactory = null;
//    this.application.removeELContextListener(this);
    this.application = null;
    this.initialized = false;
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.portlet.faces.Bridge#init(javax.portlet.PortletConfig)
   */
  @SuppressWarnings("unchecked")
  public void init(PortletConfig config) throws BridgeException {
    if (null == config) {
      throw new NullPointerException(
          "No PortletConfig at the bridge initialization");
    }
    if (initialized) {
      throw new BridgeException("JSF portlet bridge already initialized");
    }
    String portletName = config.getPortletName();
    if (log.isLoggable(Level.FINE)) {
      log.fine("Start portletbridge initialization for " + portletName);
    }

    this.portletConfig = config;
    PortletContext portletContext = config.getPortletContext();
  
    WebXML webXml = new WebXML();      
        webXml.parse(portletContext);
        this.filterInitParams = webXml.getFilterInitParams();

    initFaces(portletContext);
    // add locales to faces application
    transferLocales(config);
    // Register exception handler.
    exceptionHandler = createExceptionHandler();
    // Parse web.xml for a Faces Servlet mappings.
    this.facesServletMappings = webXml.getFacesServletMappings();
    
    errorPages = webXml.getErrorViews();
    // Get all excluded request attributes names.
    this.excludedAttributes = new HashSet<ExcludedRequestAttribute>();
    String bridgeParametersPrefix = Bridge.BRIDGE_PACKAGE_PREFIX
        + portletName + ".";
    List<String> excluded = (List<String>) portletContext
        .getAttribute(bridgeParametersPrefix
            + Bridge.EXCLUDED_REQUEST_ATTRIBUTES);
    if (null != excluded) {
      for (String name : excluded) {
        excludedAttributes.add(new ExcludedRequestAttribute(name));
      }
    }
    String maxScopesParameter = portletContext.getInitParameter(Bridge.MAX_MANAGED_REQUEST_SCOPES);
    if (null != maxScopesParameter) {
      numberOfRequestScopes = Integer.parseInt(maxScopesParameter);
    }

    FacesConfig facesConfig = new FacesConfig();
    facesConfig.parse(portletContext);
    excluded = facesConfig.getExcludedAttributes();
    if (null != excluded) {
      for (String name : excluded) {
        excludedAttributes.add(new ExcludedRequestAttribute(name));
      }
    }
    publicParameterMapping = facesConfig.getParameterMapping();
    // Get preserve action parameters flag
    Boolean preserveParams = (Boolean) portletContext
        .getAttribute(bridgeParametersPrefix
            + Bridge.PRESERVE_ACTION_PARAMS);
    this.preserveActionParams = Boolean.TRUE.equals(preserveParams);
    // Get devault view's Map.
    this.defaultViewIdMap = (Map<String, String>) portletContext
        .getAttribute(bridgeParametersPrefix
            + Bridge.DEFAULT_VIEWID_MAP);
    if (null == this.defaultViewIdMap || 0 == this.defaultViewIdMap.size()) {
      throw new BridgeException("No JSF view id's defined in portlet");
    }
    // Event Handler
    eventHandler = (BridgeEventHandler) portletContext
        .getAttribute(bridgeParametersPrefix
            + Bridge.BRIDGE_EVENT_HANDLER);
    // Public Parameters Handler
    publicParameterHandler = (BridgePublicRenderParameterHandler) portletContext
        .getAttribute(bridgeParametersPrefix
            + Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER);
    // Initialization done.
    initialized = true;
    if (log.isLoggable(Level.FINE)) {
      log.fine("Done portletbridge initialization for " + portletName);
    }
  }

  /**
   * @param portletContext
   */
  protected void initFaces(PortletContext portletContext) {
    try {
      // get faces lifecycle instance. Name of the Lifecycle can be
      // changed by the init parameter, as described in the JSR 301
      // PLT
      // 3.2
      strategy = BridgeStrategy.getCurrentStrategy(this);
      LifecycleFactory factory = (LifecycleFactory) FactoryFinder
          .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
      String lifecycleId = portletContext
          .getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
      if (null == lifecycleId) {
        lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
      }
      if (log.isLoggable(Level.FINE)) {
        log.fine("Create instance of a JSF lifecycle " + lifecycleId);
      }
      this.lifecycle = factory.getLifecycle(lifecycleId);
      // get faces context factory instance
      this.facesContextFactory = (FacesContextFactory) FactoryFinder
          .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
      this.lifecycle.getPhaseListeners();
      // get Application instance.
      ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder
          .getFactory(FactoryFinder.APPLICATION_FACTORY);
      application = appFactory.getApplication();

      // Setup appropriate UIViewRoot and ViewRootRenderer
      RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
          .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
      // Setup renderkit for portlet bridge. 
      FacesContext context = new InitFacesContext(application,
          portletContext);
      strategy.init(context, renderKitFactory);
      context.release();
    } catch (FacesException e) {
      throw new BridgeException("JSF Initialization error", e);
    }
  }

  protected Application getApplication() {
    return application;
  }

  /**
   * Transfer protlet locales to JSF {@link Application}. JSF framework gets locales from faces-config.xml but portlet
   * can define its own.
   * @param config
   */
  protected void transferLocales(PortletConfig config) {
    // Get configured faces locales.
    Iterator<Locale> supportedLocales = getApplication()
            .getSupportedLocales();
    HashSet<Locale> facesLocales = new HashSet<Locale>();
    while (supportedLocales.hasNext()) {
      facesLocales.add(supportedLocales.next());
    }
    ArrayList<Locale> portletLocales = Collections.list(config
            .getSupportedLocales());
    // Append portlet locales to Faces if portlet defines additional ones.
    // https://jira.jboss.org/jira/browse/PBR-100
    if (!facesLocales.containsAll(portletLocales)) {
      facesLocales.addAll(portletLocales);
      getApplication().setSupportedLocales(facesLocales);
    }
  }

  protected ExceptionHandler createExceptionHandler(
      ) {
    ExceptionHandler handler = createInstance(EXCEPTION_HANDLER_CLASS_PARAMETER);
    if (null == handler) {
      handler = new ExceptionHandlerImpl();
    }
    return handler;
  }
 
  @SuppressWarnings("unchecked")
  protected <E> E createInstance(String classNameParameter){
    String className = getPortletConfig().getPortletContext().getInitParameter(classNameParameter);
    E instance = null;
    if(null != className){
      ClassLoader classLoader = getClassLoader();
      try {
        Class<? extends E> clazz = (Class<? extends E>) classLoader.loadClass(className);
        instance = clazz.newInstance();
      } catch (Exception e) {
        log.log(Level.SEVERE,"Class load error: "+className,e);
      }
    }
    return instance;
  }

  protected ClassLoader getClassLoader() {
    ClassLoader classLoader = Thread.currentThread()
        .getContextClassLoader();
    if (null == classLoader) {
      classLoader = this.getClass().getClassLoader();
    }
    return classLoader;
  }

  public void doFacesRequest(ActionRequest request, ActionResponse response)
      throws BridgeException {
    assertParameters(request, response);
    if (log.isLoggable(Level.FINE)) {
      log.fine("Start bridge action request processing for portlet "
          + getPortletName());
    }
    PortletBridgeContext bridgeContext = initRequest(request, response, Bridge.PortletPhase.ACTION_PHASE);
    RequestScopeManager requestStateManager = RequestScopeManager.getInstance(request,numberOfRequestScopes);
    StateId stateId = requestStateManager
        .getStateId(request,response);
    bridgeContext.setStateId(stateId);
    BridgeRequestScope windowState = new BridgeRequestScope();
    bridgeContext.setRequestScope(windowState);
    FacesContext facesContext = createFacesContext(request, response);
    try {
      strategy.beforeActionRequest(facesContext);
      processIncomingParameters(facesContext, request);
      execute(facesContext);
      strategy.afterActionRequestExecute(facesContext);
      // save request scope variables and Faces Messages.
      if (!facesContext.getResponseComplete()) {
        // Setup portlet modes from parameters.
        Map<String, String[]> viewIdParameters = bridgeContext.getViewIdParameters();
        if (null != viewIdParameters && viewIdParameters.size() > 0) {
          processPortletParameters(response, stateId, facesContext,
              facesContext.getViewRoot().getViewId(),
              viewIdParameters);
        }
        processOutgoingParameters(facesContext,request,response);
        // Save view state for a render phases.
        facesContext.getApplication().getStateManager().saveView(
            facesContext);
        windowState.saveRequest(facesContext, true);
      } else {
        windowState.reset();
        String redirectViewId = bridgeContext.getRedirectViewId();
        if (null != redirectViewId) {
          windowState.setViewId(redirectViewId);
          // Save redirect request parameters.
          Map<String, String[]> newRequestParameters = bridgeContext
              .getRedirectRequestParameters();
          windowState.setRequestParameters(newRequestParameters);
          processPortletParameters(response, stateId, facesContext,
              redirectViewId, newRequestParameters);
          processOutgoingParameters(facesContext,request,response);
        }
      }
     
    } catch (Exception e) {
      // handle exception.
      exceptionHandler.processActionException(facesContext, windowState,
          e);
    } finally {
         if (null != bridgeContext.getRedirectViewId() || !facesContext.getResponseComplete()) {
       requestStateManager.saveRequestScope(stateId, windowState);
            response.setRenderParameter(RequestScopeManager.STATE_ID_PARAMETER, stateId.toString());
         }
      strategy.afterActionRequest(facesContext);
      facesContext.release();
    }
  }
 
  private static interface ParameterFunction {
    public boolean processParameter(ELContext elContext,
              Map<String, String[]> publicParameters, String name,
              ValueExpression valueExpression);
  }

  private void processOutgoingParameters(FacesContext facesContext,
          PortletRequest request, final StateAwareResponse response) {
    Enumeration<String> parameterNames = getPortletConfig()
            .getPublicRenderParameterNames();
    if (null != publicParameterMapping && publicParameterMapping.size() > 0
            && parameterNames.hasMoreElements()) {
      ParameterFunction outgoingFunction = new ParameterFunction() {
        public boolean processParameter(ELContext elContext,
                Map<String, String[]> publicParameters, String name,
                ValueExpression valueExpression) {
          boolean valueChanged = false;
          String modelValue = (String) valueExpression.getValue(elContext);
          if (null != modelValue) {
            String[] values = publicParameters.get(name);
            String parameterValue = (null != values && values.length > 0) ? values[0]
                    : null;
            if (null == parameterValue || !modelValue.equals(parameterValue)) {
              response.setRenderParameter(name, modelValue);
              valueChanged = true;
            }
          } else if (publicParameters.containsKey(name)) {
            response.removePublicRenderParameter(name);
            valueChanged = true;
          }
          return valueChanged;
        }

      };
      processPublicParameters(facesContext, request, parameterNames,
              outgoingFunction);

    }
  }

  private void processIncomingParameters(FacesContext facesContext,
          PortletRequest request) {
    Enumeration<String> parameterNames = getPortletConfig()
            .getPublicRenderParameterNames();
    if (null != publicParameterMapping && publicParameterMapping.size() > 0
            && parameterNames.hasMoreElements()) {
      ParameterFunction incomingFunction = new ParameterFunction(){
        public boolean processParameter(ELContext elContext,
                  Map<String, String[]> publicParameters, String name,
                  ValueExpression valueExpression) {
            boolean valueChanged = false;
            Object oldValue = valueExpression.getValue(elContext);
            if (publicParameters.containsKey(name)) {
              String[] values = publicParameters.get(name);
              String newValue = (null != values && values.length > 0) ? values[0]
                      : null;
              if (null == oldValue || !oldValue.equals(newValue)) {
                valueExpression.setValue(elContext, newValue);
                valueChanged = true;
              }
            } else if (null != oldValue) {
              valueExpression.setValue(elContext, null);
              valueChanged = true;
            }
            return valueChanged;
          }
   
      };
      boolean valueChanged = processPublicParameters(facesContext, request,
                    parameterNames,incomingFunction);
      if (valueChanged && null != publicParameterHandler) {
        publicParameterHandler.processUpdates(facesContext);
      }
    }
  }

  private boolean processPublicParameters(FacesContext facesContext,
            PortletRequest request, Enumeration<String> parameterNames, ParameterFunction function) {
      boolean valueChanged = false;
      ExpressionFactory expressionFactory = facesContext.getApplication()
              .getExpressionFactory();
      ELContext elContext = facesContext.getELContext();
      StringBuilder preffixedName = new StringBuilder(getPortletName())
              .append(':');
      int preffixLength = preffixedName.length();
      Map<String, String[]> publicParameters = request
              .getPublicParameterMap();
      // Iterate over configured paremeter names.
      while (parameterNames.hasMoreElements()) {
        // First, check for a common name mapping.
        String name = parameterNames.nextElement();
        // Lookup for parameter name in the mappings table.
        String mappingEl = publicParameterMapping.get(name);
        if (null == mappingEl) {
          // if no common mapping found, check for preffixed name.
          preffixedName.setLength(preffixLength);
          mappingEl = publicParameterMapping.get(preffixedName
                  .append(name).toString());
        }
        if (null != mappingEl) {
          // Found a mapping for the patameter, process it.
          ValueExpression valueExpression = expressionFactory
                  .createValueExpression(elContext, mappingEl,
                          Object.class);
          valueChanged = function.processParameter(elContext,
                        publicParameters, name, valueExpression)?true:valueChanged;
        }
      }
      return valueChanged;
    }


  public void processPortletParameters(ActionResponse response,
      StateId stateId, FacesContext facesContext, String redirectViewId,
      Map<String, String[]> newRequestParameters)
      throws MalformedURLException, PortletModeException {
    for (Entry<String, String[]> entry : newRequestParameters.entrySet()) {
      String key = entry.getKey();
      if (Bridge.PORTLET_MODE_PARAMETER.equals(key)) {
        String portletModeName = entry.getValue()[0];
        PortletMode mode = new PortletMode(portletModeName);
        PortalActionURL historyViewId = new PortalActionURL(
            redirectViewId);
        stateId.setMode(mode);
        historyViewId.setParameter(
            RequestScopeManager.STATE_ID_PARAMETER, stateId
                .toString());
        historyViewId.setParameter(Bridge.PORTLET_MODE_PARAMETER,
            portletModeName);
        facesContext.getExternalContext().getSessionMap().put(
            VIEWID_HISTORY_PREFIX + portletModeName,
            historyViewId.toString());
        response.setPortletMode(mode);
      } else if (Bridge.PORTLET_WINDOWSTATE_PARAMETER.equals(key)) {
        try {
          WindowState state = new WindowState(entry.getValue()[0]);
          response.setWindowState(state);
        } catch (WindowStateException e) {
          // only valid modes supported.
        }

      }
    }
  }

  private PortletBridgeContext createBridgeContext(PortletRequest request) {
    PortletBridgeContext bridgeContext = new PortletBridgeContext(this);
    request.setAttribute(PortletBridgeContext.REQUEST_PARAMETER_NAME,
        bridgeContext);
    bridgeContext.setInitialRequestAttributeNames(request
        .getAttributeNames());
    return bridgeContext;
  }

  public void doFacesRequest(RenderRequest request, RenderResponse response)
      throws BridgeException {
    assertParameters(request, response);

    if (log.isLoggable(Level.FINE)) {
      log.fine("Start bridge render request processing for portlet "
          + getPortletName());
    }
    // TODO - detect head rendering.
    Object renderPartAttribute = request.getAttribute(RenderRequest.RENDER_PART);
    RenderResponse wrappedResponse = strategy.createResponseWrapper(response);

    PortletBridgeContext bridgeContext = initRequest(request, wrappedResponse, Bridge.PortletPhase.RENDER_PHASE);
    RequestScopeManager requestStateManager = RequestScopeManager.getInstance(request,numberOfRequestScopes);
    String namespace = wrappedResponse.getNamespace();
    StateId stateId = requestStateManager.getStateId(request, response);
    bridgeContext.setStateId(stateId);
    BridgeRequestScope windowState = requestStateManager.getRequestScope(
        stateId);
    if (null == windowState) {
      windowState = new BridgeRequestScope();
      requestStateManager.saveRequestScope(stateId, windowState);
    }
    bridgeContext.setRequestScope(windowState);
    FacesContext facesContext = createFacesContext(request, wrappedResponse);
    try {
      windowState.restoreRequest(facesContext, true);
      // set portletbridge title if its set.
      ResourceBundle bundle = portletConfig.getResourceBundle(request
          .getLocale());
      if (bundle != null) {
        String title = null;
        try {
          title = bundle.getString("javax.portlet.title");
          wrappedResponse.setTitle(title);
        } catch (Exception e) {
          // Ignore MissingResourceException
        }
      }

      try {
        // If we're using RichFaces, setup proper parameters for this render
        // request
        strategy.beforeRenderRequest(facesContext);
        processIncomingParameters(facesContext, request);
        String redirectViewId = bridgeContext.getRedirectViewId();
        if (null == redirectViewId) {
          if (null == facesContext.getViewRoot()) {
            // Restore faces view ( Listener should stop processing
            // after restoreView phase ).
            execute(facesContext);
            // TODO - store changed parameters into url's.
            // processOutgoingParameters(facesContext);
          }
          if (!facesContext.getResponseComplete()) {
            render(facesContext);
          }
          redirectViewId = bridgeContext.getRedirectViewId();
        }
        // detect redirect case. Reset response, clear request
        // variables as far as Seam state.
        // Perform new render phase with a new ViewId.
        // TODO - move page navigation from Seam phase listener to the Strategy.
        if (null != redirectViewId) {
          windowState.reset();
          windowState.setViewId(redirectViewId);

          Map<String, String[]> redirectParams = bridgeContext
              .getRedirectRequestParameters();

          // release old FacesContext.
          facesContext.release();
          // Reset attributes to initial state
          bridgeContext.resetRequestAttributes(request);
          wrappedResponse.resetBuffer();
          if (redirectParams != null) {
            windowState.setRequestParameters(redirectParams);
          }

          // Create new FacesContext
          facesContext = createFacesContext(request, wrappedResponse);
          ViewHandler viewHandler = facesContext.getApplication()
              .getViewHandler();
          UIViewRoot viewRoot = viewHandler.createView(facesContext,
              redirectViewId);
          facesContext.setViewRoot(viewRoot);
          render(facesContext);
        }
        windowState.setViewId(facesContext.getViewRoot().getViewId());
      } catch (Exception e) {
        wrappedResponse.resetBuffer();
        log.log(Level.SEVERE, "Error processing execute lifecycle", e);
        exceptionHandler.processRenderException(facesContext,
            windowState, e);
        facesContext = FacesContext.getCurrentInstance();
      }
      // Set important Portal parameters to window state.
      String viewId = facesContext.getViewRoot().getViewId();
      //
      windowState.setNamespace(namespace);
      // TODO - encode request attributes, portlet mode and windowId, as
      // required by JSR-301 5.3.3
      String portletModeName = request.getPortletMode().toString();
      PortalActionURL historyViewId = new PortalActionURL(viewId);
      historyViewId.setParameter(RequestScopeManager.STATE_ID_PARAMETER,
          stateId.toString());
      historyViewId.setParameter(Bridge.PORTLET_MODE_PARAMETER,
          portletModeName);
      facesContext.getExternalContext().getSessionMap().put(
          VIEWID_HISTORY_PREFIX + portletModeName,
          historyViewId.toString());
      if (log.isLoggable(Level.FINE)) {
        log.fine("Finish rendering portletbridge for namespace "
            + namespace);
      }
      // Disable portletbridge caching.
      // TODO - detect ajax components on page, static views can be
      // cached.
      // wrappedResponse.setProperty(RenderResponse.EXPIRATION_CACHE,
      // "0");
    } catch (Exception e) {
      throwBridgeException(e);
    } finally {
      strategy.afterRenderRequest(facesContext, wrappedResponse);
      facesContext.release();
    }
  }


  protected void assertParameters(PortletRequest request,
      PortletResponse response) {
    if (null == request) {
      throw new NullPointerException("Request parameter is null");
    }
    if (null == response) {
      throw new NullPointerException("Response parameter is null");
    }
    if (!isInitialized()) {
      throw new BridgeException("JSF Portlet bridge is not initialized");
    }
  }

  public void doFacesRequest(ResourceRequest request,
          ResourceResponse response) throws BridgeException {
    assertParameters(request, response);

    if (log.isLoggable(Level.FINE)) {
      log.fine("Start bridge resource request processing for portlet "
              + getPortletName());
    }
    PortletBridgeContext bridgeContext = initRequest(request, response, Bridge.PortletPhase.RESOURCE_PHASE);
    if (!strategy.serveResource(request, response)) {
      if (null == request.getParameter(Bridge.FACES_VIEW_ID_PARAMETER)
              && null == request
                      .getParameter(Bridge.FACES_VIEW_PATH_PARAMETER)) {
        String target = request.getResourceID();
        if (null != target) {
        try {
            PortletContext portletContext = getPortletConfig()
                    .getPortletContext();
            PortletRequestDispatcher dispatcher = portletContext
                    .getRequestDispatcher(target);
            if (null != dispatcher) {
              String serverInfo = portletContext.getServerInfo();
              if (null != serverInfo
                             && (serverInfo
                              .startsWith("JBossPortletContainer")
                      || serverInfo
                              .startsWith("GateInPortletContainer"))) {
                // HACK - Jboss portal does not handle 'forward'
                // method during resource requests.
                // see
                // https://jira.jboss.org/jira/browse/JBPORTAL-2432
                String mimeType = portletContext
                        .getMimeType(target);
                if (null == mimeType) {
                  int lastIndexOfSlash = target
                          .lastIndexOf('/');
                  if (lastIndexOfSlash >= 0) {
                    target = target
                            .substring(lastIndexOfSlash + 1);
                  }
                  int indexOfQuestion = target.indexOf('?');
                  if (indexOfQuestion >= 0) {
                    target = target.substring(0,
                            indexOfQuestion);
                  }
                  mimeType = portletContext
                          .getMimeType(target);
                }
                if (null != mimeType) {
                  response.setContentType(mimeType);
                }
                dispatcher.include(request, response);
              } else {
                dispatcher.forward(request, response);
              }
            }
        } catch (Exception e) {
          throwBridgeException(e);
        }
        } else {
          throw new BridgeException("Unable to serve resource");
        }

      } else {
        // FACES REQUEST.
        ResourceResponse wrappedResponse = strategy
                .createResponseWrapper(response);
        RequestScopeManager requestStateManager = RequestScopeManager
                .getInstance(request, numberOfRequestScopes);
        FacesContext facesContext = createFacesContext(request,
                wrappedResponse);
        StateId stateId = requestStateManager.getStateId(request,
                wrappedResponse);
        bridgeContext.setStateId(stateId);
        BridgeRequestScope windowState = requestStateManager
                .getRequestScope(stateId);
        if (null == windowState) {
          windowState = new BridgeRequestScope();
          requestStateManager.saveRequestScope(stateId, windowState);
        } else {
          windowState.reset();
        }
        bridgeContext.setRequestScope(windowState);
        try {
          strategy.beforeResourceRequest(facesContext);
          processIncomingParameters(facesContext, request);
          execute(facesContext);
          // TODO - create applicable processing function.
//          processOutgoingParameters(facesContext,request,response);
          strategy.afterResourceRequestExecute(facesContext);
          windowState.saveRequest(facesContext, false);
          if (!facesContext.getResponseComplete()) {
            render(facesContext);
          }
        } catch (Exception e) {
          wrappedResponse.resetBuffer();
          log.log(Level.SEVERE, "Error processing execute lifecycle", e);
          exceptionHandler.processResourceException(facesContext,
              windowState, e);
          facesContext = FacesContext.getCurrentInstance();
        } finally {
          strategy.afterResourceRequest(facesContext, wrappedResponse);
          facesContext.release();
        }
      }
    }
  }

  private void throwBridgeException(Exception e) throws BridgeException {
    if (!(e instanceof BridgeException)) {
      e = new BridgeException(e);
    }
    throw (BridgeException) e;
  }

   public void doFacesRequest(EventRequest request, EventResponse response)
      throws BridgeException
   {
      //ensure non null request/response and bridge is initialized
      assertParameters(request, response);

      if (log.isLoggable(Level.FINE))
      {
         log.fine("Start bridge event request processing for portlet "
            + getPortletName());
      }
      //init bridge context and set PORTLET_LIFECYCLE_PHASE to current portlet phase
      PortletBridgeContext bridgeContext = initRequest(request,
                                                       response,
                                                       Bridge.PortletPhase.EVENT_PHASE);

      //get RequestScopeManager which holds STATE_ID parameter and adds
      // REQUEST_STATE_MANAGER to PortletSession
      RequestScopeManager requestStateManager =
         RequestScopeManager.getInstance(request, numberOfRequestScopes);

      //get the stateId for this event request, simple init with stateId and randomUUID
      StateId stateId = requestStateManager.getStateId(request, response);

      //store in bridge context
      bridgeContext.setStateId(stateId);

      //get the current RequestScope from the stateId otherwise get it form states map
      BridgeRequestScope windowState = requestStateManager.getRequestScope(stateId);

      //check for failure of pulling it from the RequestScopeManager's map of "states"
      if (null == windowState)
      {
         windowState = new BridgeRequestScope();
      }
      else
      {
         windowState.reset();
      }
      //create the facesContext using facesContextFactory
      FacesContext facesContext = createFacesContext(request, response);

      try
      {
         // If strategy enlists Seam, Propagate current render parameters.
         //call FacesLifecycle.beginRequest from seamPhaseListenerWrapper
         //  which will setup up all the contexts, except conversation is null
         strategy.beforeEventRequest(facesContext);

         //portlet sets render params
         response.setRenderParameters(request);

         //helper method for setting incoming params as EL variables
         processIncomingParameters(facesContext, request);

         //execute phases from LifecyclePhase - for actions only
         execute(facesContext);

         //check for null event handler
         if (null == eventHandler)
         {
            log.severe("The EventHandler is null for " + getPortletName() + ". Ensure " +
               "your portlet.xml settings are correct and that you have implemented the " +
               "BridgeEventHandler in your application.");
         }
         //get the event from the request
         Event event = request.getEvent();

         //Handle the event and get the result
         EventNavigationResult result = eventHandler.handleEvent(facesContext, event);

         if (result != null)
         {
            facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext,
                                                                                  result.getFromAction(),
                                                                                  result.getOutcome());
            // the navigation rule might indicate a redirect
            if (facesContext.getResponseComplete())
            {
               return;
            }
         }

         //now place view root in request scope.
         windowState.setViewRoot(facesContext.getViewRoot());

         //set the request scope of this event (aka windowState)
         bridgeContext.setRequestScope(windowState);
        
         //helper for removal and addition of PRPs
         processOutgoingParameters(facesContext, request, response);

         //update stateId in RequestScopeManager and put it on session as REQUEST_STATE_MANAGER
         requestStateManager.saveRequestScope(stateId, windowState);

         //add the STATE_ID_PARAMETER so we can fish the ID out in the render request
         response.setRenderParameter(RequestScopeManager.STATE_ID_PARAMETER, stateId.toString());
      }
      catch (Exception e)
      {
         log.log(Level.SEVERE, "Error processing event request", e);
         exceptionHandler.processEventException(facesContext, windowState, e);
      }
      finally
      {
         //If Seam, we set conversationIds and ends Faces request from SeamPhaseListenerWrapper
         strategy.afterEventRequest(facesContext);
         facesContext.release();
      }

   }


  /**
   * @param facesContext
   * @param windowState
   * @throws FacesException
   */
  private void renderResponse(FacesContext facesContext,
      BridgeRequestScope windowState) throws FacesException {
    if (null == facesContext.getViewRoot()) {
      execute(facesContext);
      // TODO - store changed parameters into url's.
//      processOutgoingParameters(facesContext);
    }
    //
    if (!facesContext.getResponseComplete()) {
      render(facesContext);
    }
  }

  /**
   * @param request
   * @param response
   * @param currentPhase
   * @return initialized bridge context instance.
   * @throws BridgeException
   */
  protected PortletBridgeContext initRequest(PortletRequest request,
      PortletResponse response, PortletPhase currentPhase)
      throws BridgeException {
    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, currentPhase);
    // Check viewId history sessions attributes
    Map<String, String> viewIdMap = getDefaultViewIdMap();
    String firstMode = viewIdMap.keySet().iterator().next();
    PortletSession portletSession = request.getPortletSession();
    if (null == portletSession.getAttribute(VIEWID_HISTORY_PREFIX
        + firstMode)) {
      // Fill viewId's history attributes by default values.
      for (Entry<String, String> entry : viewIdMap.entrySet()) {
        portletSession.setAttribute(VIEWID_HISTORY_PREFIX
            + entry.getKey(), encodeModeParam(entry.getKey(), entry
            .getValue()));
      }
    }
    return createBridgeContext(request);
  }

  protected void finishRequest(PortletRequest request,
      PortletResponse response) throws BridgeException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if(null != facesContext){
      facesContext.release();
    }
    request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
    request.removeAttribute(PortletBridgeContext.REQUEST_PARAMETER_NAME);
  }
  /**
   * Encode mode parameter into viewId.
   *
   * @param mode
   * @param viewId
   * @return
   */
  private String encodeModeParam(String mode, String viewId) {
    try {
      PortalActionURL viewIdUrl = new PortalActionURL(viewId);
      viewIdUrl.addParameter(Bridge.PORTLET_MODE_PARAMETER, mode);
      return viewIdUrl.toString();
    } catch (MalformedURLException e) {
      throw new BridgeException("Malformed ViewId", e);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#getPortletConfig()
   */
  public PortletConfig getPortletConfig() {
    return portletConfig;
  }

  protected Object getContext() {
    return portletConfig.getPortletContext();
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org.jboss.portletbridge.BridgeConfig#getInitParameter(java.lang.String)
   */
  public String getInitParameter(String name) {
    String initParameter = portletConfig.getInitParameter(name);
    if (null == initParameter) {
      initParameter = portletConfig.getPortletContext().getInitParameter(
          name);
    }
    return initParameter;
  }

  /**
   * @return the initialized
   */
  protected boolean isInitialized() {
    return initialized;
  }

  /**
   * @return the exceptionHandler
   */
  protected ExceptionHandler getExceptionHandler() {
    return exceptionHandler;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#getFacesServletMappings()
   */
  public List<String> getFacesServletMappings() {
    return facesServletMappings;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#getExcludedAttributes()
   */
  public Set<ExcludedRequestAttribute> getExcludedAttributes() {
    return excludedAttributes;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#getPortletName()
   */
  public String getPortletName() {
    return portletConfig.getPortletName();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#isPreserveActionParams()
   */
  public boolean isPreserveActionParams() {
    return preserveActionParams;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jboss.portletbridge.BridgeConfig#getDefaultViewIdMap()
   */
  public Map<String, String> getDefaultViewIdMap() {
    return defaultViewIdMap;
  }

  /**
   * @return the numberOfRequestScopes
   */
  public int getNumberOfRequestScopes() {
    return numberOfRequestScopes;
  }

  public void contextCreated(ELContextEvent event) {
    // Add the portletConfig to the ELContext
    ELContext elContext = event.getELContext();
    if (elContext.getContext(PortletConfig.class) == null) {
      elContext.putContext(PortletConfig.class, portletConfig);
    }
  }

  /**
   * Get currenf JSF lifecycle instance.
   *
   * @return
   */
  public Lifecycle getFacesLifecycle() {
    return this.lifecycle;
  }

  /**
   * Create new faces context instance.
   *
   * @param request
   * @param response
   * @return new instance of faces context.
   */
    public FacesContext createFacesContext(Object request, Object response) {
    FacesContext facesContext = this.facesContextFactory.getFacesContext(
        getContext(), request, response, getFacesLifecycle());
    return facesContext;
  }

  protected void execute(FacesContext context) throws FacesException {
    getFacesLifecycle().execute(context);
  }

  protected void render(FacesContext context) throws FacesException {
    getFacesLifecycle().render(context);
  }

  /**
   * @return the errorPages
   */
  public Map<Class<? extends Throwable>, String> getErrorPages() {
    return errorPages;
  }

  /**
     * @return the strategy
     */
    public BridgeStrategy getStrategy() {
      return strategy;
    }
   
    public Map<String, String> getFilterInitParams(String filterClassName) {
        if(this.filterInitParams != null) {
            return this.filterInitParams.get(filterClassName);
        }
        return new HashMap<String, String>();
    }
}
TOP

Related Classes of org.jboss.portletbridge.AjaxPortletBridge$ParameterFunction

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.