public synchronized Map<String, Object[]> getParameterMap() {
      if (parameterMap == null) {
        // Two conditions: file upload ("multipart/form-data") or not
        if (getContentType() != null && getContentType().startsWith("multipart/form-data")) {
          // Special handling for multipart/form-data

          // Decode the multipart data
          parameterMap =
              Multipart.getParameterMapMultipart(
                  pipelineContext, request, ServletExternalContext.DEFAULT_FORM_CHARSET_DEFAULT);
        } else if (portletRequest instanceof ResourceRequest) {
          // We encoded query parameters directly into the resource id in this case
          final String queryString =
              NetUtils.getQueryString(((ResourceRequest) portletRequest).getResourceID());
          if (queryString != null)
            parameterMap =
                Collections.unmodifiableMap(
                    StringConversions.stringArrayMapToObjectArrayMap(
                        NetUtils.decodeQueryString(queryString, false)));
          else parameterMap = Collections.emptyMap();
        } else {
          // Not a resource request, so just use native request parameters
          parameterMap = new HashMap<String, Object[]>(portletRequest.getParameterMap());
          parameterMap.remove(WSRPURLRewriter.PathParameterName());
          parameterMap = Collections.unmodifiableMap(parameterMap);
        }
      }
      return parameterMap;
    }
    public synchronized Map<String, String[]> getHeaderValuesMap() {
      // NOTE: The container may or may not make HTTP headers available through the properties API
      if (headerValuesMap == null) {
        headerValuesMap = new HashMap<String, String[]>();

        // NOTE: Not sure we should even pass these properties as "headers"
        // Example of property: javax.portlet.markup.head.element.support = true
        for (Enumeration<String> e = portletRequest.getPropertyNames(); e.hasMoreElements(); ) {
          String name = e.nextElement();
          // NOTE: Normalize names to lowercase to ensure consistency between servlet containers
          headerValuesMap.put(
              name.toLowerCase(),
              StringConversions.stringEnumerationToArray(portletRequest.getProperties(name)));
        }

        // PLT.11.1.5 Request Properties: "client request HTTP headers may not be always available.
        // Portlets
        // should not rely on the presence of headers to function properly. The PortletRequest
        // interface
        // provides specific methods to access information normally available as HTTP headers:
        // content-length,
        // content-type, accept-language."
        // NOTE: It seems like while Liferay 5 was making headers available, Liferay 6 doesn't
        // anymore.
        if (portletRequest instanceof ClientDataRequest) {
          final ClientDataRequest clientDataRequest = (ClientDataRequest) portletRequest;
          if (clientDataRequest.getContentType() != null)
            headerValuesMap.put("content-type", new String[] {clientDataRequest.getContentType()});
          if (clientDataRequest.getContentLength() != -1)
            headerValuesMap.put(
                "content-length",
                new String[] {Integer.toString(clientDataRequest.getContentLength())});
        }
      }
      return headerValuesMap;
    }