
net.sourceforge.stripes.controller.multipart.CommonsMultipartWrapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stripes Show documentation
Show all versions of stripes Show documentation
Stripes web framework jar, including tag library.
/* Copyright 2005-2006 Tim Fennell
*
* 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 net.sourceforge.stripes.controller.multipart;
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.controller.FileUploadLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.FileUploadBase;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Pattern;
/**
* An implementation of MultipartWrapper that uses Jakarta Commons FileUpload
* (from apache) to parse the request parts. This implementation requires that
* both commons-fileupload and commons-io be present in the classpath. While
* this implementation does introduce additional dependencies, it's licensing
* (ASL 2.0) is significantly less restrictive than the licensing for COS - the
* other alternative provided by Stripes.
*
* @author Tim Fennell
* @since Stripes 1.4
*/
public class CommonsMultipartWrapper implements MultipartWrapper {
private static final Pattern WINDOWS_PATH_PREFIX_PATTERN = Pattern.compile("(?i:^[A-Z]:\\\\)");
/**
* Ensure this class will not load unless Commons FileUpload is on the
* classpath.
*/
static {
FileUploadException.class.getName();
}
private Map files = new HashMap();
private Map parameters = new HashMap();
private String charset;
public void build(HttpServletRequest request) {
throw new UnsupportedOperationException("Multipart wrappers cannot use this build() method. They must use the one in the build() interface.");
}
/**
* Pseudo-constructor that allows the class to perform any initialization
* necessary.
*
* @param request an HttpServletRequest that has a content-type of
* multipart.
* @param tempDir a File representing the temporary directory that can be
* used to store file parts as they are uploaded if this is desirable
* @param maxPostSize the size in bytes beyond which the request should not
* be read, and a FileUploadLimitExceeded exception should be thrown
* @throws IOException if a problem occurs processing the request of storing
* temporary files
* @throws FileUploadLimitExceededException if the POST content is longer
* than the maxPostSize supplied.
*/
@SuppressWarnings("unchecked")
public void build(HttpServletRequest request, File tempDir, long maxPostSize)
throws IOException, FileUploadLimitExceededException {
try {
this.charset = request.getCharacterEncoding();
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(tempDir);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(maxPostSize);
List items = upload.parseRequest(request);
Map> params = new HashMap>();
for (FileItem item : items) {
// If it's a form field, add the string value to the list
if (item.isFormField()) {
List values = params.get(item.getFieldName());
if (values == null) {
values = new ArrayList();
params.put(item.getFieldName(), values);
}
values.add(charset == null ? item.getString() : item.getString(charset));
} // Else store the file param
else {
files.put(item.getFieldName(), item);
}
}
// Now convert them down into the usual map of String->String[]
for (Map.Entry> entry : params.entrySet()) {
List values = entry.getValue();
this.parameters.put(entry.getKey(), values.toArray(new String[values.size()]));
}
} catch (FileUploadBase.SizeLimitExceededException slee) {
throw new FileUploadLimitExceededException(maxPostSize, slee.getActualSize());
} catch (FileUploadException fue) {
IOException ioe = new IOException("Could not parse and cache file upload data.");
ioe.initCause(fue);
throw ioe;
}
}
/**
* Fetches the names of all non-file parameters in the request. Directly
* analogous to the method of the same name in HttpServletRequest when the
* request is non-multipart.
*
* @return an Enumeration of all non-file parameter names in the request
*/
public Enumeration getParameterNames() {
return new IteratorEnumeration(this.parameters.keySet().iterator());
}
/**
* Fetches all values of a specific parameter in the request. To simulate
* the HTTP request style, the array should be null for non-present
* parameters, and values in the array should never be null - the empty
* String should be used when there is value.
*
* @param name the name of the request parameter
* @return an array of non-null parameters or null
*/
public String[] getParameterValues(String name) {
return this.parameters.get(name);
}
/**
* Fetches the names of all file parameters in the request. Note that these
* are not the file names, but the names given to the form fields in which
* the files are specified.
*
* @return the names of all file parameters in the request.
*/
public Enumeration getFileParameterNames() {
return new IteratorEnumeration(this.files.keySet().iterator());
}
/**
* Responsible for constructing a FileBean object for the named file
* parameter. If there is no file parameter with the specified name this
* method should return null.
*
* @param name the name of the file parameter
* @return a FileBean object wrapping the uploaded file
*/
public FileBean getFileParameterValue(String name) {
final FileItem item = this.files.get(name);
if (item == null
|| ((item.getName() == null || item.getName().length() == 0) && item.getSize() == 0)) {
return null;
} else {
// Attempt to ensure the file name is just the basename with no path included
String filename = item.getName();
int index;
if (WINDOWS_PATH_PREFIX_PATTERN.matcher(filename).find()) {
index = filename.lastIndexOf('\\');
} else {
index = filename.lastIndexOf('/');
}
if (index >= 0 && index + 1 < filename.length() - 1) {
filename = filename.substring(index + 1);
}
// Use an anonymous inner subclass of FileBean that overrides all the
// methods that rely on having a File present, to use the FileItem
// created by commons upload instead.
return new FileBean(null, item.getContentType(), filename, this.charset) {
@Override
public long getSize() {
return item.getSize();
}
@Override
public InputStream getInputStream() throws IOException {
return item.getInputStream();
}
@Override
public void save(File toFile) throws IOException {
try {
item.write(toFile);
delete();
} catch (Exception e) {
if (e instanceof IOException) {
throw (IOException) e;
} else {
IOException ioe = new IOException("Problem saving uploaded file.");
ioe.initCause(e);
throw ioe;
}
}
}
@Override
public void delete() throws IOException {
item.delete();
}
};
}
}
/**
* Little helper class to create an enumeration as per the interface.
*/
private static class IteratorEnumeration implements Enumeration {
Iterator iterator;
/**
* Constructs an enumeration that consumes from the underlying iterator.
*/
IteratorEnumeration(Iterator iterator) {
this.iterator = iterator;
}
/**
* Returns true if more elements can be consumed, false otherwise.
*/
public boolean hasMoreElements() {
return this.iterator.hasNext();
}
/**
* Gets the next element out of the iterator.
*/
public String nextElement() {
return this.iterator.next();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy