001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.multipart.commons;
018:
019: import java.util.List;
020:
021: import javax.servlet.ServletContext;
022: import javax.servlet.http.HttpServletRequest;
023:
024: import org.apache.commons.fileupload.FileItemFactory;
025: import org.apache.commons.fileupload.FileUpload;
026: import org.apache.commons.fileupload.FileUploadBase;
027: import org.apache.commons.fileupload.FileUploadException;
028: import org.apache.commons.fileupload.servlet.ServletFileUpload;
029: import org.apache.commons.fileupload.servlet.ServletRequestContext;
030:
031: import org.springframework.web.context.ServletContextAware;
032: import org.springframework.web.multipart.MaxUploadSizeExceededException;
033: import org.springframework.web.multipart.MultipartException;
034: import org.springframework.web.multipart.MultipartHttpServletRequest;
035: import org.springframework.web.multipart.MultipartResolver;
036: import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
037: import org.springframework.web.util.WebUtils;
038:
039: /**
040: * Servlet-based {@link org.springframework.web.multipart.MultipartResolver} implementation
041: * for <a href="http://jakarta.apache.org/commons/fileupload">Jakarta Commons FileUpload</a>
042: * 1.1 or higher.
043: *
044: * <p>Provides maxUploadSize, maxInMemorySize, and defaultEncoding settings as
045: * bean properties (inherited from CommonsFileUploadSupport). See respective
046: * ServletFileUpload / DiskFileItemFactory properties (sizeMax, sizeThreshold,
047: * headerEncoding) for details in terms of defaults and accepted values.
048: *
049: * <p>Saves temporary files to the servlet container's temporary directory.
050: * Needs to be initialized <i>either</i> by an application context <i>or</i>
051: * via the constructor that takes a ServletContext (for standalone usage).
052: *
053: * @author Trevor D. Cook
054: * @author Juergen Hoeller
055: * @since 29.09.2003
056: * @see #CommonsMultipartResolver(ServletContext)
057: * @see #setResolveLazily
058: * @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver
059: * @see org.apache.commons.fileupload.servlet.ServletFileUpload
060: * @see org.apache.commons.fileupload.disk.DiskFileItemFactory
061: */
062: public class CommonsMultipartResolver extends CommonsFileUploadSupport
063: implements MultipartResolver, ServletContextAware {
064:
065: private boolean resolveLazily = false;
066:
067: /**
068: * Constructor for use as bean. Determines the servlet container's
069: * temporary directory via the ServletContext passed in as through the
070: * ServletContextAware interface (typically by a WebApplicationContext).
071: * @see #setServletContext
072: * @see org.springframework.web.context.ServletContextAware
073: * @see org.springframework.web.context.WebApplicationContext
074: */
075: public CommonsMultipartResolver() {
076: super ();
077: }
078:
079: /**
080: * Constructor for standalone usage. Determines the servlet container's
081: * temporary directory via the given ServletContext.
082: * @param servletContext the ServletContext to use
083: */
084: public CommonsMultipartResolver(ServletContext servletContext) {
085: this ();
086: setServletContext(servletContext);
087: }
088:
089: /**
090: * Set whether to resolve the multipart request lazily at the time of
091: * file or parameter access.
092: * <p>Default is "false", resolving the multipart elements immediately, throwing
093: * corresponding exceptions at the time of the {@link #resolveMultipart} call.
094: * Switch this to "true" for lazy multipart parsing, throwing parse exceptions
095: * once the application attempts to obtain multipart files or parameters.
096: */
097: public void setResolveLazily(boolean resolveLazily) {
098: this .resolveLazily = resolveLazily;
099: }
100:
101: /**
102: * Initialize the underlying <code>org.apache.commons.fileupload.servlet.ServletFileUpload</code>
103: * instance. Can be overridden to use a custom subclass, e.g. for testing purposes.
104: * @param fileItemFactory the Commons FileItemFactory to use
105: * @return the new ServletFileUpload instance
106: */
107: protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
108: return new ServletFileUpload(fileItemFactory);
109: }
110:
111: public void setServletContext(ServletContext servletContext) {
112: if (!isUploadTempDirSpecified()) {
113: getFileItemFactory().setRepository(
114: WebUtils.getTempDir(servletContext));
115: }
116: }
117:
118: public boolean isMultipart(HttpServletRequest request) {
119: return ServletFileUpload
120: .isMultipartContent(new ServletRequestContext(request));
121: }
122:
123: public MultipartHttpServletRequest resolveMultipart(
124: final HttpServletRequest request) throws MultipartException {
125: if (this .resolveLazily) {
126: return new DefaultMultipartHttpServletRequest(request) {
127: protected void initializeMultipart() {
128: MultipartParsingResult parsingResult = parseRequest(request);
129: setMultipartFiles(parsingResult.getMultipartFiles());
130: setMultipartParameters(parsingResult
131: .getMultipartParameters());
132: }
133: };
134: } else {
135: MultipartParsingResult parsingResult = parseRequest(request);
136: return new DefaultMultipartHttpServletRequest(request,
137: parsingResult.getMultipartFiles(), parsingResult
138: .getMultipartParameters());
139: }
140: }
141:
142: /**
143: * Parse the given servlet request, resolving its multipart elements.
144: * @param request the request to parse
145: * @return the parsing result
146: * @throws MultipartException if multipart resolution failed.
147: */
148: protected MultipartParsingResult parseRequest(
149: HttpServletRequest request) throws MultipartException {
150: String encoding = determineEncoding(request);
151: FileUpload fileUpload = prepareFileUpload(encoding);
152: try {
153: List fileItems = ((ServletFileUpload) fileUpload)
154: .parseRequest(request);
155: return parseFileItems(fileItems, encoding);
156: } catch (FileUploadBase.SizeLimitExceededException ex) {
157: throw new MaxUploadSizeExceededException(fileUpload
158: .getSizeMax(), ex);
159: } catch (FileUploadException ex) {
160: throw new MultipartException(
161: "Could not parse multipart servlet request", ex);
162: }
163: }
164:
165: /**
166: * Determine the encoding for the given request.
167: * Can be overridden in subclasses.
168: * <p>The default implementation checks the request encoding,
169: * falling back to the default encoding specified for this resolver.
170: * @param request current HTTP request
171: * @return the encoding for the request (never <code>null</code>)
172: * @see javax.servlet.ServletRequest#getCharacterEncoding
173: * @see #setDefaultEncoding
174: */
175: protected String determineEncoding(HttpServletRequest request) {
176: String encoding = request.getCharacterEncoding();
177: if (encoding == null) {
178: encoding = getDefaultEncoding();
179: }
180: return encoding;
181: }
182:
183: public void cleanupMultipart(MultipartHttpServletRequest request) {
184: cleanupFileItems(request.getFileMap().values());
185: }
186:
187: }
|