Package org.apache.myfaces.trinidadinternal.config.upload

Source Code of org.apache.myfaces.trinidadinternal.config.upload.CompositeUploadedFileProcessorImpl$RequestInfo

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.trinidadinternal.config.upload;


import java.io.File;
import java.io.IOException;
import java.io.Serializable;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.util.Map;

import javax.portlet.ActionRequest;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;

import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.model.UploadedFile;
import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
import org.apache.myfaces.trinidad.webapp.UploadedFileProcessor;
import org.apache.myfaces.trinidadinternal.context.external.PortletApplicationMap;
import org.apache.myfaces.trinidadinternal.context.external.PortletInitParameterMap;
import org.apache.myfaces.trinidadinternal.context.external.PortletRequestMap;
import org.apache.myfaces.trinidadinternal.context.external.ServletApplicationMap;
import org.apache.myfaces.trinidadinternal.context.external.ServletInitParameterMap;
import org.apache.myfaces.trinidadinternal.context.external.ServletRequestMap;

/**
* This is the default implementaion of UploadedFileProcessor. It works with
* multiple ChainedUploadedFileProcessor declared in trinidad-config.xml by dispatching
* the lifecycle calls to them in the order of declaration.
**/
public class CompositeUploadedFileProcessorImpl implements UploadedFileProcessor
{

  public CompositeUploadedFileProcessorImpl()
  {
    chainedProcessors = Collections.emptyList();
  }

  public CompositeUploadedFileProcessorImpl(
          List<? extends UploadedFileProcessor> chainedProcessors)
  {
    this.chainedProcessors = chainedProcessors;
  }

  @Override
  public void init(Object context)
  {
    _init(context);
    for(UploadedFileProcessor processor: chainedProcessors)
    {
      //call other chained processor's init
      processor.init(context);
    }

  }

  @Override
  public UploadedFile processFile(Object request, UploadedFile tempFile) throws IOException
  {
    //NOTE: The following optimization was suggested at one point:
    // Check if there are any processors in the list. If yes then call _processFile
    // else just return tempFile we got. Calling _processFile buffers the entire
    // file content. tempFile arg however is not buffered. If there are no
    // ChainedUploadedFileProcessor in the list, then there is no need to buffer.
    // BUT, the call to getLength() and dispose() on tempFile fails.
    // This is becasue, the impl of these 2 methods are not complete -
    // Bug - https://issues.apache.org/jira/browse/TRINIDAD-1765
    // This bug could not be fixed due to the explanatio in the bug.

    //call _processFile first. This will create the auto buffer that we want.
    UploadedFile original = _processFile(request, tempFile);
    if(chainedProcessors.isEmpty())
    {
      return original;
    }
    else
    {
      List<UploadedFile> files = new ArrayList<UploadedFile>(chainedProcessors.size()+1);
      files.add(original);
      for(UploadedFileProcessor processor: chainedProcessors)
      {
        try
        {
          original = processor.processFile(request, original);
        }
        catch (IOException ioe)
        {
          _LOG.severe(ioe);
          String test = ioe.getLocalizedMessage();
          original = new ErrorFile(tempFile.getFilename(), ioe.getLocalizedMessage());
          // The chain breaks if one of the chained processor throws an IOException, if the intent
          //  is to allow rest of the processors in chain to process, they could return custom
          //  UploadedFile instance with length -1 and opaqueData having the failure details.
          break;
        }
        files.add(original);
      }
      //the dispose order should be reverse!
      Collections.reverse(files);
      return new WrappedUploadedFileImpl(original, files);
    }
  }


  /**
   * Wrapper around UploadedFileImpl to listen for dispose() call and dispatch to
   * other UploadedFileImpls returned by other chained processors
   */
  private static class WrappedUploadedFileImpl implements UploadedFile, Serializable
  {

    public WrappedUploadedFileImpl(UploadedFile original, List<UploadedFile> files)
    {
      this.original = original;
      this.files = files;
    }

    public void dispose()
    {
      try
      {
        original.dispose();
      }
      catch(Exception e)
      {
        _LOG.warning("Exception while disposing!", e);
        //log and continue disposing the rest.
      }
      if(!files.isEmpty())
      {
        List<UploadedFile> disposed = new ArrayList<UploadedFile>();
        disposed.add(original);
        for(UploadedFile file: files)
        {
          if(!disposed.contains(file))
          {
            try
            {
              file.dispose();
            }
            catch(Exception e)
            {
              _LOG.warning("Exception while disposing!", e);
              //log and continue disposing the rest.
            }
            disposed.add(file);
          }
        }
      }
    }

    public String getFilename()
    {
      return original.getFilename();
    }

