1 package com.imcode.util;
2
3 import org.apache.commons.collections.MultiHashMap;
4 import org.apache.commons.collections.MultiMap;
5 import org.apache.commons.collections.iterators.IteratorEnumeration;
6 import org.apache.commons.fileupload.*;
7 import org.apache.commons.lang.UnhandledException;
8 import org.apache.oro.text.perl.Perl5Util;
9
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletRequestWrapper;
12 import javax.activation.DataSource;
13 import java.io.*;
14 import java.util.*;
15
16 /***
17 * Extends HttpServletRequest for RFC 1867 form based file upload support from Jakarta Commons-FileUpload
18 */
19 public class MultipartHttpServletRequest extends HttpServletRequestWrapper {
20 static final String CHARSET_ISO_8859_1 = "ISO-8859-1";
21
22 private MultiMap fileItemMap;
23
24 public MultipartHttpServletRequest( HttpServletRequest request ) throws IOException {
25 this(request,-1) ;
26 }
27
28 /***
29 Constructor used to specify a size limit for uploads.
30
31 @param sizeLimit The maximum size for an upload, in bytes.
32 **/
33 public MultipartHttpServletRequest( HttpServletRequest request, long sizeLimit ) throws IOException {
34 super( request );
35 if ( FileUploadBase.isMultipartContent( request ) ) {
36 FileUpload fileUpload = new FileUpload( new DefaultFileItemFactory() );
37 fileUpload.setSizeMax( sizeLimit );
38 List fileItems ;
39 try {
40 fileItems = fileUpload.parseRequest( request );
41 } catch ( FileUploadException e ) {
42 throw new IOException( e.getMessage() );
43 }
44 fileItemMap = new MultiHashMap();
45 for ( Iterator iterator = fileItems.iterator(); iterator.hasNext(); ) {
46 FileItem fileItem = new BaseNameFileItem( (FileItem)iterator.next() );
47 fileItemMap.put( fileItem.getFieldName(), fileItem );
48 }
49 }
50 }
51
52 public String getParameter( String key ) {
53 String[] parameterValues = getParameterValues( key );
54 if ( null != parameterValues && parameterValues.length > 0 ) {
55 return parameterValues[0];
56 }
57 return null;
58 }
59
60 public DataSourceFileItem getParameterFileItem( String key ) {
61 DataSourceFileItem[] parameterValues = getParameterFileItems( key );
62 if ( null != parameterValues && parameterValues.length > 0 ) {
63 return parameterValues[0];
64 }
65 return null;
66 }
67
68 public DataSourceFileItem[] getParameterFileItems( String key ) {
69 if ( null == fileItemMap ) {
70 return null;
71 }
72 final Collection parameterFileItems = (Collection)fileItemMap.get( key );
73 if ( null == parameterFileItems ) {
74 return null;
75 }
76 return (DataSourceFileItem[])parameterFileItems.toArray( new DataSourceFileItem[parameterFileItems.size()] );
77 }
78
79 public Map getParameterMap() {
80 Map map = super.getParameterMap() ;
81 if ( null != fileItemMap ) {
82 map = new HashMap( map );
83 Set fileItemKeys = fileItemMap.keySet();
84 for ( Iterator iterator = fileItemKeys.iterator(); iterator.hasNext(); ) {
85 String key = (String)iterator.next();
86 map.put( key, getParameterValues( key ) );
87 }
88 }
89 return map;
90 }
91
92 public Enumeration getParameterNames() {
93 Enumeration superParameterNames = super.getParameterNames();
94 Set parameterNames = new HashSet();
95 while ( superParameterNames.hasMoreElements() ) {
96 parameterNames.add( superParameterNames.nextElement() );
97 }
98 if (null != fileItemMap) {
99 parameterNames.addAll( fileItemMap.keySet() );
100 }
101 return new IteratorEnumeration( parameterNames.iterator() );
102 }
103
104 public String[] getParameterValues( String key ) {
105 if ( null != fileItemMap ) {
106 List parameterValues = new ArrayList();
107 Collection fileItems = (Collection)fileItemMap.get( key );
108 if ( null == fileItems ) {
109 return null;
110 }
111 for ( Iterator iterator = fileItems.iterator(); iterator.hasNext(); ) {
112 FileItem fileItem = (FileItem)iterator.next();
113 String contentType = fileItem.getContentType();
114 parameterValues.add( getStringFromBytesWithContentType( fileItem.get(), contentType ) );
115 }
116 return (String[])parameterValues.toArray( new String[parameterValues.size()] );
117 }
118 return super.getParameterValues( key );
119 }
120
121 static String getStringFromBytesWithContentType( byte[] bytes, String contentType ) {
122 try {
123 return new String( bytes, getCharsetFromContentType(contentType) );
124 } catch ( UnsupportedEncodingException ignored ) {
125 }
126 try {
127 return new String( bytes, CHARSET_ISO_8859_1 );
128 } catch ( UnsupportedEncodingException never ) {
129 throw new UnhandledException(never);
130 }
131 }
132
133 static String getCharsetFromContentType(String contentType) {
134 String charset = CHARSET_ISO_8859_1;
135 if ( null != contentType ) {
136 Perl5Util perl5Util = new Perl5Util();
137 if ( perl5Util.match( "///bcharset=\"?(//S+?)\"?(?:$|;|//s)/", contentType ) ) {
138 charset = perl5Util.group( 1 );
139 }
140 }
141 return charset ;
142 }
143
144 public interface DataSourceFileItem extends FileItem, DataSource {
145
146 }
147
148 private class BaseNameFileItem extends FileItemWrapper {
149
150 private BaseNameFileItem( FileItem fileItem ) {
151 super( fileItem );
152 }
153
154 public String getName() {
155 String filename = fileItem.getName();
156 if ( null != filename ) {
157 filename = filename.substring( filename.lastIndexOf( '/' ) + 1 );
158 filename = filename.substring( filename.lastIndexOf( '//' ) + 1 );
159 }
160 return filename;
161 }
162 }
163
164 private class FileItemWrapper implements DataSourceFileItem {
165
166 FileItem fileItem;
167
168 private FileItemWrapper( FileItem fileItem ) {
169 this.fileItem = fileItem;
170 }
171
172 public String getContentType() {
173 return fileItem.getContentType();
174 }
175
176 public String getFieldName() {
177 return fileItem.getFieldName();
178 }
179
180 public void setFieldName( String s ) {
181 fileItem.setFieldName( s );
182 }
183
184 public InputStream getInputStream() throws IOException {
185 return fileItem.getInputStream();
186 }
187
188 public String getName() {
189 return fileItem.getName();
190 }
191
192 public OutputStream getOutputStream() throws IOException {
193 return fileItem.getOutputStream();
194 }
195
196 public long getSize() {
197 return fileItem.getSize();
198 }
199
200 public String getString() {
201 return fileItem.getString();
202 }
203
204 public boolean isFormField() {
205 return fileItem.isFormField();
206 }
207
208 public void setFormField( boolean b ) {
209 fileItem.setFormField( b );
210 }
211
212 public boolean isInMemory() {
213 return fileItem.isInMemory();
214 }
215
216 public byte[] get() {
217 return fileItem.get();
218 }
219
220 public void delete() {
221 fileItem.delete();
222 }
223
224 public String getString( String s ) throws UnsupportedEncodingException {
225 return fileItem.getString( s );
226 }
227
228 public void write( File file ) throws Exception {
229 fileItem.write( file );
230 }
231 }
232
233 }