@Override
    public IPortalRequestInfo getPortalRequestInfo(HttpServletRequest request) {
        request = this.portalRequestUtils.getOriginalPortalRequest(request);
        final IPortalRequestInfo cachedPortalRequestInfo =
                (IPortalRequestInfo) request.getAttribute(PORTAL_REQUEST_INFO_ATTR);
        if (cachedPortalRequestInfo != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("short-circuit: found portalRequestInfo within request attributes");
            }
            return cachedPortalRequestInfo;
        }

        synchronized (PortalWebUtils.getRequestAttributeMutex(request)) {
            // set a flag to say this request is currently being parsed
            final Boolean inProgressAttr =
                    (Boolean) request.getAttribute(PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR);
            if (inProgressAttr != null && inProgressAttr) {
                if (logger.isDebugEnabled()) {
                    logger.warn("Portal request info parsing already in progress, returning null");
                }
                return null;
            }
            request.setAttribute(PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR, Boolean.TRUE);
        }

        try {
            // Clone the parameter map so data can be removed from it as it is parsed to help
            // determine
            // what to do with non-namespaced parameters
            final Map<String, String[]> parameterMap = new ParameterMap(request.getParameterMap());

            final String requestPath = this.urlPathHelper.getPathWithinApplication(request);

            if (LEGACY_URL_PATHS.contains(requestPath)) {
                return parseLegacyPortalUrl(request, parameterMap);
            }

            final IUrlNodeSyntaxHelper urlNodeSyntaxHelper =
                    this.urlNodeSyntaxHelperRegistry.getCurrentUrlNodeSyntaxHelper(request);

            final PortalRequestInfoImpl portalRequestInfo = new PortalRequestInfoImpl();
            IPortletWindowId targetedPortletWindowId = null;
            PortletRequestInfoImpl targetedPortletRequestInfo = null;

            final String[] requestPathParts = SLASH_PATTERN.split(requestPath);

            UrlState requestedUrlState = null;
            ParseStep parseStep = ParseStep.FOLDER;
            for (int pathPartIndex = 0; pathPartIndex < requestPathParts.length; pathPartIndex++) {
                String pathPart = requestPathParts[pathPartIndex];

                logger.trace("In parseStep {} considering pathPart [{}].", parseStep, pathPart);

                if (StringUtils.isEmpty(pathPart)) {
                    continue;
                }

                switch (parseStep) {
                    case FOLDER:
                        {
                            parseStep = ParseStep.PORTLET;

                            if (FOLDER_PATH_PREFIX.equals(pathPart)) {

                                logger.trace(
                                        "Skipping adding {} to the folders deque "
                                                + "because it is simply the folder path prefix.",
                                        pathPart);

                                pathPartIndex++;

                                final LinkedList<String> folders = new LinkedList<String>();
                                for (; pathPartIndex < requestPathParts.length; pathPartIndex++) {
                                    pathPart = requestPathParts[pathPartIndex];

                                    if (PORTLET_PATH_PREFIX.equals(pathPart)) {
                                        logger.trace(
                                                "Found the portlet part of the path "
                                                        + "demarked by portlet path prefix [{}]; "
                                                        + "stepping back one path part to finish folder processing",
                                                pathPart);
                                        pathPartIndex--;
                                        break;
                                    } else {

                                        if (pathPart.endsWith(REQUEST_TYPE_SUFFIX)) {
                                            logger.trace(
                                                    "Found the end of the folder path with pathPart [{}];"
                                                            + " stepping back one, checking for state, "
                                                            + "and finishing folder parsing",
                                                    pathPart);
                                            pathPartIndex--;
                                            pathPart = requestPathParts[pathPartIndex];

                                            // If a state was added to the folder list remove it and
                                            // step back one so
                                            // other code can handle it
                                            if (UrlState.valueOfIngoreCase(pathPart, null)
                                                    != null) {
                                                logger.trace(
                                                        "A state was added to the end of folder list {};"
                                                                + " removing it.",
                                                        folders);
                                                folders.removeLast();
                                                pathPartIndex--;
                                            }
                                            break;
                                        }
                                    }

                                    logger.trace("Adding pathPart [{}] to folders.", pathPart);
                                    folders.add(pathPart);
                                }

                                logger.trace("Folders is [{}]", folders);
                                if (folders.size() > 0) {
                                    final String targetedLayoutNodeId =
                                            urlNodeSyntaxHelper.getLayoutNodeForFolderNames(
                                                    request, folders);
                                    portalRequestInfo.setTargetedLayoutNodeId(targetedLayoutNodeId);
                                }
                                break;
                            }
                        }
                        // fall through
                    case PORTLET:
                        {
                            parseStep = ParseStep.STATE;

                            final String targetedLayoutNodeId =
                                    portalRequestInfo.getTargetedLayoutNodeId();

                            if (PORTLET_PATH_PREFIX.equals(pathPart)) {
                                if (++pathPartIndex < requestPathParts.length) {
                                    pathPart = requestPathParts[pathPartIndex];

                                    targetedPortletWindowId =
                                            urlNodeSyntaxHelper.getPortletForFolderName(
                                                    request, targetedLayoutNodeId, pathPart);
                                }

                                break;
                            }

                            // See if a portlet was targeted by parameter
                            final String[] targetedPortletIds =
                                    parameterMap.remove(PARAM_TARGET_PORTLET);
                            if (targetedPortletIds != null && targetedPortletIds.length > 0) {
                                final String targetedPortletString = targetedPortletIds[0];
                                targetedPortletWindowId =
                                        urlNodeSyntaxHelper.getPortletForFolderName(
                                                request,
                                                targetedLayoutNodeId,
                                                targetedPortletString);
                            }
                        }
                        // fall through
                    case STATE:
                        {
                            parseStep = ParseStep.TYPE;

                            // States other than the default only make sense if a portlet is being
                            // targeted
                            if (targetedPortletWindowId == null) {
                                break;
                            }

                            requestedUrlState = UrlState.valueOfIngoreCase(pathPart, null);

                            // Set the URL state
                            if (requestedUrlState != null) {
                                portalRequestInfo.setUrlState(requestedUrlState);

                                // If the request is stateless
                                if (statelessUrlStates.contains(requestedUrlState)) {
                                    final IPortletWindow statelessPortletWindow =
                                            this.portletWindowRegistry
                                                    .getOrCreateStatelessPortletWindow(
                                                            request, targetedPortletWindowId);
                                    targetedPortletWindowId =
                                            statelessPortletWindow.getPortletWindowId();
                                }

                                // Create the portlet request info
                                targetedPortletRequestInfo =
                                        portalRequestInfo.getPortletRequestInfo(
                                                targetedPortletWindowId);
                                portalRequestInfo.setTargetedPortletWindowId(
                                        targetedPortletWindowId);

                                // Set window state based on URL State first then look for the
                                // window state parameter
                                switch (requestedUrlState) {
                                    case MAX:
                                        {
                                            targetedPortletRequestInfo.setWindowState(
                                                    WindowState.MAXIMIZED);
                                        }
                                        break;

                                    case DETACHED:
                                        {
                                            targetedPortletRequestInfo.setWindowState(
                                                    IPortletRenderer.DETACHED);
                                        }
                                        break;

                                    case EXCLUSIVE:
                                        {
                                            targetedPortletRequestInfo.setWindowState(
                                                    IPortletRenderer.EXCLUSIVE);
                                        }
                                        break;

                                    default:
                                        // Nothing to do -- some cases don't need treatment
                                }

                                break;
                            }
                        }
                        // fall through
                    case TYPE:
                        {
                            parseStep = ParseStep.COMPLETE;

                            if (pathPartIndex == requestPathParts.length - 1
                                    && pathPart.endsWith(REQUEST_TYPE_SUFFIX)
                                    && pathPart.length() > REQUEST_TYPE_SUFFIX.length()) {
                                final String urlTypePart =
                                        pathPart.substring(
                                                0,
                                                pathPart.length() - REQUEST_TYPE_SUFFIX.length());
                                final UrlType urlType;

                                // Handle inline resourceIds, look for a . in the request type
                                // string and use the suffix as the urlType
                                final int lastPeriod = urlTypePart.lastIndexOf('.');
                                if (lastPeriod >= 0 && lastPeriod < urlTypePart.length()) {
                                    final String urlTypePartSuffix =
                                            urlTypePart.substring(lastPeriod + 1);
                                    urlType = UrlType.valueOfIngoreCase(urlTypePartSuffix, null);
                                    if (urlType == UrlType.RESOURCE
                                            && targetedPortletRequestInfo != null) {
                                        final String resourceId =
                                                urlTypePart.substring(0, lastPeriod);
                                        targetedPortletRequestInfo.setResourceId(resourceId);
                                    }
                                } else {
                                    urlType = UrlType.valueOfIngoreCase(urlTypePart, null);
                                }

                                if (urlType != null) {
                                    portalRequestInfo.setUrlType(urlType);
                                    break;
                                }
                            }
                        }
                        // fall through
                    default:
                        // Nothing to do -- some cases don't need treatment
                }
            }

            // If a targeted portlet window ID is found but no targeted portlet request info has
            // been retrieved yet, set it up
            if (targetedPortletWindowId != null && targetedPortletRequestInfo == null) {
                targetedPortletRequestInfo =
                        portalRequestInfo.getPortletRequestInfo(targetedPortletWindowId);
                portalRequestInfo.setTargetedPortletWindowId(targetedPortletWindowId);
            }

            // Get the set of portlet window ids that also have parameters on the url
            final String[] additionalPortletIdArray = parameterMap.remove(PARAM_ADDITIONAL_PORTLET);
            final Set<String> additionalPortletIds =
                    Sets.newHashSet(
                            additionalPortletIdArray != null
                                    ? additionalPortletIdArray
                                    : new String[0]);

            // Used if there is delegation to capture form-submit and other non-prefixed parameters
            // Map of parent id to delegate id
            final Map<IPortletWindowId, IPortletWindowId> delegateIdMappings =
                    new LinkedHashMap<IPortletWindowId, IPortletWindowId>(0);

            // Parse all remaining parameters from the request
            final Set<Entry<String, String[]>> parameterEntrySet = parameterMap.entrySet();
            for (final Iterator<Entry<String, String[]>> parameterEntryItr =
                            parameterEntrySet.iterator();
                    parameterEntryItr.hasNext(); ) {
                final Entry<String, String[]> parameterEntry = parameterEntryItr.next();

                final String name = parameterEntry.getKey();
                final List<String> values = Arrays.asList(parameterEntry.getValue());

                /* NOTE: continues are being used to allow fall-through behavior like a switch statement would provide */

                // Portal Parameters, just need to remove the prefix
                if (name.startsWith(PORTAL_PARAM_PREFIX)) {
                    final Map<String, List<String>> portalParameters =
                            portalRequestInfo.getPortalParameters();
                    portalParameters.put(
                            this.safeSubstringAfter(PORTAL_PARAM_PREFIX, name), values);
                    parameterEntryItr.remove();
                    continue;
                }

                // Generic portlet parameters, have to remove the prefix and see if there was a
                // portlet windowId between the prefix and parameter name
                if (name.startsWith(PORTLET_PARAM_PREFIX)) {
                    final Tuple<String, IPortletWindowId> portletParameterParts =
                            this.parsePortletParameterName(request, name, additionalPortletIds);
                    final IPortletWindowId portletWindowId = portletParameterParts.second;
                    final String paramName = portletParameterParts.first;

                    // Get the portlet parameter map to add the parameter to
                    final Map<String, List<String>> portletParameters;
                    if (portletWindowId == null) {
                        if (targetedPortletRequestInfo == null) {
                            this.logger.warn(
                                    "Parameter "
                                            + name
                                            + " is for the targeted portlet but no portlet is targeted by the request. The parameter will be ignored. Value: "
                                            + values);
                            parameterEntryItr.remove();
                            break;
                        }

                        portletParameters = targetedPortletRequestInfo.getPortletParameters();
                    } else {
                        final PortletRequestInfoImpl portletRequestInfoImpl =
                                portalRequestInfo.getPortletRequestInfo(portletWindowId);
                        portletParameters = portletRequestInfoImpl.getPortletParameters();
                    }

                    portletParameters.put(paramName, values);
                    parameterEntryItr.remove();
                    continue;
                }

                // Portlet control parameters are either used directly or as a prefix to a windowId.
                // Use the
                // SuffixedPortletParameter to simplify their parsing
                for (final SuffixedPortletParameter suffixedPortletParameter :
                        SuffixedPortletParameter.values()) {
                    final String parameterPrefix = suffixedPortletParameter.getParameterPrefix();
                    // Skip to the next parameter prefix if the current doesn't match
                    if (!name.startsWith(parameterPrefix)) {
                        continue;
                    }

                    // All of these parameters require at least one value
                    if (values.isEmpty()) {
                        this.logger.warn(
                                "Ignoring parameter {} as it must have a value. Value: {}",
                                name,
                                values);
                        break;
                    }

                    // Verify the parameter is being used on the correct type of URL
                    final Set<UrlType> validUrlTypes = suffixedPortletParameter.getValidUrlTypes();
                    if (!validUrlTypes.contains(portalRequestInfo.getUrlType())) {
                        this.logger.warn(
                                "Ignoring parameter {} as it is only valid for {} requests and this is a "
                                        + "{} request. Value: {}",
                                name,
                                validUrlTypes,
                                portalRequestInfo.getUrlType(),
                                values);
                        break;
                    }

                    // Determine the portlet window and request info the parameter targets
                    final IPortletWindowId portletWindowId =
                            this.parsePortletWindowIdSuffix(
                                    request, parameterPrefix, additionalPortletIds, name);
                    final PortletRequestInfoImpl portletRequestInfo =
                            getTargetedPortletRequestInfo(
                                    portalRequestInfo, targetedPortletRequestInfo, portletWindowId);
                    if (portletRequestInfo == null) {
                        this.logger.warn(
                                "Parameter {} is for the targeted portlet but no portlet is targeted"
                                        + " by the request. The parameter will be ignored. Value: {}",
                                name,
                                values);
                        break;
                    }

                    parameterEntryItr.remove();

                    // Use the enum helper to store the parameter values on the request info
                    suffixedPortletParameter.updateRequestInfo(
                            request,
                            portletWindowRegistry,
                            portletRequestInfo,
                            values,
                            delegateIdMappings);
                    break;
                }
            }

            // Any non-namespaced parameters still need processing?
            if (!parameterMap.isEmpty()) {
                // If the parameter was not ignored by a previous parser add it to whatever was
                // targeted (portlet or portal)
                final Map<String, List<String>> parameters;
                if (!delegateIdMappings.isEmpty()) {
                    // Resolve the last portlet window in the chain of delegation
                    PortletRequestInfoImpl delegatePortletRequestInfo = null;
                    for (final IPortletWindowId delegatePortletWindowId :
                            delegateIdMappings.values()) {
                        if (!delegateIdMappings.containsKey(delegatePortletWindowId)) {
                            delegatePortletRequestInfo =
                                    portalRequestInfo.getPortletRequestInfo(
                                            delegatePortletWindowId);
                            break;
                        }
                    }

                    if (delegatePortletRequestInfo != null) {
                        parameters = delegatePortletRequestInfo.getPortletParameters();
                    } else {
                        this.logger.warn(
                                "No root delegate portlet could be resolved, non-namespaced parameters"
                                        + " will be sent to the targeted portlet. THIS SHOULD NEVER HAPPEN. Delegate"
                                        + " parent/child mapping: {}",
                                delegateIdMappings);

                        if (targetedPortletRequestInfo != null) {
                            parameters = targetedPortletRequestInfo.getPortletParameters();
                        } else {
                            parameters = portalRequestInfo.getPortalParameters();
                        }
                    }
                } else if (targetedPortletRequestInfo != null) {
                    parameters = targetedPortletRequestInfo.getPortletParameters();
                } else {
                    parameters = portalRequestInfo.getPortalParameters();
                }

                ParameterMap.putAllList(parameters, parameterMap);
            }

            // If a portlet is targeted but no layout node is targeted must be maximized
            if (targetedPortletRequestInfo != null
                    && portalRequestInfo.getTargetedLayoutNodeId() == null
                    && (requestedUrlState == null || requestedUrlState == UrlState.NORMAL)) {
                portalRequestInfo.setUrlState(UrlState.MAX);
                targetedPortletRequestInfo.setWindowState(WindowState.MAXIMIZED);
            }

            // Make the request info object read-only, once parsed the request info should be static
            portalRequestInfo.makeReadOnly();

            request.setAttribute(PORTAL_REQUEST_INFO_ATTR, portalRequestInfo);

            logger.debug("Finished building requestInfo: {}", portalRequestInfo);

            return portalRequestInfo;
        } finally {
            request.removeAttribute(PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR);
        }
    }
