1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.controller.impl;
17
18 import static org.seasar.cubby.internal.util.LogMessages.format;
19
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28
29 import javax.servlet.http.HttpServletRequest;
30
31 import org.apache.commons.fileupload.FileItem;
32 import org.apache.commons.fileupload.FileUpload;
33 import org.apache.commons.fileupload.FileUploadBase;
34 import org.apache.commons.fileupload.FileUploadException;
35 import org.apache.commons.fileupload.RequestContext;
36 import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
37 import org.seasar.cubby.controller.RequestParseException;
38 import org.seasar.cubby.controller.RequestParser;
39 import org.seasar.cubby.internal.util.StringUtils;
40 import org.seasar.cubby.spi.ContainerProvider;
41 import org.seasar.cubby.spi.ProviderFactory;
42 import org.seasar.cubby.spi.container.Container;
43 import org.seasar.cubby.spi.container.LookupException;
44
45
46
47
48
49
50
51
52
53
54
55 public class MultipartRequestParser implements RequestParser {
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 @SuppressWarnings("unchecked")
84 public Map<String, Object[]> getParameterMap(
85 final HttpServletRequest request) {
86 final Map<String, Object[]> parameterMap = new HashMap<String, Object[]>(
87 request.getParameterMap());
88 final Container container = ProviderFactory
89 .get(ContainerProvider.class).getContainer();
90 try {
91 final RequestContext requestContext = container
92 .lookup(RequestContext.class);
93 final FileUpload fileUpload = container.lookup(FileUpload.class);
94 final Map<String, Object[]> multipartParameterMap = getMultipartParameterMap(
95 fileUpload, requestContext);
96 parameterMap.putAll(multipartParameterMap);
97 return parameterMap;
98 } catch (final LookupException e) {
99 throw new IllegalStateException(e);
100 }
101 }
102
103 @SuppressWarnings("unchecked")
104 Map<String, Object[]> getMultipartParameterMap(final FileUpload fileUpload,
105 final RequestContext requestContext) {
106 try {
107 final String encoding = requestContext.getCharacterEncoding();
108 fileUpload.setHeaderEncoding(encoding);
109 final List<FileItem> items = fileUpload
110 .parseRequest(requestContext);
111
112
113 final Map<String, Object[]> parameterMap = toParameterMap(encoding,
114 items);
115
116 return parameterMap;
117 } catch (final FileUploadException e) {
118 final String messageCode;
119 final Object[] args;
120 if (e instanceof SizeLimitExceededException) {
121 final SizeLimitExceededException sle = (SizeLimitExceededException) e;
122 messageCode = "ECUB0202";
123 args = new Object[] { sle.getPermittedSize(),
124 sle.getActualSize() };
125 } else {
126 messageCode = "ECUB0201";
127 args = new Object[] { e };
128 }
129 throw new RequestParseException(format(messageCode, args), e);
130 } catch (final IOException e) {
131 throw new RequestParseException(e);
132 }
133 }
134
135 Map<String, Object[]> toParameterMap(final String encoding,
136 final List<FileItem> items) throws UnsupportedEncodingException {
137 final Map<String, List<Object>> valueListParameterMap = new LinkedHashMap<String, List<Object>>();
138 for (final FileItem item : items) {
139 final Object value;
140 if (item.isFormField()) {
141 value = item.getString(encoding);
142 } else {
143 if (StringUtils.isEmpty(item.getName()) || item.getSize() == 0) {
144
145 value = null;
146 } else {
147 value = item;
148 }
149 }
150 final List<Object> values;
151 if (valueListParameterMap.containsKey(item.getFieldName())) {
152 values = valueListParameterMap.get(item.getFieldName());
153 } else {
154 values = new ArrayList<Object>();
155 valueListParameterMap.put(item.getFieldName(), values);
156 }
157 values.add(value);
158 }
159
160 final Map<String, Object[]> parameterMap = fromValueListMapToValueArrayMap(valueListParameterMap);
161 return parameterMap;
162 }
163
164 Map<String, Object[]> fromValueListMapToValueArrayMap(
165 final Map<String, List<Object>> valueListMap) {
166
167 final Map<String, Object[]> parameterMap = new HashMap<String, Object[]>();
168 for (final Entry<String, List<Object>> entry : valueListMap.entrySet()) {
169 final List<Object> values = entry.getValue();
170 final Object[] valueArray;
171 if (values.get(0) instanceof String) {
172 valueArray = new String[values.size()];
173 } else {
174 valueArray = new FileItem[values.size()];
175 }
176 parameterMap.put(entry.getKey(), values.toArray(valueArray));
177 }
178 return parameterMap;
179 }
180
181
182
183
184
185
186
187
188
189
190 public boolean isParsable(final HttpServletRequest request) {
191 final Container container = ProviderFactory
192 .get(ContainerProvider.class).getContainer();
193 try {
194 final RequestContext requestContext = container
195 .lookup(RequestContext.class);
196 return FileUploadBase.isMultipartContent(requestContext);
197 } catch (final LookupException e) {
198 return false;
199 }
200 }
201
202 }