View Javadoc

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