Package com.liferay.faces.bridge.container.liferay

Source Code of com.liferay.faces.bridge.container.liferay.LiferayURLGeneratorBaseImpl

/**
* Copyright (c) 2000-2014 Liferay, Inc. All rights reserved.
*
* 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 (at your option)
* 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.
*/
package com.liferay.faces.bridge.container.liferay;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.context.FacesContext;
import javax.faces.render.RenderKit;
import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.WindowState;

import com.liferay.faces.bridge.BridgeConstants;
import com.liferay.faces.bridge.util.URLParameter;
import com.liferay.faces.util.lang.StringPool;
import com.liferay.faces.util.logging.Logger;
import com.liferay.faces.util.logging.LoggerFactory;
import com.liferay.faces.util.product.ProductConstants;
import com.liferay.faces.util.product.ProductMap;

import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.Portlet;
import com.liferay.portal.service.PortletLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.Portal;


/**
* <p>This abstract class implements the {@link LiferayURLGenerator} contract for generating URLs that are compatible
* with Liferay Portal. The main reason why this is necessary is because the Liferay Portal {@link
* PortletURLImpl#toString()} method returns different values depending on the portlet lifecycle phase during which it
* is called. Additionally, it sometimes includes the public render parameters in the URL (which are not required for
* JSF portlets). Another issue is related to ICEfaces, which uses a server-side DOM-diff algorithm within it's {@link
* RenderKit}. When DOM-diff strategies are used, it is critical that URLs always be the same regardless of which
* portlet lifecycle phase is executing. For example, a URL generated during the {@link PortletRequest#RENDER_PHASE} of
* the portlet lifecycle must be identical to the one generated during the {@link PortletRequest#RESOURCE_PHASE}, or
* else a DOM-diff will be detected.</p>
*
* <p>The constructors of this class receive a String-based parameter named "baseURL" which is expected to be the result
* of calling the toString() method of a Liferay URL. The baseURL is then parsed and the URL parameters are cached so
* that the {@link #generateURL(Map)} method can quickly generate a consistent URL.</p>
*
* @author  Neil Griffin
*/
public abstract class LiferayURLGeneratorBaseImpl implements LiferayURLGenerator {

  // Logger
  private static final Logger logger = LoggerFactory.getLogger(LiferayURLGeneratorBaseImpl.class);

  // Private Constants
  private static final int LIFERAY_BUILD_NUMBER = ProductMap.getInstance().get(ProductConstants.LIFERAY_PORTAL)
    .getBuildId();

  // Private Data Members
  private String baseURL;
  private Map<String, String> parameterMap;
  private PortletMode initialPortletMode;
  private String prefix;
  private String responseNamespace;
  private WindowState initialWindowState;
  private List<URLParameter> wsrpParameters;
  private String portletURLAnchor;

  /**
   * Constructs a new instance.
   *
   * @param  baseURL            The String-based URL generated by Liferay Portal's PortletURLImpl#toString() method.
   * @param  responseNamespace  The response namespace.
   */
  public LiferayURLGeneratorBaseImpl(String baseURL, String responseNamespace) {
    this(baseURL, null, responseNamespace, null);
  }

  /**
   * Constructs a new instance.
   *
   * @param  baseURL            The String-based URL generated by Liferay Portal's {@link PortletURLImpl#toString()}
   *                            method.
   * @param  portletMode        The portlet mode specified by Liferay Portal's {@link PortletURLImpl#getPortletMode()}
   *                            method.
   * @param  responseNamespace  The response namespace.
   * @param  windowState        The window state specified by Liferay Portal's {@link PortletURLImpl#getWindowState()}
   *                            method.
   */
  public LiferayURLGeneratorBaseImpl(String baseURL, PortletMode portletMode, String responseNamespace,
    WindowState windowState) {

    this.baseURL = baseURL;
    this.initialPortletMode = portletMode;
    this.responseNamespace = responseNamespace;
    this.initialWindowState = windowState;
    parse();
  }

  public String generateURL(Map<String, String[]> additionalParameterMap) {
    return generateURL(additionalParameterMap, null, null);
  }

  public String generateURL(Map<String, String[]> additionalParameterMap, String resourceId) {
    return generateURL(additionalParameterMap, null, resourceId, null);
  }

  public String generateURL(Map<String, String[]> additionalParameterMap, PortletMode portletMode,
    WindowState windowState) {
    return generateURL(additionalParameterMap, portletMode, null, windowState);
  }

  public String generateURL(Map<String, String[]> additionalParameterMap, PortletMode portletMode, String resourceId,
    WindowState windowState) {

    String toStringValue = null;

    if (baseURL.contains(Portal.FRIENDLY_URL_SEPARATOR)) {
      toStringValue = baseURL;
    }
    else {

      StringBuilder url = new StringBuilder();

      // Build up a new URL string based on the one returned by Liferay, but discard everything after the
      // question mark because it's filled with all kinds of unnecessary stuff.
      url.append(prefix);

      // Possibly add the p_auth parameter.
      boolean firstParameter = true;
      String portalAuthToken = parameterMap.get(LiferayConstants.P_AUTH);

      if (portalAuthToken != null) {

        appendParameterToURL(firstParameter, LiferayConstants.P_AUTH, portalAuthToken, url);
        firstParameter = false;
      }

      // Possibly add the p_l_id parameter.
      String plid = parameterMap.get(LiferayConstants.P_L_ID);

      if (plid != null) {

        appendParameterToURL(firstParameter, LiferayConstants.P_L_ID, plid, url);
        firstParameter = false;
      }

      // Possibly add the p_p_auth parameter.
      String portletAuthToken = parameterMap.get(LiferayConstants.P_P_AUTH);

      if (portletAuthToken != null) {

        boolean addPortletAuthToken = true;

        if ((LIFERAY_BUILD_NUMBER < 6102) || ((LIFERAY_BUILD_NUMBER > 6102) && (LIFERAY_BUILD_NUMBER < 6130))) {

          // Versions of Liferay Portal prior to 6.1.2-CE/6.1.30-EE suffered from LPS-36481 which caused
          // PortletURLImpl.addPortletAuthToken(StringBundle, Key) method to add the p_p_auth parameter to
          // URLs for portlets when add-default-resource=false. It is therefore necessary to check that
          // add-default-resource=true before adding the p_p_auth parameter to the URL.
          FacesContext facesContext = FacesContext.getCurrentInstance();
          PortletRequest portletRequest = (PortletRequest) facesContext.getExternalContext().getRequest();
          String portletId = (String) portletRequest.getAttribute(WebKeys.PORTLET_ID);
          ThemeDisplay themeDisplay = (ThemeDisplay) portletRequest.getAttribute(WebKeys.THEME_DISPLAY);

          try {
            Portlet portlet = PortletLocalServiceUtil.getPortletById(themeDisplay.getCompanyId(),
                portletId);
            addPortletAuthToken = portlet.isAddDefaultResource();
          }
          catch (SystemException e) {
            logger.error(e);
          }
        }

        if (addPortletAuthToken) {
          appendParameterToURL(firstParameter, LiferayConstants.P_P_AUTH, portletAuthToken, url);
          firstParameter = false;
        }
      }

      // Always add the p_p_id parameter
      String parameterValue = responseNamespace;

      if (parameterValue.startsWith(StringPool.UNDERLINE)) {
        parameterValue = parameterValue.substring(1);
      }

      if (parameterValue.endsWith(StringPool.UNDERLINE)) {
        parameterValue = parameterValue.substring(0, parameterValue.length() - 1);
      }

      appendParameterToURL(firstParameter, LiferayConstants.P_P_ID, parameterValue, url);

      firstParameter = false;

      // Always add the p_p_lifecycle parameter.
      String portletLifecycleId = getPortletLifecycleId();
      appendParameterToURL(LiferayConstants.P_P_LIFECYCLE, portletLifecycleId, url);

      // Add the p_p_state parameter.
      FacesContext facesContext = FacesContext.getCurrentInstance();
      Map<String, Object> applicationMap = facesContext.getExternalContext().getApplicationMap();

      WindowState urlWindowState = initialWindowState;

      if (windowState != null) {
        urlWindowState = windowState;
      }

      if (urlWindowState == null) {
        parameterValue = (String) applicationMap.get(responseNamespace + LiferayConstants.P_P_STATE);
      }
      else {
        parameterValue = urlWindowState.toString();
      }

      appendParameterToURL(LiferayConstants.P_P_STATE, parameterValue, url);

      // Possibly add the p_p_state_rcv parameter.
      String stateRestoreCurrentView = parameterMap.get(LiferayConstants.P_P_STATE_RCV);

      if (stateRestoreCurrentView != null) {
        appendParameterToURL(LiferayConstants.P_P_STATE_RCV, stateRestoreCurrentView, url);
      }

      // Add the p_p_mode parameter.
      PortletMode urlPortletMode = initialPortletMode;

      if (portletMode != null) {
        urlPortletMode = portletMode;
      }

      if (urlPortletMode == null) {
        parameterValue = (String) applicationMap.get(responseNamespace + LiferayConstants.P_P_MODE);
      }
      else {
        parameterValue = urlPortletMode.toString();
      }

      appendParameterToURL(LiferayConstants.P_P_MODE, parameterValue, url);

      // Possibly add the p_p_cacheability parameter
      if (LiferayConstants.LIFECYCLE_RESOURCE_PHASE_ID.equals(portletLifecycleId)) {
        String cacheability = parameterMap.get(LiferayConstants.P_P_CACHEABILITY);

        if (cacheability != null) {
          appendParameterToURL(LiferayConstants.P_P_CACHEABILITY, cacheability, url);
        }
      }

      // Always add the p_p_col_id parameter
      parameterValue = (String) applicationMap.get(responseNamespace + LiferayConstants.P_P_COL_ID);
      appendParameterToURL(LiferayConstants.P_P_COL_ID, parameterValue, url);

      // Possibly add the p_p_col_count parameter.
      parameterValue = (String) applicationMap.get(responseNamespace + LiferayConstants.P_P_COL_COUNT);
      appendParameterToURL(LiferayConstants.P_P_COL_COUNT, parameterValue, url);

      // Add the p_p_col_pos parameter if it is greater than zero (same logic as Liferay's
      // PortletURLImpl.toString())
      parameterValue = (String) applicationMap.get(responseNamespace + LiferayConstants.P_P_COL_POS);

      if ((parameterValue != null) && (parameterValue.length() > 0)) {

        try {
          int colPos = Integer.parseInt(parameterValue);

          if (colPos > 0) {
            appendParameterToURL(LiferayConstants.P_P_COL_POS, parameterValue, url);
          }
        }
        catch (NumberFormatException e) {
          // ignore
        }
      }

      // Possibly add the p_o_p_id parameter.
      String outerPortletId = parameterMap.get(LiferayConstants.P_O_P_ID);

      if (outerPortletId != null) {
        appendParameterToURL(LiferayConstants.P_O_P_ID, outerPortletId, url);
      }

      // Possibly add the doAsUserId parameter.
      String doAsUserId = parameterMap.get(LiferayConstants.DO_AS_USER_ID);

      if (doAsUserId != null) {
        appendParameterToURL(LiferayConstants.DO_AS_USER_ID, doAsUserId, url);
      }

      // Possibly add the doAsUserLanguageId parameter.
      String doAsUserLanguageId = parameterMap.get(LiferayConstants.DO_AS_USER_LANGUAGE_ID);

      if (doAsUserLanguageId != null) {
        appendParameterToURL(LiferayConstants.DO_AS_USER_LANGUAGE_ID, doAsUserLanguageId, url);
      }

      // Possibly add the doAsGroupId parameter.
      String doAsGroupId = parameterMap.get(LiferayConstants.DO_AS_GROUP_ID);

      if (doAsGroupId != null) {
        appendParameterToURL(LiferayConstants.DO_AS_GROUP_ID, doAsGroupId, url);
      }

      // Possibly add the refererGroupId parameter.
      String refererGroupId = parameterMap.get(LiferayConstants.REFERER_GROUP_ID);

      if (refererGroupId != null) {
        appendParameterToURL(LiferayConstants.REFERER_GROUP_ID, refererGroupId, url);
      }

      // Possibly add the refererPlid parameter.
      String refererPlid = parameterMap.get(LiferayConstants.REFERER_PLID);

      if (refererPlid != null) {
        appendParameterToURL(LiferayConstants.REFERER_PLID, refererPlid, url);
      }

      // Possibly add the controlPanelCategory parameter.
      String controlPanelCategory = parameterMap.get(LiferayConstants.CONTROL_PANEL_CATEGORY);

      if (controlPanelCategory != null) {
        appendParameterToURL(LiferayConstants.CONTROL_PANEL_CATEGORY, controlPanelCategory, url);
      }

      // Add request parameters from the request parameter map.
      boolean namespaced = !responseNamespace.startsWith(BridgeConstants.WSRP);

      Set<Map.Entry<String, String[]>> mapEntries = additionalParameterMap.entrySet();

      if (mapEntries != null) {

        for (Map.Entry<String, String[]> mapEntry : mapEntries) {
          String[] parameterValues = mapEntry.getValue();

          if (parameterValues != null) {

            String parameterName = mapEntry.getKey();

            for (String curParameterValue : parameterValues) {

              if (curParameterValue != null) {

                String encodedParameterValue = encode(curParameterValue);
                appendParameterToURL(firstParameter, namespaced, parameterName, encodedParameterValue,
                  url);
              }
            }
          }
        }
      }

      // Add WSRP URL parameters
      for (URLParameter wsrpParameter : wsrpParameters) {

        appendParameterToURL(wsrpParameter.getName(), wsrpParameter.getValue(), url);
      }

      // Possibly add the p_p_resource_id parameter.
      String urlResourceId = parameterMap.get(LiferayConstants.P_O_P_ID);

      if (resourceId != null) {
        urlResourceId = resourceId;
      }

      if (urlResourceId == null) {

        if (prefix.startsWith(BridgeConstants.WSRP)) {
          appendParameterToURL(LiferayConstants.P_P_RESOURCE_ID, BridgeConstants.WSRP, url);
        }
      }
      else {
        appendParameterToURL(LiferayConstants.P_P_RESOURCE_ID, urlResourceId, url);
      }

      // Possibly add a Portlet URL Anchor
      if (portletURLAnchor != null) {
        url.append(portletURLAnchor);
      }

      toStringValue = url.toString();
    }

    return toStringValue;
  }