@ Override public IPortalRequestInfo getPortalRequestInfo ( HttpServletRequest request ) { request = this . portalRequestUtils . getOriginalPortalRequest ( request ) ; final IPortalRequestInfo cachedPortalRequestInfo = ( IPortalRequestInfo ) request . getAttribute ( PORTAL_REQUEST_INFO_ATTR ) ; if ( cachedPortalRequestInfo != null ) { if ( logger . isDebugEnabled ( ) ) { logger . debug ( "short-circuit: found portalRequestInfo within request attributes" ) ; } return cachedPortalRequestInfo ; } synchronized ( PortalWebUtils . getRequestAttributeMutex ( request ) ) { final Boolean inProgressAttr = ( Boolean ) request . getAttribute ( PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR ) ; if ( inProgressAttr != null && inProgressAttr ) { if ( logger . isDebugEnabled ( ) ) { logger . warn ( "Portal request info parsing already in progress, returning null" ) ; } return null ; } request . setAttribute ( PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR , Boolean . TRUE ) ; } try { final Map < String , String [ ] > parameterMap = new ParameterMap ( request . getParameterMap ( ) ) ; final String requestPath = this . urlPathHelper . getPathWithinApplication ( request ) ; if ( LEGACY_URL_PATHS . contains ( requestPath ) ) { return parseLegacyPortalUrl ( request , parameterMap ) ; } final IUrlNodeSyntaxHelper urlNodeSyntaxHelper = this . urlNodeSyntaxHelperRegistry . getCurrentUrlNodeSyntaxHelper ( request ) ; final PortalRequestInfoImpl portalRequestInfo = new PortalRequestInfoImpl ( ) ; IPortletWindowId targetedPortletWindowId = null ; PortletRequestInfoImpl targetedPortletRequestInfo = null ; final String [ ] requestPathParts = SLASH_PATTERN . split ( requestPath ) ; UrlState requestedUrlState = null ; ParseStep parseStep = ParseStep . FOLDER ; for ( int pathPartIndex = 0 ; pathPartIndex < requestPathParts . length ; pathPartIndex ++ ) { String pathPart = requestPathParts [ pathPartIndex ] ; logger . trace ( "In parseStep {} considering pathPart [{}]." , parseStep , pathPart ) ; if ( StringUtils . isEmpty ( pathPart ) ) { continue ; } switch ( parseStep ) { case FOLDER : { parseStep = ParseStep . PORTLET ; if ( FOLDER_PATH_PREFIX . equals ( pathPart ) ) { logger . trace ( "Skipping adding {} to the folders deque " + "because it is simply the folder path prefix." , pathPart ) ; pathPartIndex ++ ; final LinkedList < String > folders = new LinkedList < String > ( ) ; for ( ; pathPartIndex < requestPathParts . length ; pathPartIndex ++ ) { pathPart = requestPathParts [ pathPartIndex ] ; if ( PORTLET_PATH_PREFIX . equals ( pathPart ) ) { logger . trace ( "Found the portlet part of the path " + "demarked by portlet path prefix [{}]; " + "stepping back one path part to finish folder processing" , pathPart ) ; pathPartIndex -- ; break ; } else { if ( pathPart . endsWith ( REQUEST_TYPE_SUFFIX ) ) { logger . trace ( "Found the end of the folder path with pathPart [{}];" + " stepping back one, checking for state, " + "and finishing folder parsing" , pathPart ) ; pathPartIndex -- ; pathPart = requestPathParts [ pathPartIndex ] ; if ( UrlState . valueOfIngoreCase ( pathPart , null ) != null ) { logger . trace ( "A state was added to the end of folder list {};" + " removing it." , folders ) ; folders . removeLast ( ) ; pathPartIndex -- ; } break ; } } logger . trace ( "Adding pathPart [{}] to folders." , pathPart ) ; folders . add ( pathPart ) ; } logger . trace ( "Folders is [{}]" , folders ) ; if ( folders . size ( ) > 0 ) { final String targetedLayoutNodeId = urlNodeSyntaxHelper . getLayoutNodeForFolderNames ( request , folders ) ; portalRequestInfo . setTargetedLayoutNodeId ( targetedLayoutNodeId ) ; } break ; } } case PORTLET : { parseStep = ParseStep . STATE ; final String targetedLayoutNodeId = portalRequestInfo . getTargetedLayoutNodeId ( ) ; if ( PORTLET_PATH_PREFIX . equals ( pathPart ) ) { if ( ++ pathPartIndex < requestPathParts . length ) { pathPart = requestPathParts [ pathPartIndex ] ; targetedPortletWindowId = urlNodeSyntaxHelper . getPortletForFolderName ( request , targetedLayoutNodeId , pathPart ) ; } break ; } final String [ ] targetedPortletIds = parameterMap . remove ( PARAM_TARGET_PORTLET ) ; if ( targetedPortletIds != null && targetedPortletIds . length > 0 ) { final String targetedPortletString = targetedPortletIds [ 0 ] ; targetedPortletWindowId = urlNodeSyntaxHelper . getPortletForFolderName ( request , targetedLayoutNodeId , targetedPortletString ) ; } } case STATE : { parseStep = ParseStep . TYPE ; if ( targetedPortletWindowId == null ) { break ; } requestedUrlState = UrlState . valueOfIngoreCase ( pathPart , null ) ; if ( requestedUrlState != null ) { portalRequestInfo . setUrlState ( requestedUrlState ) ; if ( statelessUrlStates . contains ( requestedUrlState ) ) { final IPortletWindow statelessPortletWindow = this . portletWindowRegistry . getOrCreateStatelessPortletWindow ( request , targetedPortletWindowId ) ; targetedPortletWindowId = statelessPortletWindow . getPortletWindowId ( ) ; } targetedPortletRequestInfo = portalRequestInfo . getPortletRequestInfo ( targetedPortletWindowId ) ; portalRequestInfo . setTargetedPortletWindowId ( targetedPortletWindowId ) ; switch ( requestedUrlState ) { case MAX : { targetedPortletRequestInfo . setWindowState ( WindowState . MAXIMIZED ) ; } break ; case DETACHED : { targetedPortletRequestInfo . setWindowState ( IPortletRenderer . DETACHED ) ; } break ; case EXCLUSIVE : { targetedPortletRequestInfo . setWindowState ( IPortletRenderer . EXCLUSIVE ) ; } break ; default : } break ; } } case TYPE : { parseStep = ParseStep . COMPLETE ; if ( pathPartIndex == requestPathParts . length - 1 && pathPart . endsWith ( REQUEST_TYPE_SUFFIX ) && pathPart . length ( ) > REQUEST_TYPE_SUFFIX . length ( ) ) { final String urlTypePart = pathPart . substring ( 0 , pathPart . length ( ) - REQUEST_TYPE_SUFFIX . length ( ) ) ; final UrlType urlType ; final int lastPeriod = urlTypePart . lastIndexOf ( '.' ) ; if ( lastPeriod >= 0 && lastPeriod < urlTypePart . length ( ) ) { final String urlTypePartSuffix = urlTypePart . substring ( lastPeriod + 1 ) ; urlType = UrlType . valueOfIngoreCase ( urlTypePartSuffix , null ) ; if ( urlType == UrlType . RESOURCE && targetedPortletRequestInfo != null ) { final String resourceId = urlTypePart . substring ( 0 , lastPeriod ) ; targetedPortletRequestInfo . setResourceId ( resourceId ) ; } } else { urlType = UrlType . valueOfIngoreCase ( urlTypePart , null ) ; } if ( urlType != null ) { portalRequestInfo . setUrlType ( urlType ) ; break ; } } } default : } } if ( targetedPortletWindowId != null && targetedPortletRequestInfo == null ) { targetedPortletRequestInfo = portalRequestInfo . getPortletRequestInfo ( targetedPortletWindowId ) ; portalRequestInfo . setTargetedPortletWindowId ( targetedPortletWindowId ) ; } final String [ ] additionalPortletIdArray = parameterMap . remove ( PARAM_ADDITIONAL_PORTLET ) ; final Set < String > additionalPortletIds = Sets . newHashSet ( additionalPortletIdArray != null ? additionalPortletIdArray : new String [ 0 ] ) ; final Map < IPortletWindowId , IPortletWindowId > delegateIdMappings = new LinkedHashMap < IPortletWindowId , IPortletWindowId > ( 0 ) ; final Set < Entry < String , String [ ] > > parameterEntrySet = parameterMap . entrySet ( ) ; for ( final Iterator < Entry < String , String [ ] > > parameterEntryItr = parameterEntrySet . iterator ( ) ; parameterEntryItr . hasNext ( ) ; ) { final Entry < String , String [ ] > parameterEntry = parameterEntryItr . next ( ) ; final String name = parameterEntry . getKey ( ) ; final List < String > values = Arrays . asList ( parameterEntry . getValue ( ) ) ; if ( name . startsWith ( PORTAL_PARAM_PREFIX ) ) { final Map < String , List < String > > portalParameters = portalRequestInfo . getPortalParameters ( ) ; portalParameters . put ( this . safeSubstringAfter ( PORTAL_PARAM_PREFIX , name ) , values ) ; parameterEntryItr . remove ( ) ; continue ; } if ( name . startsWith ( PORTLET_PARAM_PREFIX ) ) { final Tuple < String , IPortletWindowId > portletParameterParts = this . parsePortletParameterName ( request , name , additionalPortletIds ) ; final IPortletWindowId portletWindowId = portletParameterParts . second ; final String paramName = portletParameterParts . first ; final Map < String , List < String > > portletParameters ; if ( portletWindowId == null ) { if ( targetedPortletRequestInfo == null ) { this . logger . warn ( "Parameter " + name + " is for the targeted portlet but no portlet is targeted by the request. The parameter will be ignored. Value: " + values ) ; parameterEntryItr . remove ( ) ; break ; } portletParameters = targetedPortletRequestInfo . getPortletParameters ( ) ; } else { final PortletRequestInfoImpl portletRequestInfoImpl = portalRequestInfo . getPortletRequestInfo ( portletWindowId ) ; portletParameters = portletRequestInfoImpl . getPortletParameters ( ) ; } portletParameters . put ( paramName , values ) ; parameterEntryItr . remove ( ) ; continue ; } for ( final SuffixedPortletParameter suffixedPortletParameter : SuffixedPortletParameter . values ( ) ) { final String parameterPrefix = suffixedPortletParameter . getParameterPrefix ( ) ; if ( ! name . startsWith ( parameterPrefix ) ) { continue ; } if ( values . isEmpty ( ) ) { this . logger . warn ( "Ignoring parameter {} as it must have a value. Value: {}" , name , values ) ; break ; } final Set < UrlType > validUrlTypes = suffixedPortletParameter . getValidUrlTypes ( ) ; if ( ! validUrlTypes . contains ( portalRequestInfo . getUrlType ( ) ) ) { this . logger . warn ( "Ignoring parameter {} as it is only valid for {} requests and this is a " + "{} request. Value: {}" , name , validUrlTypes , portalRequestInfo . getUrlType ( ) , values ) ; break ; } final IPortletWindowId portletWindowId = this . parsePortletWindowIdSuffix ( request , parameterPrefix , additionalPortletIds , name ) ; final PortletRequestInfoImpl portletRequestInfo = getTargetedPortletRequestInfo ( portalRequestInfo , targetedPortletRequestInfo , portletWindowId ) ; if ( portletRequestInfo == null ) { this . logger . warn ( "Parameter {} is for the targeted portlet but no portlet is targeted" + " by the request. The parameter will be ignored. Value: {}" , name , values ) ; break ; } parameterEntryItr . remove ( ) ; suffixedPortletParameter . updateRequestInfo ( request , portletWindowRegistry , portletRequestInfo , values , delegateIdMappings ) ; break ; } } if ( ! parameterMap . isEmpty ( ) ) { final Map < String , List < String > > parameters ; if ( ! delegateIdMappings . isEmpty ( ) ) { PortletRequestInfoImpl delegatePortletRequestInfo = null ; for ( final IPortletWindowId delegatePortletWindowId : delegateIdMappings . values ( ) ) { if ( ! delegateIdMappings . containsKey ( delegatePortletWindowId ) ) { delegatePortletRequestInfo = portalRequestInfo . getPortletRequestInfo ( delegatePortletWindowId ) ; break ; } } if ( delegatePortletRequestInfo != null ) { parameters = delegatePortletRequestInfo . getPortletParameters ( ) ; } else { this . logger . warn ( "No root delegate portlet could be resolved, non-namespaced parameters" + " will be sent to the targeted portlet. THIS SHOULD NEVER HAPPEN. Delegate" + " parent/child mapping: {}" , delegateIdMappings ) ; if ( targetedPortletRequestInfo != null ) { parameters = targetedPortletRequestInfo . getPortletParameters ( ) ; } else { parameters = portalRequestInfo . getPortalParameters ( ) ; } } } else if ( targetedPortletRequestInfo != null ) { parameters = targetedPortletRequestInfo . getPortletParameters ( ) ; } else { parameters = portalRequestInfo . getPortalParameters ( ) ; } ParameterMap . putAllList ( parameters , parameterMap ) ; } if ( targetedPortletRequestInfo != null && portalRequestInfo . getTargetedLayoutNodeId ( ) == null && ( requestedUrlState == null || requestedUrlState == UrlState . NORMAL ) ) { portalRequestInfo . setUrlState ( UrlState . MAX ) ; targetedPortletRequestInfo . setWindowState ( WindowState . MAXIMIZED ) ; } portalRequestInfo . makeReadOnly ( ) ; request . setAttribute ( PORTAL_REQUEST_INFO_ATTR , portalRequestInfo ) ; logger . debug ( "Finished building requestInfo: {}" , portalRequestInfo ) ; return portalRequestInfo ; } finally { request . removeAttribute ( PORTAL_REQUEST_PARSING_IN_PROGRESS_ATTR ) ; } }
/* (non-Javadoc)
@see org.apereo.portal.url.IPortalUrlProvider#getPortalRequestInfo(javax.servlet.http.HttpServletRequest)