View Javadoc

1   /*
2    * $Id: MultipartRequestFilter.java 269 2005-08-10 17:49:22Z josem $
3    *
4    * Tarsis
5    * Copyright (C) 2002 Talika Open Source Group
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   *
21   */
22  
23  package org.talika.tarsis.filters.upload;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.util.HashMap;
28  import java.util.LinkedList;
29  
30  import javax.servlet.FilterChain;
31  import javax.servlet.FilterConfig;
32  import javax.servlet.ServletContext;
33  import javax.servlet.ServletException;
34  import javax.servlet.ServletRequest;
35  import javax.servlet.ServletResponse;
36  import javax.servlet.http.HttpServletRequest;
37  
38  import org.talika.tarsis.filters.AbstractFilter;
39  
40  /**
41   * Multipart filter process client's multipart/form-data requests.
42   *
43   * @author  Jose M. Palomar
44   * @version $Revision: 269 $
45   *
46   * @todo Add maxSize and bufferSize as filter parameters.
47   */
48  
49  public final class MultipartRequestFilter extends AbstractFilter {
50  
51      // Constants
52      /**
53       * Content multipart/form-data type.
54       */
55      private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data";
56  
57      // Fields
58      /**
59       * Max file size.
60       */
61      private int maxSize = 1 * 1024 * 1024;
62  
63      /**
64       * Buffer size.
65       */
66      private int bufferSize = 4 * 1024;
67  
68      /**
69       * Temporal directory.
70       */
71      private String tmpDir;
72  
73      // Methods
74      /**
75       * Called by the web container to indicate to a filter that it is being placed
76       * into service.<br>
77       * <br>
78       * Initialization consits in:
79       * <ol>
80       * <li>Calling super <code>int</code> method.</li>
81       * <li>Initializing temporal directory.</li>
82       * </ol>
83       *
84       * @param filterConfig FilterConfig filter configutarion.
85       * @throws ServletException if an exception has occurred that interferes with the
86       * filter's normal operation
87       * @see javax.servlet.Filter#init(FilterConfig)
88       */
89      public void init(FilterConfig filterConfig) throws ServletException {
90          super.init(filterConfig);
91  
92          ServletContext context = filterConfig.getServletContext();
93          try {
94              tmpDir = (String) context.getAttribute("javax.servlet.context.tempdir");
95          }
96          catch (ClassCastException cce) {
97              tmpDir = ((File) context.getAttribute("javax.servlet.context.tempdir")).getAbsolutePath();
98          }
99  
100         if (tmpDir == null) {
101             tmpDir = System.getProperty("java.io.tmpdir");
102         }
103 
104         if (getLogger().isDebugEnabled()) {
105             getLogger().logDebug(getFilterConfig().getFilterName() + ": Temp directory " + tmpDir);
106         }
107 
108     }
109 
110     /**
111      * Process client's requests of type multipart/form-data.<br>
112      * <br>
113      * Procesing consists in obtaining parameters and uploading files to temporal
114      * directory.<br>
115      * When request is processed all obtained elements are encapsulated in a
116      * <code>MultipartRequestWrapper</code> that is passed to next filter in
117      * chain.<br>
118      * <code>MultipartRequestWrapper</code> makes multipart requests appears as a
119      * normal request to the rest of elements in filter chain.
120      *
121      * @param servletRequest ServletRequest the <code>ServletRequest</code> object
122      * that contains the client's request.
123      * @param servletResponse ServletResponse the <code>ServletResponse</code> object
124      * that contains the servlet's response.
125      * @param filterChain FilterChain invocation chain of filtered request.
126      * @throws IOException if an input or output exception occurs
127      * @throws ServletException if an exception has occurred that interferes with the
128      * filter's normal operation
129      * @see javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
130      */
131     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
132     FilterChain filterChain)
133     throws IOException, ServletException {
134 
135         if (getLogger().isDebugEnabled()) {
136             getLogger().logDebug(getFilterConfig().getFilterName() + ": invoked");
137         }
138 
139         if ((servletRequest.getContentType() != null) &&
140            (servletRequest.getContentType().startsWith(CONTENT_TYPE_MULTIPART))) {
141 
142             HashMap parameters = new HashMap();
143             HashMap files = new HashMap();
144             try {
145 
146                 MultipartIterator iterator = new MultipartIterator(servletRequest,
147                                                                    maxSize,
148                                                                    bufferSize,
149                                                                    tmpDir);
150                 while (iterator.hasNext()) {
151                     MultipartElement element = (MultipartElement) iterator.next();
152                     if (element.getType() == MultipartElement.TEXT) {
153                         LinkedList values = (LinkedList) parameters.get(element.getName());
154                         if (values == null) {
155                             values = new LinkedList();
156                             parameters.put(element.getName(), values);
157                         }
158                         values.add(element.getValue());
159                     }
160                     else if (element.getType() == MultipartElement.FILE) {
161                         files.put(element.getName(), element.getValue());
162                     }
163                 }
164 
165             }
166             catch (Throwable t) {
167                 throw new ServletException(t);
168             }
169 
170             filterChain.doFilter(
171                     new MultipartRequestWrapper(((HttpServletRequest) servletRequest),
172                                                 parameters, files),
173                                  servletResponse);
174 
175         }
176         else {
177             filterChain.doFilter(servletRequest, servletResponse);
178         }
179     }
180 
181 }