  protected void appendParameterToURL(String parameterName, String parameterValue, StringBuilder url) {
    appendParameterToURL(false, false, parameterName, parameterValue, url);
  }

  protected void appendParameterToURL(boolean firstParameter, String parameterName, String parameterValue,
    StringBuilder url) {
    appendParameterToURL(firstParameter, false, parameterName, parameterValue, url);
  }

  protected void appendParameterToURL(boolean firstParameter, boolean namespaced, String parameterName,
    String parameterValue, StringBuilder url) {

    if (!firstParameter) {
      url.append(StringPool.AMPERSAND);
    }

    if (namespaced) {
      url.append(responseNamespace);
    }

    url.append(parameterName);
    url.append(StringPool.EQUAL);
    url.append(parameterValue);

    logger.debug("Appended param to URL name=[{0}] parameterValue=[{1}]", parameterName, parameterValue);
  }

  protected String encode(String value) {

    String encodedValue = StringPool.BLANK;

    if (value != null) {

      if (value.length() == 0) {
        encodedValue = StringPool.SPACE;
      }
      else {

        try {
          encodedValue = URLEncoder.encode(value, StringPool.UTF8);
        }
        catch (UnsupportedEncodingException e) {
          logger.error(e);
          encodedValue = StringPool.SPACE;
        }
      }
    }

    return encodedValue;
  }

