View Javadoc

1   /*
2    * Copyright 2004-2008 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.filter;
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_MESSAGES;
21  
22  import java.util.ArrayList;
23  import java.util.Enumeration;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletRequestWrapper;
29  
30  import org.seasar.cubby.CubbyConstants;
31  import org.seasar.cubby.controller.ActionContext;
32  import org.seasar.cubby.controller.ThreadContext;
33  import org.seasar.framework.beans.BeanDesc;
34  import org.seasar.framework.beans.PropertyDesc;
35  import org.seasar.framework.beans.factory.BeanDescFactory;
36  import org.seasar.framework.container.ComponentDef;
37  
38  /**
39   * 特別な属性を取得するためのリクエストのラッパです。
40   * <p>
41   * 以下のような属性を使用することができます。 <table><thead>
42   * <tr>
43   * <th>属性名</th>
44   * <th>値</th>
45   * <th>型</th>
46   * </tr>
47   * </thead><tbody>
48   * <tr>
49   * <td>{@link CubbyConstants#ATTR_CONTEXT_PATH}</td>
50   * <td>コンテキストパス</td>
51   * <td>{@link String}</td>
52   * </tr>
53   * <tr>
54   * <td>{@link CubbyConstants#ATTR_ACTION}</td>
55   * <td>アクション</td>
56   * <td>{@link org.seasar.cubby.action.Action}</td>
57   * </tr>
58   * <tr>
59   * <td>{@link CubbyConstants#ATTR_MESSAGES}</td>
60   * <td>メッセージリソース</td>
61   * <td>{@link java.util.Map}</td>
62   * </tr>
63   * <tr>
64   * <td>アクションのプロパティ名</td>
65   * <td>アクションのプロパティ値</td>
66   * <td>任意</td>
67   * </tr>
68   * </table> これらの属性は通常の属性よりも優先されるのでご注意ください。
69   * </p>
70   * 
71   * @author baba
72   * @since 1.0.0
73   */
74  public class CubbyHttpServletRequestWrapper extends HttpServletRequestWrapper {
75  
76  	/** アクションのコンテキスト。 */
77  	private final ActionContext context;
78  
79  	/**
80  	 * インスタンス化します。
81  	 * 
82  	 * @param request
83  	 *            ラップするリクエスト
84  	 * @param context
85  	 *            アクションのコンテキスト
86  	 */
87  	public CubbyHttpServletRequestWrapper(final HttpServletRequest request,
88  			final ActionContext context) {
89  		super(request);
90  
91  		this.context = context;
92  	}
93  
94  	/**
95  	 * リクエストの属性を取得します。
96  	 * 
97  	 * @param name
98  	 *            属性名
99  	 */
100 	@Override
101 	public Object getAttribute(final String name) {
102 		final Object attribute;
103 		if (ATTR_CONTEXT_PATH.equals(name)) {
104 			attribute = this.getContextPath();
105 		} else if (ATTR_ACTION.equals(name)) {
106 			attribute = context.getAction();
107 		} else if (ATTR_MESSAGES.equals(name)) {
108 			attribute = ThreadContext.getMessagesMap();
109 		} else {
110 			if (context.isInitialized()) {
111 				final ComponentDef componentDef = context.getComponentDef();
112 				final Class<?> concreteClass = componentDef.getConcreteClass();
113 				final BeanDesc beanDesc = BeanDescFactory
114 						.getBeanDesc(concreteClass);
115 				if (beanDesc.hasPropertyDesc(name)) {
116 					final PropertyDesc propertyDesc = beanDesc
117 							.getPropertyDesc(name);
118 					if (propertyDesc.isReadable()) {
119 						attribute = propertyDesc.getValue(context.getAction());
120 					} else {
121 						attribute = super.getAttribute(name);
122 					}
123 				} else {
124 					attribute = super.getAttribute(name);
125 				}
126 			} else {
127 				attribute = super.getAttribute(name);
128 			}
129 		}
130 		return attribute;
131 	}
132 
133 	/**
134 	 * 属性名の列挙を返します。
135 	 * 
136 	 * @return 属性名の列挙
137 	 */
138 	@SuppressWarnings("unchecked")
139 	@Override
140 	public Enumeration getAttributeNames() {
141 		final List attributeNames = new ArrayList();
142 
143 		attributeNames.add(ATTR_ACTION);
144 
145 		final Class<?> concreteClass = context.getComponentDef()
146 				.getConcreteClass();
147 		final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(concreteClass);
148 		for (int i = 0; i < beanDesc.getPropertyDescSize(); i++) {
149 			final PropertyDesc propertyDesc = beanDesc.getPropertyDesc(i);
150 			if (propertyDesc.isReadable()) {
151 				attributeNames.add(propertyDesc.getPropertyName());
152 			}
153 		}
154 
155 		final Enumeration defaultAttributeNames = super.getAttributeNames();
156 		while (defaultAttributeNames.hasMoreElements()) {
157 			attributeNames.add(defaultAttributeNames.nextElement());
158 		}
159 		return new IteratorEnumeration(attributeNames.iterator());
160 	}
161 
162 	private static class IteratorEnumeration<T> implements Enumeration<T> {
163 
164 		private final Iterator<T> iterator;
165 
166 		private IteratorEnumeration(final Iterator<T> iterator) {
167 			this.iterator = iterator;
168 		}
169 
170 		/**
171 		 * {@inheritDoc}
172 		 */
173 		public boolean hasMoreElements() {
174 			return iterator.hasNext();
175 		}
176 
177 		/**
178 		 * {@inheritDoc}
179 		 */
180 		public T nextElement() {
181 			return iterator.next();
182 		}
183 
184 	}
185 
186 }