protected IPortletWindow wrapPortletWindowData(
      HttpServletRequest request, PortletWindowData portletWindowData) {
    final IPortletEntityId portletEntityId = portletWindowData.getPortletEntityId();
    final IPortletEntity portletEntity =
        this.portletEntityRegistry.getPortletEntity(request, portletEntityId);
    if (portletEntity == null) {
      return null;
    }

    final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition();
    final PortletDefinition portletDescriptor =
        this.portletDefinitionRegistry.getParentPortletDescriptor(
            portletDefinition.getPortletDefinitionId());
    if (portletDescriptor == null) {
      return null;
    }

    final IPortletWindow portletWindow =
        new PortletWindowImpl(portletDescriptor, portletEntity, portletWindowData);

    logger.trace(
        "Wrapping PortletWindowData {} as IPortletWindow", portletWindow.getPortletWindowId());

    return portletWindow;
  }
  @Override
  public IPortletWindow createDelegatePortletWindow(
      HttpServletRequest request,
      IPortletEntityId portletEntityId,
      IPortletWindowId delegationParentId) {
    Validate.notNull(request, "request can not be null");
    Validate.notNull(portletEntityId, "portletEntityId can not be null");

    // TODO does a delegate portlet entity need some sort of special treatment or do we just assume
    // that the calling code is using one?

    final IPortletWindowId portletWindowId =
        this.getDefaultPortletWindowId(request, portletEntityId);

    final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);

    // Check if there is portlet window cached in the request
    IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
    if (portletWindow != null) {
      logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
      return portletWindow;
    }

    final PortletWindowData portletWindowData =
        this.getOrCreateDefaultPortletWindowData(
            request, portletEntityId, portletWindowId, delegationParentId);
    portletWindow = wrapPortletWindowData(request, portletWindowData);
    if (portletWindow == null) {
      return null;
    }

    // Cache the wrapped window in the request
    return portletWindowMap.storeIfAbsentWindow(portletWindow);
  }
  @Override
  public IPortletWindow getOrCreateDefaultPortletWindow(
      HttpServletRequest request, IPortletEntityId portletEntityId) {
    Validate.notNull(request, "request can not be null");
    Validate.notNull(portletEntityId, "portletEntityId can not be null");

    final IPortletWindowId portletWindowId =
        this.getDefaultPortletWindowId(request, portletEntityId);

    final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);

    // Check if there is portlet window cached in the request
    IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
    if (portletWindow != null) {
      logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
      return portletWindow;
    }

    final PortletWindowData portletWindowData =
        this.getOrCreateDefaultPortletWindowData(request, portletEntityId, portletWindowId);
    portletWindow = wrapPortletWindowData(request, portletWindowData);
    if (portletWindow == null) {
      return null;
    }

    // Cache the wrapped window in the request
    return portletWindowMap.storeIfAbsentWindow(portletWindow);
  }
 protected String getPortletFname(HttpServletRequest request, IPortletWindowId portletWindowId) {
   final IPortletWindow portletWindow =
       this.portletWindowRegistry.getPortletWindow(request, portletWindowId);
   final IPortletEntity portletEntity = portletWindow.getPortletEntity();
   final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition();
   return portletDefinition.getFName();
 }
 protected IPortletWindowId getErrorPortletWindowId(HttpServletRequest request, String fname) {
   final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
   final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
   final IUserLayoutManager userLayoutManager = preferencesManager.getUserLayoutManager();
   final String errorPortletSubscribeId = userLayoutManager.getSubscribeId(fname);
   final IPortletEntity errorPortletEntity =
       this.portletEntityRegistry.getOrCreatePortletEntity(
           request, userInstance, errorPortletSubscribeId);
   final IPortletWindow portletWindow =
       this.portletWindowRegistry.getOrCreateDefaultPortletWindow(
           request, errorPortletEntity.getPortletEntityId());
   return portletWindow.getPortletWindowId();
 }
  /* (non-Javadoc)
   * @see org.jasig.portal.portlet.container.properties.BaseRequestPropertiesManager#getRequestProperties(javax.servlet.http.HttpServletRequest, org.jasig.portal.portlet.om.IPortletWindow)
   */
  @Override
  public Map<String, String[]> getRequestProperties(
      HttpServletRequest portletRequest, IPortletWindow portletWindow) {
    if (this.propertyToAttributeMappings.isEmpty() && this.nonNamespacedProperties.isEmpty()) {
      return Collections.emptyMap();
    }

    final HttpServletRequest portalRequest =
        this.portalRequestUtils.getOriginalPortalRequest(portletRequest);
    final String windowIdStr = portletWindow.getPortletWindowId().getStringId();

    final Builder<String, String[]> properties = ImmutableMap.builder();
    for (final Enumeration<String> attributeNames = portalRequest.getAttributeNames();
        attributeNames.hasMoreElements(); ) {
      final String fullAttributeName = attributeNames.nextElement();
      final String propertyName = getPropertyName(windowIdStr, fullAttributeName);
      if (propertyName == null) {
        continue;
      }

      logger.debug(
          "Found portal request attribute {} returning as property {}",
          fullAttributeName,
          propertyName);

      final Object value = portalRequest.getAttribute(fullAttributeName);
      final String[] values = convertValue(value);

      properties.put(propertyName, values);
    }

    return properties.build();
  }
  /* (non-Javadoc)
   * @see org.jasig.portal.portlet.registry.IPortletWindowRegistry#getPortletWindow(javax.servlet.http.HttpServletRequest, org.jasig.portal.portlet.om.IPortletWindowId)
   */
  @Override
  public IPortletWindow getPortletWindow(
      HttpServletRequest request, IPortletWindowId portletWindowId) {
    Validate.notNull(request, "request can not be null");
    Validate.notNull(portletWindowId, "portletWindowId can not be null");

    final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);

    IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
    if (portletWindow != null) {
      logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
      return portletWindow;
    }

    final PortletWindowIdImpl localPortletWindowId =
        this.convertPortletWindowId(request, portletWindowId);

    // Find the window data from the correct window data map
    final PortletWindowData portletWindowData;
    if (STATELESS_PORTLET_WINDOW_ID.equals(localPortletWindowId.getWindowInstanceId())) {
      final PortletWindowCache<PortletWindowData> statelessPortletWindowDataMap =
          this.getStatelessPortletWindowDataMap(request, false);
      if (statelessPortletWindowDataMap != null) {
        portletWindowData = statelessPortletWindowDataMap.getWindow(portletWindowId);
      } else {
        portletWindowData = null;
      }
    } else {
      portletWindowData = this.getPortletWindowData(request, portletWindowId);
    }

    if (portletWindowData == null) {
      logger.trace("No IPortletWindow {} exists, returning null");
      return null;
    }

    portletWindow = this.wrapPortletWindowData(request, portletWindowData);

    // Cache the wrapped window in the request
    return portletWindowMap.storeIfAbsentWindow(portletWindow);
  }
  @Override
  public void storePortletWindow(HttpServletRequest request, IPortletWindow portletWindow) {
    if (isDisablePersistentWindowStates(request)) {
      return;
    }

    final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
    final IPerson person = userInstance.getPerson();
    if (person.isGuest()) {
      // Never persist things for the guest user, just rely on in-memory storage
      return;
    }

    final IStylesheetDescriptor themeStylesheetDescriptor =
        this.getThemeStylesheetDescriptor(request);

    final WindowState windowState = portletWindow.getWindowState();

    final IPortletEntity portletEntity = portletWindow.getPortletEntity();
    final WindowState entityWindowState = portletEntity.getWindowState(themeStylesheetDescriptor);

    // If the window and entity states are different
    if (windowState != entityWindowState && !windowState.equals(entityWindowState)) {
      final WindowState defaultWindowState = this.getDefaultWindowState(themeStylesheetDescriptor);

      // If a window state is set and is one of the persistent states set it on the entity
      if (!defaultWindowState.equals(windowState) && persistentWindowStates.contains(windowState)) {
        portletEntity.setWindowState(themeStylesheetDescriptor, windowState);
      }
      // If not remove the state from the entity
      else if (entityWindowState != null) {
        portletEntity.setWindowState(themeStylesheetDescriptor, null);
      }

      // Persist the modified entity
      this.portletEntityRegistry.storePortletEntity(request, portletEntity);
    }
  }
  @Override
  public Tuple<IPortletWindow, StartElement> getPortletWindow(
      HttpServletRequest request, StartElement element) {
    // Check if the layout node explicitly specifies the window id
    final Attribute windowIdAttribute = element.getAttributeByName(PORTLET_WINDOW_ID_ATTR_NAME);
    if (windowIdAttribute != null) {
      final String windowIdStr = windowIdAttribute.getValue();
      final IPortletWindowId portletWindowId = this.getPortletWindowId(request, windowIdStr);
      final IPortletWindow portletWindow = this.getPortletWindow(request, portletWindowId);
      return new Tuple<IPortletWindow, StartElement>(portletWindow, element);
    }

    // No explicit window id, look it up based on the layout node id
    final Attribute nodeIdAttribute = element.getAttributeByName(IUserLayoutManager.ID_ATTR_NAME);
    final String layoutNodeId = nodeIdAttribute.getValue();

    IPortletWindow portletWindow =
        this.getOrCreateDefaultPortletWindowByLayoutNodeId(request, layoutNodeId);
    if (portletWindow == null) {
      // No window for the layout node, return null
      return null;
    }

    final IPortalRequestInfo portalRequestInfo =
        this.urlSyntaxProvider.getPortalRequestInfo(request);
    if (portalRequestInfo.getUrlState() == UrlState.DETACHED) {
      // Handle detached portlets explicitly
      // TODO Can we ever have non-targeted portlets render in a detached request? If so should they
      // all be stateless windows anyways?
      final IPortletWindowId portletWindowId = portletWindow.getPortletWindowId();
      portletWindow = this.getOrCreateStatelessPortletWindow(request, portletWindowId);
    }

    element = this.addPortletWindowId(element, portletWindow.getPortletWindowId());

    return new Tuple<IPortletWindow, StartElement>(portletWindow, element);
  }
  protected String getAttributeName(IPortletWindow portletWindow, String property) {
    final String mappedAttributeName = this.propertyToAttributeMappings.get(property);
    final String attributeName;
    if (mappedAttributeName == null) {
      attributeName = property;
    } else {
      attributeName = mappedAttributeName;
    }

    if (this.nonNamespacedProperties.contains(property)) {
      return attributeName;
    }

    final IPortletWindowId portletWindowId = portletWindow.getPortletWindowId();
    return portletWindowId.getStringId() + attributeName;
  }
  @Override
  public IPortletWindow getOrCreateStatelessPortletWindow(
      HttpServletRequest request, IPortletWindowId basePortletWindowId) {
    // Need the basePortletWindowId to be an instance of PortletWindowIdImpl so that we can extract
    // the entity ID
    if (!(basePortletWindowId instanceof PortletWindowIdImpl)) {
      final String basePortletWindowIdStr = basePortletWindowId.getStringId();
      basePortletWindowId = this.getPortletWindowId(request, basePortletWindowIdStr);
    }

    // Get the entity ID for the portlet window
    final IPortletEntityId portletEntityId =
        ((PortletWindowIdImpl) basePortletWindowId).getPortletEntityId();

    // Create the stateless ID
    final PortletWindowIdImpl statelessPortletWindowId =
        this.createPortletWindowId(STATELESS_PORTLET_WINDOW_ID, portletEntityId);

    // See if there is already a request cached stateless window
    IPortletWindow statelessPortletWindow =
        this.getPortletWindow(request, statelessPortletWindowId);
    if (statelessPortletWindow != null) {
      return statelessPortletWindow;
    }

    // Lookup the base portlet window to clone the stateless from
    final IPortletWindow basePortletWindow = this.getPortletWindow(request, basePortletWindowId);

    final PortletWindowCache<PortletWindowData> statelessPortletWindowDataMap =
        this.getStatelessPortletWindowDataMap(request, true);

    // If no base to clone from lookup the entity and pluto definition data
    if (basePortletWindow == null) {
      final IPortletEntity portletEntity =
          this.portletEntityRegistry.getPortletEntity(request, portletEntityId);
      if (portletEntity == null) {
        throw new IllegalArgumentException(
            "No IPortletEntity could be found for "
                + portletEntity
                + " while creating stateless portlet window for "
                + basePortletWindowId);
      }

      final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition();
      final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId();
      final PortletDefinition portletDescriptor =
          this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId);

      final PortletWindowData portletWindowData =
          new PortletWindowData(statelessPortletWindowId, portletEntityId);
      statelessPortletWindowDataMap.storeWindow(portletWindowData);

      statelessPortletWindow =
          new StatelessPortletWindowImpl(portletWindowData, portletEntity, portletDescriptor);
    }
    // Clone the existing base window
    else {
      final PortletWindowData portletWindowData =
          new PortletWindowData(statelessPortletWindowId, portletEntityId);
      portletWindowData.setExpirationCache(basePortletWindow.getExpirationCache());
      portletWindowData.setPortletMode(basePortletWindow.getPortletMode());
      portletWindowData.setWindowState(basePortletWindow.getWindowState());
      portletWindowData.setPublicRenderParameters(basePortletWindow.getPublicRenderParameters());
      portletWindowData.setRenderParameters(basePortletWindow.getRenderParameters());

      statelessPortletWindowDataMap.storeWindow(portletWindowData);

      final IPortletEntity portletEntity = basePortletWindow.getPortletEntity();
      final PortletDefinition portletDescriptor =
          basePortletWindow.getPlutoPortletWindow().getPortletDefinition();
      statelessPortletWindow =
          new StatelessPortletWindowImpl(portletWindowData, portletEntity, portletDescriptor);
    }

    // Cache the stateless window in the request
    final PortletWindowCache<IPortletWindow> portletWindowMap = this.getPortletWindowMap(request);
    portletWindowMap.storeWindow(statelessPortletWindow);

    return statelessPortletWindow;
  }
  protected String getUrlString(IRedirectionUrl url, HttpServletRequest request) {

    if (url instanceof ExternalRedirectionUrl) {
      ExternalRedirectionUrl externalUrl = (ExternalRedirectionUrl) url;
      StringBuffer urlStr = new StringBuffer();
      urlStr.append(externalUrl.getUrl());

      try {

        // add any additional parameters
        String separator = "?";
        for (Map.Entry<String, String[]> param : externalUrl.getAdditionalParameters().entrySet()) {
          for (String value : param.getValue()) {
            urlStr.append(separator);
            urlStr.append(param.getKey());
            urlStr.append("=");
            urlStr.append(URLEncoder.encode(value, "UTF-8"));
            separator = "&";
          }
        }

        // add any dynamic parameters
        for (Map.Entry<String, String> param : externalUrl.getDynamicParameters().entrySet()) {
          String[] values = request.getParameterValues(param.getKey());
          if (values != null) {
            for (String value : values) {
              urlStr.append(separator);
              urlStr.append(param.getValue());
              urlStr.append("=");
              urlStr.append(URLEncoder.encode(value, "UTF-8"));
              separator = "&";
            }
          }
        }
        return urlStr.toString();

      } catch (UnsupportedEncodingException ex) {
        log.error("Unable to encode URL parameter for external service redirect", ex);
        return null;
      }

    } else {

      PortletRedirectionUrl portletUrl = (PortletRedirectionUrl) url;

      // create the base URL for the portlet
      final IPortletWindow portletWindow =
          this.portletWindowRegistry.getOrCreateDefaultPortletWindowByFname(
              request, portletUrl.getFname());
      final IPortalUrlBuilder portalUrlBuilder =
          this.portalUrlProvider.getPortalUrlBuilderByPortletWindow(
              request, portletWindow.getPortletWindowId(), portletUrl.getType());
      final IPortletUrlBuilder portletUrlBuilder = portalUrlBuilder.getTargetedPortletUrlBuilder();
      portletUrlBuilder.setPortletMode(portletUrl.getMode());
      portletUrlBuilder.setWindowState(WindowState.MAXIMIZED);

      // for each of the defined additional parameters, add a matching
      // parameter to the portlet URL
      for (Map.Entry<String, String[]> param : portletUrl.getAdditionalParameters().entrySet()) {
        portletUrlBuilder.addParameter(param.getKey(), param.getValue());
      }

      // for each of the defined dynamic parameters, add a parameter if
      // the value submitted to this service was non-null
      for (Map.Entry<String, String> param : portletUrl.getDynamicParameters().entrySet()) {
        String[] values = request.getParameterValues(param.getKey());
        if (values != null) {
          portletUrlBuilder.addParameter(param.getValue(), values);
        }
      }

      return portalUrlBuilder.getUrlString();
    }
  }