View Javadoc

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