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