    public String getContentType()
    {
      return original.getContentType();
    }

    public long getLength()
    {
      return original.getLength();
    }

    public Object getOpaqueData()
    {
      return original.getOpaqueData();
    }

    public InputStream getInputStream() throws IOException
    {
      return original.getInputStream();
    }

    private final UploadedFile original;
    private final List<UploadedFile> files;
    private static final long serialVersionUID = 1L;
  }

  private void _init(Object context)
  {
    ContextInfo info;
    if(_PORTLET_CONTEXT_CLASS != null && _PORTLET_CONTEXT_CLASS.isInstance(context))
    {
      info = _getPortletContextInfo(context);
    }
    else
    {
      info = _getServletContextInfo(context);
    }

    //
    // Get MaxMemory and TempDir properties from servlet init params
    //
    if (_maxMemory == -1)
    {
      String maxMemory = info.initParams.get(MAX_MEMORY_PARAM_NAME);
      if (maxMemory != null)
      {
        try
        {
          _maxMemory = Long.parseLong(maxMemory);
        }
        catch (NumberFormatException nfe)
        {
          _maxMemory = _DEFAULT_MAX_MEMORY;
        }
      }
      else
      {
        _maxMemory = _DEFAULT_MAX_MEMORY;
      }
    }

    if (_maxDiskSpace == -1)
    {
      String maxDiskSpace = info.initParams.get(MAX_DISK_SPACE_PARAM_NAME);
      if (maxDiskSpace != null)
      {
        try
        {
          _maxDiskSpace = Long.parseLong(maxDiskSpace);
        }
        catch (NumberFormatException nfe)
        {
          _maxDiskSpace = _DEFAULT_MAX_DISK_SPACE;
        }
      }
      else
      {
        _maxDiskSpace = _DEFAULT_MAX_DISK_SPACE;
      }
    }

    if (_tempDir == null)
    {
      _tempDir = info.initParams.get(TEMP_DIR_PARAM_NAME);
      // Use the webapp temporary directory if the temporary directory
      // has not been explicitly set.
      if (_tempDir == null)
      {
        File tempDirFile = (File)
          info.attributes.get("javax.servlet.context.tempdir");
        if (tempDirFile != null)
          _tempDir = tempDirFile.getAbsolutePath();
      }
    }
   
    if (_maxFileSize == -1)
    {
      String maxFileSize = info.initParams.get(MAX_FILE_SIZE_PARAM_NAME);
      if (maxFileSize != null)
      {
        try
        {
          _maxFileSize = Long.parseLong(maxFileSize);
        }
        catch (NumberFormatException nfe)
        {
          _maxFileSize = _DEFAULT_MAX_FILE_SIZE;
        }
      }
      else
      {
        _maxFileSize = _DEFAULT_MAX_FILE_SIZE;
      }
    }
  }

  private UploadedFile _processFile(
      Object request, UploadedFile tempFile)
  {
    RequestInfo info = _getRequestInfo(request);
    int contentLength = getContentLength(request);
    Map<String, Object> requestMap;

    if (_isPortletRequestClass(request))
      requestMap = _getPortletRequestMap(request);
    else
      requestMap = _getServletRequestMap(request);

    Long maxMemory = (Long)requestMap.get(MAX_MEMORY_PARAM_NAME);
    Long maxDiskSpace = (Long)requestMap.get(MAX_DISK_SPACE_PARAM_NAME);
    String tempDir = (String)requestMap.get(TEMP_DIR_PARAM_NAME);
    Long maxFileSizeSpace = (Long)requestMap.get(MAX_FILE_SIZE_PARAM_NAME);
   
    if (maxMemory != null)
    {
      _maxMemory = maxMemory;
    }

    if (maxDiskSpace != null)
    {
      _maxDiskSpace = maxDiskSpace;
    }

    if (tempDir != null)
      _tempDir = tempDir;

    if (maxFileSizeSpace != null)
    {
      _maxFileSize = maxFileSizeSpace;
    }
   
    if(contentLength>_maxDiskSpace)
    {
      return new ErrorFile(tempFile.getFilename(), _LOG.getMessage("UPLOADED_FILE_LARGE"));
    }
    // If the file is too large throw error
    if(contentLength>_maxFileSize)
    {
      return new ErrorFile(tempFile.getFilename(), _LOG.getMessage("UPLOADED_FILE_LARGE"));
    }
    // Process one new file, loading only as much as can fit
    // in the remaining memory and disk space.
    UploadedFileImpl file = new UploadedFileImpl();
    try
    {
      file.loadFile(tempFile,
                    _maxMemory - info.totalBytesInMemory,
                    _maxDiskSpace - info.totalBytesOnDisk,
                    _tempDir);
    }
    catch(IOException ioe)
    {
      _LOG.severe(ioe);
      return new ErrorFile(tempFile.getFilename(), ioe.getLocalizedMessage());
    }

    // Keep a tally of how much we've stored in memory and on disk.
    long length = file.getLength();
    if (file.__isInMemory())
    {
      info.totalBytesInMemory += length;
    }
    else
    {
      info.totalBytesOnDisk += length;
    }

    return file;
  }