  protected void parse() {

    parameterMap = new HashMap<String, String>();
    wsrpParameters = new ArrayList<URLParameter>();

    String queryString = baseURL;
    int queryPos = baseURL.indexOf(StringPool.QUESTION);

    if (queryPos > 0) {
      prefix = baseURL.substring(0, queryPos + 1);
      queryString = baseURL.substring(queryPos + 1);
    }

    String[] nameValuePairs = queryString.split(BridgeConstants.REGEX_AMPERSAND_DELIMITER);

    if (nameValuePairs != null) {

      for (String nameValuePair : nameValuePairs) {

        int equalsPos = nameValuePair.indexOf(StringPool.EQUAL);

        if (equalsPos > 0) {

          String name = nameValuePair.substring(0, equalsPos);
          String value = nameValuePair.substring(equalsPos + 1);

          if (nameValuePair.startsWith(BridgeConstants.WSRP)) {
            URLParameter urlParameter = new URLParameter(name, value);
            wsrpParameters.add(urlParameter);
          }
          else {
            parameterMap.put(name, value);
          }
        }
      }
    }

    int pos = baseURL.indexOf(StringPool.POUND);

    if (pos > 0) {
      portletURLAnchor = baseURL.substring(pos);
    }

  }
}
TOP

Related Classes of com.liferay.faces.bridge.container.liferay.LiferayURLGeneratorBaseImpl

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.