All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.phloc.web.fileupload.AbstractFileUploadBase Maven / Gradle / Ivy

/**
 * Copyright (C) 2006-2015 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * Licensed 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 com.phloc.web.fileupload;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.annotations.ReturnsMutableCopy;
import com.phloc.commons.charset.CCharset;
import com.phloc.commons.charset.CharsetManager;
import com.phloc.commons.string.StringParser;
import com.phloc.web.fileupload.MultipartStream.ItemInputStream;
import com.phloc.web.fileupload.util.AbstractLimitedInputStream;
import com.phloc.web.fileupload.util.FileItemHeadersImpl;
import com.phloc.web.fileupload.util.ICloseable;
import com.phloc.web.fileupload.util.Streams;

/**
 * 

* High level API for processing file uploads. *

*

* This class handles multiple files per single HTML widget, sent using * multipart/mixed encoding type, as specified by RFC 1867. *

*

* How the data for individual parts is stored is determined by the factory used * to create them; a given part may be in memory, on disk, or somewhere else. *

* * @author Rafal Krzewski * @author Daniel Rall * @author Jason van Zyl * @author John McNally * @author Martin Cooper * @author Sean C. Sullivan * @version $Id: FileUploadBase.java 963609 2010-07-13 06:56:47Z jochen $ */ public abstract class AbstractFileUploadBase { /** *

* Utility method that determines whether the request contains multipart * content. *

*

* NOTE:This method will be moved to the * ServletFileUpload class after the FileUpload 1.1 release. * Unfortunately, since this method is static, it is not possible to provide * its replacement until this method is removed. *

* * @param ctx * The request context to be evaluated. Must be non-null. * @return true if the request is multipart; false * otherwise. */ public static final boolean isMultipartContent (@Nonnull final IRequestContext ctx) { final String contentType = ctx.getContentType (); if (contentType == null) return false; if (contentType.toLowerCase (Locale.US).startsWith (MULTIPART)) return true; return false; } /** * HTTP content type header name. */ public static final String CONTENT_TYPE = "Content-type"; /** * HTTP content disposition header name. */ public static final String CONTENT_DISPOSITION = "Content-disposition"; /** * HTTP content length header name. */ public static final String CONTENT_LENGTH = "Content-length"; /** * Content-disposition value for form data. */ public static final String FORM_DATA = "form-data"; /** * Content-disposition value for file attachment. */ public static final String ATTACHMENT = "attachment"; /** * Part of HTTP content type header. */ public static final String MULTIPART = "multipart/"; /** * HTTP content type header for multipart forms. */ public static final String MULTIPART_FORM_DATA = "multipart/form-data"; /** * HTTP content type header for multiple uploads. */ public static final String MULTIPART_MIXED = "multipart/mixed"; // ----------------------------------------------------------- Data members /** * The maximum size permitted for the complete request, as opposed to * {@link #m_nFileSizeMax}. A value of -1 indicates no maximum. */ private long m_nSizeMax = -1; /** * The maximum size permitted for a single uploaded file, as opposed to * {@link #m_nSizeMax}. A value of -1 indicates no maximum. */ private long m_nFileSizeMax = -1; /** * The content encoding to use when reading part headers. */ private String m_sHeaderEncoding; /** * The progress listener. */ private IProgressListener m_aListener; // ----------------------------------------------------- Property accessors /** * Returns the factory class used when creating file items. * * @return The factory class for new file items. */ public abstract IFileItemFactory getFileItemFactory (); /** * Returns the maximum allowed size of a complete request, as opposed to * {@link #getFileSizeMax()}. * * @return The maximum allowed size, in bytes. The default value of -1 * indicates, that there is no limit. * @see #setSizeMax(long) */ public long getSizeMax () { return m_nSizeMax; } /** * Sets the maximum allowed size of a complete request, as opposed to * {@link #setFileSizeMax(long)}. * * @param sizeMax * The maximum allowed size, in bytes. The default value of -1 * indicates, that there is no limit. * @see #getSizeMax() */ public void setSizeMax (final long sizeMax) { m_nSizeMax = sizeMax; } /** * Returns the maximum allowed size of a single uploaded file, as opposed to * {@link #getSizeMax()}. * * @see #setFileSizeMax(long) * @return Maximum size of a single uploaded file. */ public long getFileSizeMax () { return m_nFileSizeMax; } /** * Sets the maximum allowed size of a single uploaded file, as opposed to * {@link #getSizeMax()}. * * @see #getFileSizeMax() * @param fileSizeMax * Maximum size of a single uploaded file. */ public void setFileSizeMax (final long fileSizeMax) { m_nFileSizeMax = fileSizeMax; } /** * Retrieves the character encoding used when reading the headers of an * individual part. When not specified, or null, the request * encoding is used. If that is also not specified, or null, the * platform default encoding is used. * * @return The encoding used to read part headers. */ public String getHeaderEncoding () { return m_sHeaderEncoding; } /** * Specifies the character encoding to be used when reading the headers of * individual part. When not specified, or null, the request * encoding is used. If that is also not specified, or null, the * platform default encoding is used. * * @param encoding * The encoding used to read part headers. */ public void setHeaderEncoding (final String encoding) { m_sHeaderEncoding = encoding; } /** * Processes an RFC 1867 * compliant multipart/form-data stream. * * @param ctx * The context for the request to be parsed. * @return An iterator to instances of FileItemStream parsed from * the request, in the order that they were transmitted. * @throws FileUploadException * if there are problems reading/parsing the request or storing files. * @throws IOException * An I/O error occurred. This may be a network error while * communicating with the client or a problem while storing the * uploaded content. */ @Nonnull public IFileItemIterator getItemIterator (@Nonnull final IRequestContext ctx) throws FileUploadException, IOException { return new FileItemIteratorImpl (ctx); } /** * Processes an RFC 1867 * compliant multipart/form-data stream. * * @param ctx * The context for the request to be parsed. * @return A list of FileItem instances parsed from the request, * in the order that they were transmitted. * @throws FileUploadException * if there are problems reading/parsing the request or storing files. */ @Nonnull @ReturnsMutableCopy public List parseRequest (final IRequestContext ctx) throws FileUploadException { final List items = new ArrayList (); boolean bSuccessful = false; try { final IFileItemIterator iter = getItemIterator (ctx); final IFileItemFactory aFileItemFactory = getFileItemFactory (); if (aFileItemFactory == null) throw new NullPointerException ("No FileItemFactory has been set."); while (iter.hasNext ()) { final IFileItemStream item = iter.next (); // Don't use getName() here to prevent an InvalidFileNameException. final String fileName = ((AbstractFileUploadBase.FileItemIteratorImpl.FileItemStreamImpl) item).m_sName; final IFileItem fileItem = aFileItemFactory.createItem (item.getFieldName (), item.getContentType (), item.isFormField (), fileName); items.add (fileItem); try { Streams.copy (item.openStream (), fileItem.getOutputStream (), true); } catch (final FileUploadIOException e) { throw (FileUploadException) e.getCause (); } catch (final IOException e) { throw new IOFileUploadException ("Processing of " + MULTIPART_FORM_DATA + " request failed. " + e.getMessage (), e); } if (fileItem instanceof IFileItemHeadersSupport) { final IFileItemHeaders fih = item.getHeaders (); ((IFileItemHeadersSupport) fileItem).setHeaders (fih); } } bSuccessful = true; return items; } catch (final FileUploadIOException e) { throw (FileUploadException) e.getCause (); } catch (final IOException e) { throw new FileUploadException (e.getMessage (), e); } finally { if (!bSuccessful) { for (final IFileItem fileItem : items) { try { fileItem.delete (); } catch (final Throwable e) { // ignore it } } } } } // ------------------------------------------------------ Protected methods /** * Retrieves the boundary from the Content-type header. * * @param contentType * The value of the content type header from which to extract the * boundary value. * @return The boundary, as a byte array. */ @Nullable protected byte [] getBoundary (final String contentType) { final ParameterParser parser = new ParameterParser (); parser.setLowerCaseNames (true); // Parameter parser can handle null input final Map params = parser.parse (contentType, new char [] { ';', ',' }); final String boundaryStr = params.get ("boundary"); if (boundaryStr == null) return null; return CharsetManager.getAsBytes (boundaryStr, CCharset.CHARSET_ISO_8859_1_OBJ); } /** * Retrieves the file name from the Content-disposition header. * * @param headers * The HTTP headers object. * @return The file name for the current encapsulation. */ protected String getFileName (final IFileItemHeaders headers) { return _getFileName (headers.getHeader (CONTENT_DISPOSITION)); } /** * Returns the given content-disposition headers file name. * * @param pContentDisposition * The content-disposition headers value. * @return The file name */ private String _getFileName (final String pContentDisposition) { String fileName = null; if (pContentDisposition != null) { final String cdl = pContentDisposition.toLowerCase (Locale.US); if (cdl.startsWith (FORM_DATA) || cdl.startsWith (ATTACHMENT)) { final ParameterParser parser = new ParameterParser (); parser.setLowerCaseNames (true); // Parameter parser can handle null input final Map params = parser.parse (pContentDisposition, ';'); if (params.containsKey ("filename")) { fileName = params.get ("filename"); if (fileName != null) { fileName = fileName.trim (); } else { // Even if there is no value, the parameter is present, // so we return an empty file name rather than no file // name. fileName = ""; } } } } return fileName; } /** * Retrieves the field name from the Content-disposition header. * * @param headers * A Map containing the HTTP request headers. * @return The field name for the current encapsulation. */ protected String getFieldName (final IFileItemHeaders headers) { return _getFieldName (headers.getHeader (CONTENT_DISPOSITION)); } /** * Returns the field name, which is given by the content-disposition header. * * @param pContentDisposition * The content-dispositions header value. * @return The field jake */ private String _getFieldName (final String pContentDisposition) { String fieldName = null; if (pContentDisposition != null && pContentDisposition.toLowerCase (Locale.US).startsWith (FORM_DATA)) { final ParameterParser parser = new ParameterParser (); parser.setLowerCaseNames (true); // Parameter parser can handle null input final Map params = parser.parse (pContentDisposition, ';'); fieldName = params.get ("name"); if (fieldName != null) { fieldName = fieldName.trim (); } } return fieldName; } /** *

* Parses the header-part and returns as key/value pairs. *

* If there are multiple headers of the same names, the name will map to a * comma-separated list containing the values. * * @param headerPart * The header-part of the current * encapsulation. * @return A Map containing the parsed HTTP request headers. */ protected IFileItemHeaders getParsedHeaders (final String headerPart) { final int len = headerPart.length (); final FileItemHeadersImpl headers = newFileItemHeaders (); int start = 0; for (;;) { int end = _parseEndOfLine (headerPart, start); if (start == end) { break; } final StringBuilder header = new StringBuilder (headerPart.substring (start, end)); start = end + 2; while (start < len) { int nonWs = start; while (nonWs < len) { final char c = headerPart.charAt (nonWs); if (c != ' ' && c != '\t') { break; } ++nonWs; } if (nonWs == start) { break; } // Continuation line found end = _parseEndOfLine (headerPart, nonWs); header.append (' ').append (headerPart.substring (nonWs, end)); start = end + 2; } _parseHeaderLine (headers, header.toString ()); } return headers; } /** * Creates a new instance of {@link IFileItemHeaders}. * * @return The new instance. */ protected FileItemHeadersImpl newFileItemHeaders () { return new FileItemHeadersImpl (); } /** * Skips bytes until the end of the current line. * * @param headerPart * The headers, which are being parsed. * @param end * Index of the last byte, which has yet been processed. * @return Index of the \r\n sequence, which indicates end of line. */ private int _parseEndOfLine (final String headerPart, final int end) { int index = end; for (;;) { final int offset = headerPart.indexOf ('\r', index); if (offset == -1 || offset + 1 >= headerPart.length ()) { throw new IllegalStateException ("Expected headers to be terminated by an empty line."); } if (headerPart.charAt (offset + 1) == '\n') { return offset; } index = offset + 1; } } /** * Reads the next header line. * * @param headers * String with all headers. * @param header * Map where to store the current header. */ private void _parseHeaderLine (final FileItemHeadersImpl headers, final String header) { final int colonOffset = header.indexOf (':'); if (colonOffset == -1) { // This header line is malformed, skip it. return; } final String headerName = header.substring (0, colonOffset).trim (); final String headerValue = header.substring (header.indexOf (':') + 1).trim (); headers.addHeader (headerName, headerValue); } /** * The iterator, which is returned by * {@link AbstractFileUploadBase#getItemIterator(IRequestContext)}. */ private class FileItemIteratorImpl implements IFileItemIterator { /** * Default implementation of {@link IFileItemStream}. */ class FileItemStreamImpl implements IFileItemStream, Closeable { /** * The file items content type. */ private final String m_sContentType; /** * The file items field name. */ private final String m_sFieldName; /** * The file items file name. */ private final String m_sName; /** * Whether the file item is a form field. */ private final boolean m_bFormField; /** * The file items input stream. */ private final InputStream m_aStream; /** * The headers, if any. */ private IFileItemHeaders m_aHeaders; /** * Creates a new instance. * * @param pName * The items file name, or null. * @param pFieldName * The items field name. * @param pContentType * The items content type, or null. * @param pFormField * Whether the item is a form field. * @param pContentLength * The items content length, if known, or -1 * @throws IOException * Creating the file item failed. */ FileItemStreamImpl (final String pName, final String pFieldName, final String pContentType, final boolean pFormField, final long pContentLength) throws IOException { m_sName = pName; m_sFieldName = pFieldName; m_sContentType = pContentType; m_bFormField = pFormField; final ItemInputStream itemStream = m_aMulti.newInputStream (); InputStream istream = itemStream; if (m_nFileSizeMax != -1) { if (pContentLength != -1 && pContentLength > m_nFileSizeMax) { final FileSizeLimitExceededException e = new FileSizeLimitExceededException ("The field " + m_sFieldName + " exceeds its maximum permitted " + " size of " + m_nFileSizeMax + " bytes.", pContentLength, m_nFileSizeMax); e.setFileName (pName); e.setFieldName (pFieldName); throw new FileUploadIOException (e); } istream = new AbstractLimitedInputStream (istream, m_nFileSizeMax) { @Override protected void raiseError (final long pSizeMax, final long pCount) throws IOException { itemStream.close (true); final FileSizeLimitExceededException e = new FileSizeLimitExceededException ("The field " + m_sFieldName + " exceeds its maximum permitted " + " size of " + pSizeMax + " bytes.", pCount, pSizeMax); e.setFieldName (m_sFieldName); e.setFileName (m_sName); throw new FileUploadIOException (e); } }; } m_aStream = istream; } /** * Returns the items content type, or null. * * @return Content type, if known, or null. */ public String getContentType () { return m_sContentType; } /** * Returns the items field name. * * @return Field name. */ public String getFieldName () { return m_sFieldName; } /** * Returns the items file name. * * @return File name, if known, or null. * @throws InvalidFileNameException * The file name contains a NUL character, which might be an * indicator of a security attack. If you intend to use the file * name anyways, catch the exception and use * InvalidFileNameException#getName(). */ public String getName () { return Streams.checkFileName (m_sName); } /** * Returns, whether this is a form field. * * @return True, if the item is a form field, otherwise false. */ public boolean isFormField () { return m_bFormField; } /** * Returns an input stream, which may be used to read the items contents. * * @return Opened input stream. * @throws IOException * An I/O error occurred. */ @Nonnull public InputStream openStream () throws IOException { if (((ICloseable) m_aStream).isClosed ()) throw new IFileItemStream.ItemSkippedException (); return m_aStream; } /** * Closes the file item. * * @throws IOException * An I/O error occurred. */ public void close () throws IOException { m_aStream.close (); } /** * Returns the file item headers. * * @return The items header object */ public IFileItemHeaders getHeaders () { return m_aHeaders; } /** * Sets the file item headers. * * @param pHeaders * The items header object */ public void setHeaders (final IFileItemHeaders pHeaders) { m_aHeaders = pHeaders; } } /** * The multi part stream to process. */ private final MultipartStream m_aMulti; /** * The notifier, which used for triggering the {@link IProgressListener}. */ private final MultipartStream.ProgressNotifier m_aNotifier; /** * The boundary, which separates the various parts. */ private final byte [] m_aBoundary; /** * The item, which we currently process. */ private FileItemStreamImpl m_aCurrentItem; /** * The current items field name. */ private String m_sCurrentFieldName; /** * Whether we are currently skipping the preamble. */ private boolean m_bSkipPreamble; /** * Whether the current item may still be read. */ private boolean m_bItemValid; /** * Whether we have seen the end of the file. */ private boolean m_bEof; /** * Creates a new instance. * * @param ctx * The request context. * @throws FileUploadException * An error occurred while parsing the request. * @throws IOException * An I/O error occurred. */ FileItemIteratorImpl (@Nonnull final IRequestContext ctx) throws FileUploadException, IOException { ValueEnforcer.notNull (ctx, "RequestContext"); final String sContentType = ctx.getContentType (); if (sContentType == null || !sContentType.toLowerCase (Locale.US).startsWith (MULTIPART)) { throw new InvalidContentTypeException ("the request doesn't contain a " + MULTIPART_FORM_DATA + " or " + MULTIPART_MIXED + " stream, content type header is " + sContentType); } InputStream input = ctx.getInputStream (); if (m_nSizeMax >= 0) { final long requestSize = ctx.getContentLength (); if (requestSize == -1) { input = new AbstractLimitedInputStream (input, m_nSizeMax) { @Override protected void raiseError (final long pSizeMax, final long pCount) throws IOException { final FileUploadException ex = new SizeLimitExceededException ("the request was rejected because" + " its size (" + pCount + ") exceeds the configured maximum" + " (" + pSizeMax + ")", pCount, pSizeMax); throw new FileUploadIOException (ex); } }; } else { if (m_nSizeMax >= 0 && requestSize > m_nSizeMax) { throw new SizeLimitExceededException ("the request was rejected because its size (" + requestSize + ") exceeds the configured maximum (" + m_nSizeMax + ")", requestSize, m_nSizeMax); } } } String charEncoding = m_sHeaderEncoding; if (charEncoding == null) { charEncoding = ctx.getCharacterEncoding (); } m_aBoundary = getBoundary (sContentType); if (m_aBoundary == null) { throw new FileUploadException ("the request was rejected because " + "no multipart boundary was found"); } // Content length may be -1 if not specified by sender final long nContentLength = ctx.getContentLength (); m_aNotifier = new MultipartStream.ProgressNotifier (m_aListener, nContentLength); m_aMulti = new MultipartStream (input, m_aBoundary, m_aNotifier); m_aMulti.setHeaderEncoding (charEncoding); m_bSkipPreamble = true; findNextItem (); } /** * Called for finding the nex item, if any. * * @return True, if an next item was found, otherwise false. * @throws IOException * An I/O error occurred. */ private boolean findNextItem () throws IOException { if (m_bEof) return false; if (m_aCurrentItem != null) { m_aCurrentItem.close (); m_aCurrentItem = null; } for (;;) { boolean nextPart; if (m_bSkipPreamble) { nextPart = m_aMulti.skipPreamble (); } else { nextPart = m_aMulti.readBoundary (); } if (!nextPart) { if (m_sCurrentFieldName == null) { // Outer multipart terminated -> No more data m_bEof = true; return false; } // Inner multipart terminated -> Return to parsing the outer m_aMulti.setBoundary (m_aBoundary); m_sCurrentFieldName = null; continue; } final IFileItemHeaders headers = getParsedHeaders (m_aMulti.readHeaders ()); if (m_sCurrentFieldName == null) { // We're parsing the outer multipart final String fieldName = getFieldName (headers); if (fieldName != null) { final String subContentType = headers.getHeader (CONTENT_TYPE); if (subContentType != null && subContentType.toLowerCase (Locale.US).startsWith (MULTIPART_MIXED)) { m_sCurrentFieldName = fieldName; // Multiple files associated with this field name final byte [] subBoundary = getBoundary (subContentType); m_aMulti.setBoundary (subBoundary); m_bSkipPreamble = true; continue; } final String fileName = getFileName (headers); m_aCurrentItem = new FileItemStreamImpl (fileName, fieldName, headers.getHeader (CONTENT_TYPE), fileName == null, getContentLength (headers)); m_aNotifier.noteItem (); m_bItemValid = true; return true; } } else { final String fileName = getFileName (headers); if (fileName != null) { m_aCurrentItem = new FileItemStreamImpl (fileName, m_sCurrentFieldName, headers.getHeader (CONTENT_TYPE), false, getContentLength (headers)); m_aNotifier.noteItem (); m_bItemValid = true; return true; } } m_aMulti.discardBodyData (); } } private long getContentLength (final IFileItemHeaders pHeaders) { return StringParser.parseLong (pHeaders.getHeader (CONTENT_LENGTH), -1L); } /** * Returns, whether another instance of {@link IFileItemStream} is * available. * * @throws FileUploadException * Parsing or processing the file item failed. * @throws IOException * Reading the file item failed. * @return True, if one or more additional file items are available, * otherwise false. */ public boolean hasNext () throws FileUploadException, IOException { if (m_bEof) return false; if (m_bItemValid) return true; return findNextItem (); } /** * Returns the next available {@link IFileItemStream}. * * @throws java.util.NoSuchElementException * No more items are available. Use {@link #hasNext()} to prevent * this exception. * @throws FileUploadException * Parsing or processing the file item failed. * @throws IOException * Reading the file item failed. * @return FileItemStream instance, which provides access to the next file * item. */ public IFileItemStream next () throws FileUploadException, IOException { if (m_bEof || (!m_bItemValid && !hasNext ())) throw new NoSuchElementException (); m_bItemValid = false; return m_aCurrentItem; } } /** * This exception is thrown for hiding an inner {@link FileUploadException} in * an {@link IOException}. */ public static class FileUploadIOException extends IOException { /** * The exceptions UID, for serializing an instance. */ private static final long serialVersionUID = -7047616958165584154L; /** * Creates a FileUploadIOException with the given cause. * * @param pCause * The exceptions cause, if any, or null. */ public FileUploadIOException (final FileUploadException pCause) { super (pCause); } } /** * Thrown to indicate that the request is not a multipart request. */ public static class InvalidContentTypeException extends FileUploadException { /** * The exceptions UID, for serializing an instance. */ private static final long serialVersionUID = -9073026332015646668L; /** * Constructs a InvalidContentTypeException with no detail * message. */ public InvalidContentTypeException () { // Nothing to do. } /** * Constructs an InvalidContentTypeException with the specified * detail message. * * @param message * The detail message. */ public InvalidContentTypeException (final String message) { super (message); } } /** * Thrown to indicate an IOException. */ public static class IOFileUploadException extends FileUploadException { /** * The exceptions UID, for serializing an instance. */ private static final long serialVersionUID = 1749796615868477269L; /** * Creates a new instance with the given cause. * * @param pMsg * The detail message. * @param pException * The exceptions cause. */ public IOFileUploadException (final String pMsg, final IOException pException) { super (pMsg, pException); } } /** * This exception is thrown, if a requests permitted size is exceeded. */ protected abstract static class SizeException extends FileUploadException { private static final long serialVersionUID = -8776225574705254126L; /** * The actual size of the request. */ private final long m_nActual; /** * The maximum permitted size of the request. */ private final long m_nPermitted; /** * Creates a new instance. * * @param message * The detail message. * @param actual * The actual number of bytes in the request. * @param permitted * The requests size limit, in bytes. */ protected SizeException (final String message, final long actual, final long permitted) { super (message); m_nActual = actual; m_nPermitted = permitted; } /** * Retrieves the actual size of the request. * * @return The actual size of the request. */ public long getActualSize () { return m_nActual; } /** * Retrieves the permitted size of the request. * * @return The permitted size of the request. */ public long getPermittedSize () { return m_nPermitted; } } /** * Thrown to indicate that the request size exceeds the configured maximum. */ public static class SizeLimitExceededException extends SizeException { /** * The exceptions UID, for serializing an instance. */ private static final long serialVersionUID = -2474893167098052828L; /** * Constructs a SizeExceededException with the specified detail * message, and actual and permitted sizes. * * @param message * The detail message. * @param actual * The actual request size. * @param permitted * The maximum permitted request size. */ public SizeLimitExceededException (final String message, final long actual, final long permitted) { super (message, actual, permitted); } } /** * Thrown to indicate that A files size exceeds the configured maximum. */ public static class FileSizeLimitExceededException extends SizeException { /** * The exceptions UID, for serializing an instance. */ private static final long serialVersionUID = 8150776562029630058L; /** * File name of the item, which caused the exception. */ private String m_sFileName; /** * Field name of the item, which caused the exception. */ private String m_sFieldName; /** * Constructs a SizeExceededException with the specified detail * message, and actual and permitted sizes. * * @param message * The detail message. * @param actual * The actual request size. * @param permitted * The maximum permitted request size. */ public FileSizeLimitExceededException (final String message, final long actual, final long permitted) { super (message, actual, permitted); } /** * Returns the file name of the item, which caused the exception. * * @return File name, if known, or null. */ public String getFileName () { return m_sFileName; } /** * Sets the file name of the item, which caused the exception. */ public void setFileName (final String pFileName) { m_sFileName = pFileName; } /** * Returns the field name of the item, which caused the exception. * * @return Field name, if known, or null. */ public String getFieldName () { return m_sFieldName; } /** * Sets the field name of the item, which caused the exception. */ public void setFieldName (final String pFieldName) { m_sFieldName = pFieldName; } } /** * Returns the progress listener. * * @return The progress listener, if any, or null. */ public IProgressListener getProgressListener () { return m_aListener; } /** * Sets the progress listener. * * @param pListener * The progress listener, if any. Defaults to null. */ public void setProgressListener (final IProgressListener pListener) { m_aListener = pListener; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy