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.tags;
17  
18  import static org.seasar.cubby.CubbyConstants.ATTR_CONTEXT_PATH;
19  import static org.seasar.cubby.tags.TagUtils.toAttr;
20  
21  import java.io.IOException;
22  import java.net.MalformedURLException;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  import javax.servlet.jsp.JspException;
29  import javax.servlet.jsp.JspWriter;
30  import javax.servlet.jsp.PageContext;
31  import javax.servlet.jsp.tagext.BodyContent;
32  import javax.servlet.jsp.tagext.BodyTagSupport;
33  import javax.servlet.jsp.tagext.DynamicAttributes;
34  
35  import org.seasar.cubby.controller.FormWrapper;
36  import org.seasar.cubby.controller.FormWrapperFactory;
37  import org.seasar.cubby.util.LinkBuilder;
38  import org.seasar.framework.container.S2Container;
39  import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
40  
41  /**
42   * フォームを出力するタグライブラリ。
43   * <p>
44   * {@link InputTag}, {@link SelectTag}, {@link TextareaTag}を保持することができます。
45   * </p>
46   * 
47   * @author agata
48   * @author baba
49   * @since 1.0.0
50   */
51  public class FormTag extends BodyTagSupport implements DynamicAttributes,
52  		ParamParent {
53  
54  	/** シリアルバージョン UID */
55  	private static final long serialVersionUID = 1L;
56  
57  	/** DynamicAttributes */
58  	private final Map<String, Object> attrs = new HashMap<String, Object>();
59  
60  	/** フォームのバインディング対象のBean。 */
61  	private Object value;
62  
63  	/** 出力する URL を {@link HttpServletResponse#encodeURL(String)} でエンコードするか。 */
64  	private boolean encodeURL = true;
65  
66  	/** リンク用の補助クラス。 */
67  	private final LinkSupport linkSupport = new LinkSupport();
68  
69  	/** リンクビルダ。 */
70  	private final LinkBuilder linkBuilder = new LinkBuilder();
71  
72  	/** フォームオブジェクトのラッパー。 */
73  	private FormWrapper formWrapper;
74  
75  	/**
76  	 * {@inheritDoc} DynamicAttributeをセットします。
77  	 */
78  	public void setDynamicAttribute(final String uri, final String localName,
79  			final Object value) throws JspException {
80  		this.attrs.put(localName, value);
81  	}
82  
83  	/**
84  	 * DynamicAttributeを取得します。
85  	 * 
86  	 * @return DynamicAttribute
87  	 */
88  	protected Map<String, Object> getDynamicAttribute() {
89  		return this.attrs;
90  	}
91  
92  	/**
93  	 * フォームのバインディング対象のBeanをセットします。
94  	 * 
95  	 * @param value
96  	 *            フォームのバインディング対象のBean
97  	 */
98  	public void setValue(final Object value) {
99  		this.value = value;
100 	}
101 
102 	/**
103 	 * アクションクラスを設定します。
104 	 * 
105 	 * @param actionClass
106 	 *            アクションクラス
107 	 */
108 	public void setActionClass(final String actionClass) {
109 		linkSupport.setActionClassName(actionClass);
110 	}
111 
112 	/**
113 	 * アクションメソッドを設定します。
114 	 * 
115 	 * @param actionMethod
116 	 *            アクションメソッド
117 	 */
118 	public void setActionMethod(final String actionMethod) {
119 		linkSupport.setActionMethodName(actionMethod);
120 	}
121 
122 	/**
123 	 * 出力する URL を {@link HttpServletResponse#encodeURL(String)} でエンコードするかを設定します。
124 	 * 
125 	 * @param encodeURL
126 	 *            出力する URL を {@link HttpServletResponse#encodeURL(String)}
127 	 *            でエンコードする場合は <code>true</code>、そうでない場合は <code>false</code>
128 	 */
129 	public void setEncodeURL(final boolean encodeURL) {
130 		this.encodeURL = encodeURL;
131 	}
132 
133 	/**
134 	 * 出力する URL のプロトコルを設定します。
135 	 * 
136 	 * @param protocol
137 	 *            出力する URL のプロトコル
138 	 */
139 	public void setProtocol(final String protocol) {
140 		linkBuilder.setProtocol(protocol);
141 	}
142 
143 	/**
144 	 * 出力する URL のポートを設定します。
145 	 * 
146 	 * @param port
147 	 *            出力する URL のポート
148 	 */
149 	public void setPort(final int port) {
150 		linkBuilder.setPort(port);
151 	}
152 
153 	/**
154 	 * リクエストパラメータを追加します。
155 	 * 
156 	 * @param name
157 	 *            パラメータ名
158 	 * @param value
159 	 *            値
160 	 */
161 	public void addParameter(final String name, final String value) {
162 		linkSupport.addParameter(name, value);
163 	}
164 
165 	/**
166 	 * {@inheritDoc}
167 	 */
168 	@Override
169 	public int doStartTag() throws JspException {
170 		final S2Container container = SingletonS2ContainerFactory
171 				.getContainer();
172 		final FormWrapperFactory formWrapperFactory = (FormWrapperFactory) container
173 				.getComponent(FormWrapperFactory.class);
174 		this.formWrapper = formWrapperFactory.create(this.value);
175 		return EVAL_BODY_BUFFERED;
176 	}
177 
178 	/**
179 	 * {@inheritDoc}
180 	 */
181 	@Override
182 	public int doEndTag() throws JspException {
183 		final String contextPath = (String) pageContext.getAttribute(
184 				ATTR_CONTEXT_PATH, PageContext.REQUEST_SCOPE);
185 		if (linkSupport.isLinkable()) {
186 			final String characterEncoding = pageContext.getRequest()
187 					.getCharacterEncoding();
188 			final String url = contextPath
189 					+ linkSupport.getPath(characterEncoding);
190 			attrs.put("action", url);
191 		}
192 
193 		if (encodeURL && attrs.containsKey("action")) {
194 			final HttpServletRequest request = (HttpServletRequest) pageContext
195 					.getRequest();
196 			final HttpServletResponse response = (HttpServletResponse) pageContext
197 					.getResponse();
198 			final String actionPath = (String) attrs.get("action");
199 			final String url;
200 			try {
201 				url = linkBuilder.file(actionPath).toLink(request);
202 			} catch (final MalformedURLException e) {
203 				throw new JspException(e);
204 			}
205 			final String encodedUrl = response.encodeURL(url);
206 			attrs.put("action", encodedUrl);
207 		}
208 
209 		final JspWriter out = pageContext.getOut();
210 		try {
211 			out.write("<form ");
212 			out.write(toAttr(getDynamicAttribute()));
213 			out.write(">");
214 			final BodyContent bodyContent = getBodyContent();
215 			if (bodyContent != null) {
216 				bodyContent.writeOut(out);
217 			}
218 			out.write("</form>");
219 		} catch (final IOException e) {
220 			throw new JspException(e);
221 		}
222 		reset();
223 		return EVAL_PAGE;
224 	}
225 
226 	/**
227 	 * このタグをリセットします。
228 	 */
229 	private void reset() {
230 		linkSupport.clear();
231 		linkBuilder.clear();
232 		attrs.clear();
233 		value = null;
234 		formWrapper = null;
235 	}
236 
237 	/**
238 	 * フォームへ出力する値を取得します。
239 	 * 
240 	 * @param name
241 	 *            フィールド名
242 	 * @return フォームへ出力する値
243 	 * @since 1.1.0
244 	 */
245 	public String[] getValues(final String name) {
246 		return formWrapper.getValues(name);
247 	}
248 
249 }