public PortalURL parse()

in pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/url/impl/PortalURLParserImpl.java [122:422]


   public PortalURL parse(HttpServletRequest request) {

      String reqURI = request.getRequestURI();
      String contextPath = request.getContextPath();
      String servletName = request.getServletPath();

      if (isDebug) {
         LOG.debug("Parsing. Context Path: " + contextPath + ", Servlet Name: " + servletName + ", Request URI: " + reqURI);
      }


      String urlBase = request.getScheme()+"://" + request.getServerName() + ":" + request.getServerPort();
      // Construct portal URL using info retrieved from servlet request.
      RelativePortalURLImpl portalURL =  new RelativePortalURLImpl(urlBase, contextPath, servletName, this, request);

      // Support added for filter.  Should we separate into a different impl?
      String pathInfo = request.getPathInfo();
      if (pathInfo == null) {
         if(servletName.contains(".jsp") && !servletName.endsWith(".jsp")) {
            int idx = servletName.indexOf(".jsp")+".jsp".length();
            pathInfo = servletName.substring(idx);
            servletName = servletName.substring(0, idx);
            portalURL = new RelativePortalURLImpl(urlBase, contextPath, servletName, this, request);
            if (isDebug) {
               LOG.debug("Constructed new URL due to JSP processing. pathInfo: " + pathInfo);
            }
         }
      }
      
      // we want to work with the untranslated path info, so extract it from the URI.
      // chop off query string.
      String prefix = contextPath + servletName;
      int qi = reqURI.indexOf("?");
      qi = (qi < 0) ? reqURI.length() : qi;
      pathInfo = reqURI.substring(prefix.length(), qi);

      if (isTrace) {
         LOG.debug("Parsing request pathInfo: " + pathInfo);
      }

      // Need to set the render path (= page) and PRP mapper before the rest of the URL is parsed
      StringBuilder renderPath = new StringBuilder();
      if (pathInfo.length() > 0 && pathInfo.charAt(0) != '/') {
         renderPath.append('/');
      }

      int ind = pathInfo.indexOf(TOKEN_DELIM + PREFIX);
      if (ind < 0) {
         // there are no parameters to process
         renderPath.append(urlDecode(pathInfo));
         pathInfo = "";
      } else {
         // parameters, etc. remain to be processed
         renderPath.append(urlDecode(pathInfo.substring(0, ind)));
         pathInfo = pathInfo.substring(ind);
      }

      portalURL.setRenderPath(renderPath.toString());
      if (isTrace) {
         LOG.debug("Parse: renderPath: " + renderPath.toString() + ",  pathInfo: " + pathInfo);
      }

      // Set up public render parameter mapper & portlet ID list
      
      ServletContext sc = request.getServletContext();
      DriverConfiguration dc = (DriverConfiguration) sc.getAttribute(AttributeKeys.DRIVER_CONFIG);
      // special handling for default page
      String rp = (renderPath.length() > 0) ? renderPath.toString() : null;
      PublicRenderParameterMapper prpm = dc.getPublicRenderParameterService()
            .getPRPMapper(rp);
      portalURL.setPublicRenderParameterMapper(prpm);
      Collection<String> pids = dc.getPageConfig(rp).getPortletIds();
      portalURL.setPortletIds(pids);

      // Extract the version info for the portlets on the page and store in URL
      
      StringBuilder vstr = new StringBuilder();
      if (isTrace) {
         vstr.append("Portlet Versions: ");
      }
      for (String pid : pids) {
         String appName = PortletWindowConfig.fromId(pid).getContextPath();
         try {
            String pv = dc.getPortletRegistryService().getPortletApplication(appName).getVersion();
            portalURL.setVersion(pid, pv);
            if (isTrace) {
               vstr.append(pid).append(" = ").append(pv).append(", ");
            }
         } catch (Exception e) {
            LOG.error("Portlet application definition could not be retrieved for " + appName);
         }
      }
      if (isTrace) {
         LOG.debug(vstr.toString());
      }

      // Tokenize the rest and process the tokens
      ArrayList<String> portletIds = new ArrayList<String>();
      if (pathInfo.length() > 2) {
         String[] tokens = pathInfo.split(TOKEN_DELIM + PREFIX);
         for (String t : tokens) {

            // vals contains the component values of the token after the type
            String type, val;
            String[] vals;
            if (t.length() < 3) {
               // LOG.warn("Token >>" + t + "<< is too short!! ");
               continue;
            } else {
               type = t.substring(0, 2);
               val = t.substring(2);
               vals = val.split(DELIM);
            }

            // If the first value is numeric, attempt to dereference the index to obtain the portlet ID.
            // The code assumes that the portlet ID table in the URL appears directly after the render path. 
            int index = -1;
            String pid = null;
            if ((vals[0].length() > 0) && vals[0].matches("\\d+")) {
               try {
                  index = Integer.parseInt(vals[0]);
                  if ((index >= 0) && (index < portletIds.size())) {
                     pid = portletIds.get(index);
                  }
               } catch (Exception e) {
                  LOG.error("error parsing URL pid reference token. Token: " + vals[0] + ", exception: " + e.toString());
               }
            }

            // Get the portlet IDs & reference numbers. The portlet IDs are URL encoded.
            if (type.equals(PORTLET_ID)) {
               portletIds.add(Integer.parseInt(vals[1]), urlDecode(vals[0]));
               continue;
            } 

            // Cacheability definition: portalURL.setCacheability().
            if (type.equals(CACHE_LEVEL)) {
               portalURL.setCacheability(urlDecode(vals[0]));
               continue;
            }

            // ResourceID definition: portalURL.setResourceID().
            if (type.equals(RESOURCE_ID)) {
               portalURL.setResourceID(urlDecode(vals[0]));
               continue;
            }

            // Authenticate definition: portalURL.setAuthenticated().
            if (type.equals(AUTHENTICATE)) {
               portalURL.setAuthenticated(Boolean.valueOf(urlDecode(vals[0])));
               continue;
            }

            // Resource window definition: portalURL.setResourceWindow().
            if (type.equals(RESOURCE)) {
               portalURL.setTargetWindow(pid);
               portalURL.setType(URLType.Resource);
               continue;
            }

            // Render window definition: portalURL.setResourceWindow().
            if (type.equals(RENDER)) {
               portalURL.setTargetWindow(pid);
               portalURL.setType(URLType.Render);
               continue;
            }

            // Action window definition: portalURL.setActionWindow().
            if (type.equals(ACTION)) {
               portalURL.setTargetWindow(pid);
               portalURL.setType(URLType.Action);
               continue;
            }

            // Ajax Action window definition: portalURL.setActionWindow().
            if (type.equals(AJAX_ACTION)) {
               portalURL.setTargetWindow(pid);
               portalURL.setType(URLType.AjaxAction);
               continue;
            }

            // Partial Action window definition: portalURL.setActionWindow().
            if (type.equals(PARTIAL_ACTION)) {
               portalURL.setTargetWindow(pid);
               portalURL.setType(URLType.PartialAction);
               continue;
            }

            // Window state definition: portalURL.setWindowState().
            if (type.equals(WINDOW_STATE)) {
               portalURL.setWindowState(pid, new WindowState(urlDecode(vals[1])));
               continue;
            }

            // Portlet mode definition: portalURL.setPortletMode().
            if (type.equals(PORTLET_MODE)) {
               portalURL.setPortletMode(pid, new PortletMode(urlDecode(vals[1])));
               continue;
            }

            // The remaining types deal with parameters, so extract the
            // parameter name and values.
            StringBuilder dbgstr = new StringBuilder();
            if (isTrace) {
               dbgstr.append("Decoding parameter: window ID=").append(pid)
                     .append(", name/value=").append(vals[1]);
            }

            String values = vals[1];
            if (type.equals(PUBLIC_RENDER_PARAM)) {
               if (vals.length != 3) {
                  LOG.warn("Bad PRP Token: " + val);  
               } else {
                  values = vals[2];
               }
            }

            String[] pVals = values.split(VALUE_DELIM, -1);
            String[] paramValues = new String[0];
            String paramName = "";
            boolean isEmptyArray = false;
            if (pVals.length > 1) {
               if (pVals.length == 2 && pVals[1].equals(VALUE_ARRAY_EMPTY)) {
                  isEmptyArray = true;
               }
               for (int i = 0; i < pVals.length; i++){
                  if (pVals[i].equals(VALUE_NULL)) {
                     pVals[i] = null;
                  } else {
                     pVals[i] = urlDecode(pVals[i]);
                  }
               }
            }
            
            if (pVals.length == 0 || pVals[0] == null) {
               LOG.warn("Bad parameter token: " + values);
            } else {
               paramName = pVals[0];
               if (isEmptyArray) {
                  paramValues = new String[0];
               } else {
                  paramValues = Arrays.copyOfRange(pVals, 1, pVals.length);
               }
            }
            
            if (isTrace) {
               dbgstr.append(", paramName=").append(paramName);
               dbgstr.append(", Values length=").append(paramValues.length);
               dbgstr.append(", paramValues=").append(Arrays.toString(paramValues));
               LOG.debug(dbgstr.toString());
            }

            // Portal URL parameter: portalURL.addParameter().
            if(type.equals(RENDER_PARAM)) {
               portalURL.addParameter(new PortalURLParameter(pid, paramName, paramValues));
               continue;
            }

            // Portal URL parameter: portalURL.addParameter().
            if(type.equals(ACTION_PARAM)) {
               portalURL.addParameter(new PortalURLParameter(pid, paramName, paramValues, 
                     PortalURLParameter.PARAM_TYPE_ACTION));
               continue;
            }

            // Portal URL parameter: portalURL.addParameter().
            if(type.equals(RESOURCE_PARAM)) {
               portalURL.addParameter(new PortalURLParameter(pid, paramName, paramValues,
                     PortalURLParameter.PARAM_TYPE_RESOURCE));
               continue;
            }

            //set public parameter in portalURL
            if (type.equals(PUBLIC_RENDER_PARAM)){
               PublicRenderParameterMapper mapper = portalURL.getPublicRenderParameterMapper();
               int prpGroup = mapper.getIndex(pid, paramName);
               if (prpGroup >= 0) {
                  mapper.setValues(prpGroup, paramValues);
               } else {
                  StringBuilder sb = new StringBuilder("Could not find public render parameter group for portlet ID=");
                  sb.append(pid).append(", parameter name=").append(paramName);
                  LOG.warn(sb.toString());
               }
               continue;
            }
         }
      }

      // If we're dealing with a render request (with or without target portlet),
      // we can parse the servlet request parameters directly.
      if (portalURL.getType() == URLType.Render || portalURL.getType() == URLType.Portal) {
         portalURL.handleServletRequestParams();
      }
      
      if (isTrace) {
         LOG.debug("Found " + portletIds.size() + " IDs: " + Arrays.toString(portletIds.toArray()));
      }

      // Return the portal URL.
      return portalURL;
   }