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