##### Coverage Report - org.seasar.cubby.internal.controller.impl.CubbyHttpServletRequestWrapper

Classes in this File | Line Coverage | Branch Coverage | Complexity
CubbyHttpServletRequestWrapper |
95% | 70/73
89% | 34/38
| 3.5;3.5

1 |  |
     /*
2 |  |
      * Copyright 2004-2009 the Seasar Foundation and the Others.
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 |  |
      * either express or implied. See the License for the specific language
14 |  |
      * governing permissions and limitations under the License.
15 |  |
      */
16 |  |
     package org.seasar.cubby.internal.controller.impl;
17 |  |
18 |  |
     import static org.seasar.cubby.CubbyConstants.ATTR_ACTION;
19 |  |
     import static org.seasar.cubby.CubbyConstants.ATTR_CONTEXT_PATH;
20 |  |
     import static org.seasar.cubby.CubbyConstants.ATTR_FORM_WRAPPER_FACTORY;
21 |  |
     import static org.seasar.cubby.CubbyConstants.ATTR_MESSAGES;
22 |  |
23 |  |
     import java.util.ArrayList;
24 |  |
     import java.util.Enumeration;
25 |  |
     import java.util.HashMap;
26 |  |
     import java.util.HashSet;
27 |  |
     import java.util.List;
28 |  |
     import java.util.Map;
29 |  |
     import java.util.Set;
30 |  |
     import java.util.Map.Entry;
31 |  |
32 |  |
     import javax.servlet.http.HttpServletRequest;
33 |  |
     import javax.servlet.http.HttpServletRequestWrapper;
34 |  |
35 |  |
     import org.seasar.cubby.CubbyConstants;
36 |  |
     import org.seasar.cubby.controller.FormWrapperFactory;
37 |  |
     import org.seasar.cubby.internal.controller.ThreadContext;
38 |  |
     import org.seasar.cubby.internal.util.IteratorEnumeration;
39 |  |
     import org.seasar.cubby.spi.beans.Attribute;
40 |  |
     import org.seasar.cubby.spi.beans.BeanDesc;
41 |  |
     import org.seasar.cubby.spi.beans.BeanDescFactory;
42 |  |
43 |  |
     /**
44 |  |
      * 特別な属性を取得するためにサーブレットへの要求をラップします。
45 |  |
      * <p>
46 |  |
      * <ul>
47 |  |
      * <li>{@link #getAttribute(String)}</li>
48 |  |
      * <li>{@link #getAttributeNames()}</li>
49 |  |
      * </ul>
50 |  |
      * 上記メソッドでは、ラップされた要求の属性に加えて以下のような属性を使用することができます。
51 |  |
      * <table>
52 |  |
      * <thead>
53 |  |
      * <tr>
54 |  |
      * <th>属性名</th>
55 |  |
      * <th>値</th>
56 |  |
      * <th>型</th>
57 |  |
      * </tr>
58 |  |
      * </thead><tbody>
59 |  |
      * <tr>
60 |  |
      * <td>{@link CubbyConstants#ATTR_CONTEXT_PATH}</td>
61 |  |
      * <td>コンテキストパス</td>
62 |  |
      * <td>{@link String}</td>
63 |  |
      * </tr>
64 |  |
      * <tr>
65 |  |
      * <td>{@link CubbyConstants#ATTR_ACTION}</td>
66 |  |
      * <td>アクション</td>
67 |  |
      * <td>{@link org.seasar.cubby.action.Action}</td>
68 |  |
      * </tr>
69 |  |
      * <tr>
70 |  |
      * <td>{@link CubbyConstants#ATTR_MESSAGES}</td>
71 |  |
      * <td>メッセージリソース</td>
72 |  |
      * <td>{@link java.util.Map}</td>
73 |  |
      * </tr>
74 |  |
      * <tr>
75 |  |
      * <td>{@link CubbyConstants#ATTR_FORM_WRAPPER_FACTORY}</td>
76 |  |
      * <td>フォームオブジェクトのラッパーファクトリ</td>
77 |  |
      * <td>{@link FormWrapperFactory}</td>
78 |  |
      * </tr>
79 |  |
      * <tr>
80 |  |
      * <td>アクションのプロパティ名</td>
81 |  |
      * <td>アクションのプロパティ値</td>
82 |  |
      * <td>任意</td>
83 |  |
      * </tr>
84 |  |
      * </table>
85 |  |
      * これらの属性は通常の属性よりも優先されるのでご注意ください。
86 |  |
      * </p>
87 |  |
      * <p>
88 |  |
      * また、以下の要求パラメータに関するメソッドは、通常の要求パラメータに加え、URI パラメータも対象として処理します。
89 |  |
      * <ul>
90 |  |
      * <li>{@link #getParameter(String)}</li>
91 |  |
      * <li>{@link #getParameterMap()}</li>
92 |  |
      * <li>{@link #getParameterNames()}</li>
93 |  |
      * <li>{@link #getParameterValues(String)}</li>
94 |  |
      * </ul>
95 |  |
      * </p>
96 |  |
      *
97 |  |
      * @author baba
98 |  |
      */
99 |  |
     class CubbyHttpServletRequestWrapper extends HttpServletRequestWrapper {
100 |  |
101 |  |
             /** URI パラメータの {@link Map} です。 */
102 |  |
             private final Map<String, String[]> uriParameters;
103 |  |
104 |  |
             /** フォームオブジェクトのラッパーファクトリです。 */
105 |  |
             private FormWrapperFactory formWrapperFactory;
106 |  |
107 |  |
             /**
108 |  |
              * 指定された要求をラップした要求オブジェクトを構築します。
109 |  |
              *
110 |  |
              * @param request
111 |  |
              *            要求
112 |  |
              * @param uriParameters
113 |  |
              *            URI パラメータの {@link Map}
114 |  |
              */
115 |  |
             public CubbyHttpServletRequestWrapper(final HttpServletRequest request,
116 |  |
                             final Map<String, String[]> uriParameters) {
117 | 4 |
                     super(request);
118 | 4 |
                     this.uriParameters = uriParameters;
119 | 4 |
             }
120 |  |
121 |  |
             /**
122 |  |
              * 指定された属性の値を <code>Object</code> として返します。指定された名前の属性が存在しない場合は、
123 |  |
              * <code>null</code> を返します。
124 |  |
              *
125 |  |
              * @param name
126 |  |
              *            属性の名前を指定する <code>String</code>
127 |  |
              * @return 属性の値を含む <code>Object</code>。属性が存在しない場合は <code>null</code>
128 |  |
              */
129 |  |
             @Override
130 |  |
             public Object getAttribute(final String name) {
131 |  |
                     final Object value;
132 | 7 |
                     if (ATTR_CONTEXT_PATH.equals(name)) {
133 | 1 |
                             value = this.getContextPath();
134 | 6 |
                     } else if (ATTR_MESSAGES.equals(name)) {
135 | 1 |
                             value = ThreadContext.getMessagesMap();
136 | 5 |
                     } else if (ATTR_FORM_WRAPPER_FACTORY.equals(name)) {
137 | 0 |
                             if (this.formWrapperFactory == null) {
138 | 0 |
                                     this.formWrapperFactory = new FormWrapperFactoryImpl();
139 |  |
                             }
140 | 0 |
                             value = this.formWrapperFactory;
141 |  |
                     } else {
142 | 5 |
                             final Object action = super.getAttribute(ATTR_ACTION);
143 | 5 |
                             if (action != null) {
144 | 4 |
                                     final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(action
145 |  |
                                                     .getClass());
146 | 4 |
                                     if (beanDesc.hasPropertyAttribute(name)) {
147 | 2 |
                                             final Attribute attribute = beanDesc
148 |  |
                                                             .getPropertyAttribute(name);
149 | 2 |
                                             if (attribute.isReadable()) {
150 | 1 |
                                                     value = attribute.getValue(action);
151 |  |
                                             } else {
152 | 1 |
                                                     value = super.getAttribute(name);
153 |  |
                                             }
154 | 2 |
                                     } else {
155 | 2 |
                                             value = super.getAttribute(name);
156 |  |
                                     }
157 | 4 |
                             } else {
158 | 1 |
                                     value = super.getAttribute(name);
159 |  |
                             }
160 |  |
                     }
161 | 7 |
                     return value;
162 |  |
             }
163 |  |
164 |  |
             /**
165 |  |
              * この要求で利用できる属性の名前が格納された <code>Enumeration</code> を返します。利用できる属性が要求にない場合は、空の
166 |  |
              * <code>Enumeration</code> を返します。
167 |  |
              *
168 |  |
              * @return 要求に付随する属性の名前が格納された文字列の <code>Enumeration</code>
169 |  |
              */
170 |  |
             @SuppressWarnings("unchecked")
171 |  |
             @Override
172 |  |
             public Enumeration getAttributeNames() {
173 | 1 |
                     final Set attributeNames = new HashSet();
174 |  |
175 | 1 |
                     attributeNames.add(ATTR_CONTEXT_PATH);
176 | 1 |
                     attributeNames.add(ATTR_ACTION);
177 | 1 |
                     attributeNames.add(ATTR_MESSAGES);
178 | 1 |
                     attributeNames.add(ATTR_FORM_WRAPPER_FACTORY);
179 |  |
180 | 1 |
                     final Object action = super.getAttribute(ATTR_ACTION);
181 | 1 |
                     if (action != null) {
182 | 1 |
                             final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(action
183 |  |
                                             .getClass());
184 | 1 |
                             for (final Attribute attribute : beanDesc.findtPropertyAttributes()) {
185 | 5 |
                                     if (attribute.isReadable()) {
186 | 4 |
                                             attributeNames.add(attribute.getName());
187 |  |
                                     }
188 |  |
                             }
189 |  |
                     }
190 |  |
191 | 1 |
                     final Enumeration defaultAttributeNames = super.getAttributeNames();
192 | 3 |
                     while (defaultAttributeNames.hasMoreElements()) {
193 | 2 |
                             attributeNames.add(defaultAttributeNames.nextElement());
194 |  |
                     }
195 | 1 |
                     return new IteratorEnumeration(attributeNames.iterator());
196 |  |
             }
197 |  |
198 |  |
             /**
199 |  |
              * 要求パラメータの値を <code>String</code> として返します。
200 |  |
              * <p>
201 |  |
              * パラメータが存在しない場合は、<code>null</code> を返します。
202 |  |
              * </p>
203 |  |
              *
204 |  |
              * @param name
205 |  |
              *            パラメータの名前を指定する <code>String</code>
206 |  |
              * @return パラメータの単一の値を表す <code>String</code>
207 |  |
              */
208 |  |
             @Override
209 |  |
             public String getParameter(final String name) {
210 | 4 |
                     final String[] parameters = this.getParameterValues(name);
211 | 4 |
                     if (parameters == null) {
212 | 1 |
                             return null;
213 |  |
                     } else {
214 | 3 |
                             return parameters[0];
215 |  |
                     }
216 |  |
             }
217 |  |
218 |  |
             /**
219 |  |
              * この要求に含まれるパラメータの名前を格納した、<code>String</code> オブジェクトの
220 |  |
              * <code>Enumeration</code> を返します。
221 |  |
              * <p>
222 |  |
              * パラメータが要求にない場合、このメソッドは空の <code>Enumeration</code> を返します。
223 |  |
              * </p>
224 |  |
              */
225 |  |
             @SuppressWarnings("unchecked")
226 |  |
             @Override
227 |  |
             public Enumeration getParameterNames() {
228 | 1 |
                     return new IteratorEnumeration(this.getParameterMap().keySet()
229 |  |
                                     .iterator());
230 |  |
             }
231 |  |
232 |  |
             /**
233 |  |
              * 指定された要求パラメータのすべての値が格納された <code>String</code> オブジェクトの配列を返します。
234 |  |
              * <p>
235 |  |
              * パラメータが存在しない場合は、<code>null</code> を返します。
236 |  |
              * </p>
237 |  |
              *
238 |  |
              * @param name
239 |  |
              *            取得したいパラメータの名前を表す <code>String</code>
240 |  |
              * @return パラメータの値が格納された <code>String</code> オブジェクトの配列
241 |  |
              */
242 |  |
             @SuppressWarnings("unchecked")
243 |  |
             @Override
244 |  |
             public String[] getParameterValues(final String name) {
245 | 7 |
                     final Map<String, String[]> parameterMap = this.getParameterMap();
246 | 7 |
                     return parameterMap.get(name);
247 |  |
             }
248 |  |
249 |  |
             /**
250 |  |
              * この要求から取得できるパラメータを <code>java.util.Map</code> で返します。
251 |  |
              *
252 |  |
              * @return キーとしてパラメータ名、マップ値としてパラメータ値が格納された不変の <code>java.util.Map</code>。
253 |  |
              *         <p>
254 |  |
              *         パラメータマップ内のキーは <code>String</code> 型。パラメータマップ内の値は
255 |  |
              *         <code>String</code> の配列型
256 |  |
              *         </p>
257 |  |
              */
258 |  |
             @SuppressWarnings("unchecked")
259 |  |
             @Override
260 |  |
             public Map getParameterMap() {
261 | 10 |
                     final Map<String, String[]> parameterMap = buildParameterMap(
262 |  |
                                     (HttpServletRequest) getRequest(), uriParameters);
263 | 10 |
                     return parameterMap;
264 |  |
             }
265 |  |
266 |  |
             /**
267 |  |
              * 要求パラメータを構築します。
268 |  |
              *
269 |  |
              * @param request
270 |  |
              *            要求
271 |  |
              * @param uriParameters
272 |  |
              *            URI パラメータの {@link Map}
273 |  |
              * @return URI パラメータを含む要求パラメータの {@link Map}
274 |  |
              */
275 |  |
             private Map<String, String[]> buildParameterMap(
276 |  |
                             final HttpServletRequest request,
277 |  |
                             final Map<String, String[]> uriParameters) {
278 | 10 |
                     final Map<String, List<String>> extendedParameterMap = new HashMap<String, List<String>>();
279 |  |
280 | 10 |
                     final Map<?, ?> originalParameterMap = request.getParameterMap();
281 | 10 |
                     for (final Entry<?, ?> entry : originalParameterMap.entrySet()) {
282 | 18 |
                             final String name = (String) entry.getKey();
283 | 18 |
                             final List<String> values = new ArrayList<String>();
284 | 36 |
                             for (final String value : (String[]) entry.getValue()) {
285 | 18 |
                                     values.add(value);
286 |  |
                             }
287 | 18 |
                             extendedParameterMap.put(name, values);
288 | 18 |
                     }
289 | 10 |
                     for (final Entry<String, String[]> entry : uriParameters.entrySet()) {
290 | 18 |
                             final String name = entry.getKey();
291 | 18 |
                             if (extendedParameterMap.containsKey(name)) {
292 | 9 |
                                     final List<String> values = extendedParameterMap.get(name);
293 | 18 |
                                     for (final String value : entry.getValue()) {
294 | 9 |
                                             values.add(value);
295 |  |
                                     }
296 | 9 |
                             } else {
297 | 9 |
                                     final List<String> values = new ArrayList<String>();
298 | 18 |
                                     for (final String value : entry.getValue()) {
299 | 9 |
                                             values.add(value);
300 |  |
                                     }
301 | 9 |
                                     extendedParameterMap.put(name, values);
302 |  |
                             }
303 | 18 |
                     }
304 |  |
305 | 10 |
                     final Map<String, String[]> parameterMap = new HashMap<String, String[]>();
306 | 10 |
                     for (final Entry<String, List<String>> entry : extendedParameterMap
307 |  |
                                     .entrySet()) {
308 | 27 |
                             parameterMap.put(entry.getKey(), entry.getValue().toArray(
309 |  |
                                             new String[0]));
310 |  |
                     }
311 | 10 |
                     return parameterMap;
312 |  |
             }
313 |  |
314 |  |
     }