public void beginRequest()

in trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/upload/FileUploadConfiguratorImpl.java [102:285]


  public void beginRequest(ExternalContext externalContext)
  {
    /*
     * Note: This class does not do a dispose on the file uploads.  The
     * reason for this is that in a portal environment, multiple render-requests
     * may depend on the same set of files being available to the view layer.
     * Instead the files will be automatically cleaned up when the portlet
     * generated the next request.  If we need to clean up sooner then we should
     * clean up on the end-request.
     */
    // FIXME AdamWiner We should clean up ASAP - these are potentially very
    // large allocations of memory and file, so cleaning up as soon
    // as possible is a good thing
    //Process MultipartForm if need be
    
    RequestType reqType =  ExternalContextUtils.getRequestType(externalContext);
    if (MultipartFormHandler.isMultipartRequest(externalContext) &&
       (ExternalContextUtils.isHttpServletRequest(externalContext) || reqType.isPortlet()))
    {
      try
      {
        RequestContext requestContext = RequestContext.getCurrentInstance(); 

        //This is a list of parameters.  Under normal circumstances, this will be a new map
        Map<String, String[]> parameters;
        
        UploadedFiles files = UploadedFiles.getUploadedFiles(externalContext);
        
        //Have uploadedFiles been processed?  It is possible, with framework extensions,
        //that uploadedFiles have been processed.  If they have, there is no reason to process
        //them again.  We assume that both parameters and UploadedFiles have been processed correctly.
        //The check for isPortlet is probably redundant here, but with oddities in the requestScope,
        //and the inability to properly test this, it is probably better to be safe for now to
        //prevent regressions.
        //TODO: Remove the portlet check in the future. 
        if(!FileUploadUtils.isProcessed(externalContext) || reqType.isPortlet())
        {
          final MultipartFormHandler mfh = new MultipartFormHandler(externalContext);

          // TODO: How is this set?
          // AdamWiner: looks like the previous Trinidad incarnation
          // of this code didn't have any allowed configuration...
          mfh.setMaximumAllowedBytes(_maxAllowedBytes);
          mfh.setCharacterEncoding(ExternalContextUtils.getCharacterEncoding(externalContext));

          parameters = new HashMap<String, String[]>();
          MultipartFormItem item;
          files = new UploadedFiles(externalContext);

          while ((item = mfh.getNextPart()) != null)
          {
            final String name = item.getName();
            String value = null;
            // No filename - it's not a file uploaded field
            if (item.getFilename() == null)
            {
              value = item.getValue();
              final Object oldValue = parameters.get(name);
              if (oldValue == null)
              {
                parameters.put(name, new String[]{value});
              }
              else
              {
                final String[] oldArray = (String[]) oldValue;
                final String[] newArray = new String[oldArray.length + 1];
                System.arraycopy(oldArray, 0, newArray, 1, oldArray.length);
                newArray[0] = value;
                parameters.put(name, newArray);
              }
            }
            else if (item.getFilename().length() > 0)
            {
              // Upload a file
              _doUploadFile(requestContext, externalContext, files, item, parameters);
            }
          }
          
          //We move saving of the parameters up here because if the MPF handling
          //has already happened, we don't need to re-wrap the request.
          externalContext.getRequestMap().put(_PARAMS, parameters);
          FileUploadUtils.markProcessed(externalContext);
        }
        else
        {
          //If we don't process the multiform handler then we should get the map
          //from the request.
          parameters = externalContext.getRequestParameterValuesMap();
        }
        
        //This can happen if files were processed ahead of time and there weren't
        //any.
        if(null != files)
        {
          if (parameters.containsKey(_MULTIPLE_UPLOAD_PARAM))
          {
            // This is a multiple file upload request. We will only be processing one request at a time
            // from any particular window since multi file upload requests are queue on the client side
            // per window. So we do not need to implement extra locking logic.
            String uploadType = parameters.get(_MULTIPLE_UPLOAD_PARAM)[0];
            if (uploadType != null)
            {
              UploadedFiles windowFiles = UploadedFiles.getUploadedFilesForWindow(externalContext);
              if (uploadType.equals("multipleAdd"))
              {
                // Add files
                Map<String, List<UploadedFile>> uploadedMapFile = files.getUploadedFileMap();
                Iterator iterator = uploadedMapFile.keySet().iterator();
                while (iterator.hasNext())
                {
                  // Add all the files in the request to the window
                  String name = (String) iterator.next();
                  List<UploadedFile> fileList = uploadedMapFile.get(name);
                  for (UploadedFile file: fileList)
                  {
                    windowFiles.__put(name, file);
                  }
                }
                UploadedFiles.__saveUploadedFilesForWindow(windowFiles, externalContext, requestContext);
                uploadedMapFile.clear();
              }
              else if (uploadType.equals("multipleDelete"))
              {
                // Delete a file
                String itemName = parameters.get("itemName")[0];
                String fileName = parameters.get("fileName")[0];
                List<UploadedFile> uploadedFiles = windowFiles.getUploadedFileList(itemName);
                if (uploadedFiles != null)
                {
                  for (UploadedFile uploadedFile: uploadedFiles)
                  {
                    if (uploadedFile.getFilename().equals(fileName))
                    {
                      // Remove the file from the window, delete the tmp file from disk/memory
                      // and save the file map
                      uploadedFiles.remove(uploadedFile);
                      uploadedFile.dispose();
                      UploadedFiles.__saveUploadedFilesForWindow(windowFiles, externalContext, requestContext);
                      break;
                    }
                  }
                }
              }
              else if (uploadType.equals("multipleAddChunk"))
              {
                // Add a chunk
                String itemName = parameters.get("itemName")[0];
                String fileName = externalContext.getRequestHeaderMap().get(_MULTIPLE_UPLOAD_CHUNK_FILENAME_PARAM);
                Long chunkNum = Long.parseLong(externalContext.getRequestHeaderMap().get(_MULTIPLE_UPLOAD_CHUNK_NUM_PARAM));
                Long chunkCount = Long.parseLong(externalContext.getRequestHeaderMap().get(_MULTIPLE_UPLOAD_CHUNK_COUNT_PARAM));
                UploadedFile file = files.getUploadedFile(itemName);
                // There is no getWindowMap() in PS6 because it requries the new window manager implementation
                // so add to session map. We just won't support simultaneous uploads from different windows
                //Map<String, Object> windowMap = requestContext.getSessionMap();
                //List<UploadedFile> chunkList = (List<UploadedFile>) windowMap.get(_UPLOADED_CHUNK_FILES_LIST_KEY);
                List<UploadedFile> chunkList = (List<UploadedFile>) externalContext.getSessionMap().get(_UPLOADED_CHUNK_FILES_LIST_KEY);
                if (chunkList == null)
                {
                  chunkList = new ArrayList<UploadedFile>();
                  //windowMap.put(_UPLOADED_CHUNK_FILES_LIST_KEY, chunkList);
                  externalContext.getSessionMap().put(_UPLOADED_CHUNK_FILES_LIST_KEY, chunkList);
                }
                chunkList.add(file);
                if (chunkNum == chunkCount - 1)
                {
                  // if it's the last chunk then create a combined file
                  UploadedFile combinedFile = new ChunkedUploadedFile(fileName, file.getContentType(), chunkList);
                  windowFiles.__put(itemName, combinedFile);
                  //windowMap.remove(_UPLOADED_CHUNK_FILES_LIST_KEY);
                  externalContext.getSessionMap().remove(_UPLOADED_CHUNK_FILES_LIST_KEY);
                  UploadedFiles.__saveUploadedFilesForWindow(windowFiles, externalContext, requestContext);
                }
                files.getUploadedFileMap().clear();
              }
            }
          }
        }
      }
      catch (Throwable t)
      {
          _LOG.severe(t);
      }
    }
  }