  private int getContentLength(Object request)
  {
    int length = -1;
    if (_isPortletRequestClass(request))
    {
      length = _getPortletRequestLength(request);
    }
    else
    {
      length = _getServletRequestLength(request);
    }

    return length;
  }

  private RequestInfo _getRequestInfo(Object request)
  {
    Map<String, Object> attributes;
    if (_isPortletRequestClass(request))
    {
      attributes = _getPortletRequestMap(request);
    }
    else
    {
      attributes = _getServletRequestMap(request);
    }


    RequestInfo info = (RequestInfo) attributes.get(_REQUEST_INFO_KEY);

    if (info == null)
    {
      info = new RequestInfo();
      attributes.put(_REQUEST_INFO_KEY, info);
    }

    return info;
  }

  private boolean _isPortletRequestClass(Object request)
  {
    return (_PORTLET_REQUEST_CLASS != null && _PORTLET_REQUEST_CLASS.isInstance(request));
  }

  private static final ContextInfo _getServletContextInfo(final Object context)
  {
    assert(context instanceof ServletContext);

    final ServletContext sContext = (ServletContext)context;
    return new ContextInfo(
             new ServletInitParameterMap(sContext),
             new ServletApplicationMap(sContext));
  }

  private static final ContextInfo _getPortletContextInfo(final Object context)
  {
    assert(context instanceof PortletContext);

    final PortletContext pContext = (PortletContext)context;
    return new ContextInfo(
             new PortletInitParameterMap(pContext),
             new PortletApplicationMap(pContext));
  }

  private static final Map<String, Object> _getServletRequestMap(final Object request)
  {
    assert(request instanceof ServletRequest);

    return new ServletRequestMap((ServletRequest) request);
  }

  private static final Map<String, Object> _getPortletRequestMap(final Object request)
  {
    assert(request instanceof PortletRequest);

    return new PortletRequestMap((PortletRequest) request);
  }

  private static final int _getServletRequestLength(final Object request)
  {
    assert(request instanceof ServletRequest);

    return ((ServletRequest) request).getContentLength();
  }

  private static final int _getPortletRequestLength(final Object request)
  {
    if (!(request instanceof ActionRequest))
      return -1;

    return ((ActionRequest) request).getContentLength();
  }

  static private class RequestInfo
  {
    public long totalBytesInMemory;
    public long totalBytesOnDisk;
  }

  static private class ContextInfo
  {
    public ContextInfo(Map<String,String> init, Map<String, Object> attrib)
    {
      initParams= init;
      attributes = attrib;
    }

    public Map<String, String> initParams;
    public Map<String, Object> attributes;
  }

  private long   _maxMemory = -1;
  private long   _maxDiskSpace = -1;
  private long   _maxFileSize = -1;
  private String _tempDir = null;

  private static final long _DEFAULT_MAX_MEMORY = 102400;
  private static final long _DEFAULT_MAX_DISK_SPACE = 2048000;
  private static final long _DEFAULT_MAX_FILE_SIZE = 2048000;

  private static final String _REQUEST_INFO_KEY = CompositeUploadedFileProcessorImpl.class.getName()+
    ".UploadedFilesInfo";

  private static final TrinidadLogger _LOG =
    TrinidadLogger.createTrinidadLogger(CompositeUploadedFileProcessorImpl.class);

  private static final Class<?>        _PORTLET_CONTEXT_CLASS;
  private static final Class<?>       _PORTLET_REQUEST_CLASS;

  static
  {
    Class<?> context;
    Class<?> request;
    try
    {
      context = ClassLoaderUtils.loadClass("javax.portlet.PortletContext");
      request = ClassLoaderUtils.loadClass("javax.portlet.PortletRequest");
    }
    catch (final ClassNotFoundException e)
    {
      _LOG
          .fine("Portlet API is not available on the classpath.  Portlet configurations are disabled.");
      context = null;
      request = null;
    }

    _PORTLET_CONTEXT_CLASS = context;
    _PORTLET_REQUEST_CLASS = request;
  }


  private final List<? extends UploadedFileProcessor> chainedProcessors;
}
TOP

Related Classes of org.apache.myfaces.trinidadinternal.config.upload.CompositeUploadedFileProcessorImpl$RequestInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
TagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');