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.util.LinkBuilder;
36  
37  /**
38   * 指定されたアクションクラス、アクションメソッドへリンクする URL を特定の属性にもつタグを出力するカスタムタグです。
39   * 
40   * @author baba
41   * @since 1.1.0
42   */
43  public class LinkTag extends BodyTagSupport implements DynamicAttributes,
44  		ParamParent {
45  
46  	/** シリアルバージョン UID */
47  	private static final long serialVersionUID = 1L;
48  
49  	/** DynamicAttributes */
50  	private final Map<String, Object> attrs = new HashMap<String, Object>();
51  
52  	/** リンクの補助クラス。 */
53  	private final LinkSupport linkSupport = new LinkSupport();
54  
55  	/** リンクビルダ。 */
56  	private final LinkBuilder linkBuilder = new LinkBuilder();
57  
58  	/** 出力するタグ。 */
59  	private String tag;
60  
61  	/** リンクする URL を出力する属性。 */
62  	private String attr;
63  
64  	/** 出力する URL を {@link HttpServletResponse#encodeURL(String)} でエンコードするか。 */
65  	private boolean encodeURL = true;
66  
67  	/**
68  	 * {@inheritDoc} DynamicAttributeをセットします。
69  	 */
70  	public void setDynamicAttribute(final String uri, final String localName,
71  			final Object value) throws JspException {
72  		this.attrs.put(localName, value);
73  	}
74  
75  	/**
76  	 * 出力するタグを設定します。
77  	 * 
78  	 * @param tag
79  	 *            出力するタグ
80  	 */
81  	public void setTag(final String tag) {
82  		this.tag = tag;
83  	}
84  
85  	/**
86  	 * リンクする URL を出力する属性を設定します。
87  	 * 
88  	 * @param attr
89  	 *            リンクする URL を出力する属性
90  	 */
91  	public void setAttr(final String attr) {
92  		this.attr = attr;
93  	}
94  
95  	/**
96  	 * アクションクラスを設定します。
97  	 * 
98  	 * @param actionClass
99  	 *            アクションクラス
100 	 */
101 	public void setActionClass(final String actionClass) {
102 		linkSupport.setActionClassName(actionClass);
103 	}
104 
105 	/**
106 	 * アクションメソッドを設定します。
107 	 * 
108 	 * @param actionMethod
109 	 *            アクションメソッド
110 	 */
111 	public void setActionMethod(final String actionMethod) {
112 		linkSupport.setActionMethodName(actionMethod);
113 	}
114 
115 	/**
116 	 * 出力する URL を {@link HttpServletResponse#encodeURL(String)} でエンコードするかを設定します。
117 	 * 
118 	 * @param encodeURL
119 	 *            出力する URL を {@link HttpServletResponse#encodeURL(String)}
120 	 *            でエンコードする場合は <code>true</code>、そうでない場合は <code>false</code>
121 	 */
122 	public void setEncodeURL(final boolean encodeURL) {
123 		this.encodeURL = encodeURL;
124 	}
125 
126 	/**
127 	 * 出力する URL のプロトコルを設定します。
128 	 * 
129 	 * @param protocol
130 	 *            出力する URL のプロトコル
131 	 */
132 	public void setProtocol(final String protocol) {
133 		linkBuilder.setProtocol(protocol);
134 	}
135 
136 	/**
137 	 * 出力する URL のポートを設定します。
138 	 * 
139 	 * @param port
140 	 *            出力する URL のポート
141 	 */
142 	public void setPort(final int port) {
143 		linkBuilder.setPort(port);
144 	}
145 
146 	/**
147 	 * リクエストパラメータを追加します。
148 	 * 
149 	 * @param name
150 	 *            パラメータ名
151 	 * @param value
152 	 *            値
153 	 */
154 	public void addParameter(final String name, final String value) {
155 		linkSupport.addParameter(name, value);
156 	}
157 
158 	/**
159 	 * {@inheritDoc}
160 	 */
161 	@Override
162 	public int doStartTag() throws JspException {
163 		return EVAL_BODY_BUFFERED;
164 	}
165 
166 	/**
167 	 * {@inheritDoc}
168 	 */
169 	@Override
170 	public int doEndTag() throws JspException {
171 		final String contextPath = (String) pageContext.getAttribute(
172 				ATTR_CONTEXT_PATH, PageContext.REQUEST_SCOPE);
173 		final String actionPath;
174 		final String characterEncoding = pageContext.getRequest()
175 				.getCharacterEncoding();
176 		if (encodeURL) {
177 			final HttpServletResponse response = HttpServletResponse.class
178 					.cast(pageContext.getResponse());
179 			actionPath = response.encodeURL(contextPath
180 					+ linkSupport.getPath(characterEncoding));
181 		} else {
182 			actionPath = contextPath + linkSupport.getPath(characterEncoding);
183 		}
184 
185 		final HttpServletRequest request = (HttpServletRequest) pageContext
186 				.getRequest();
187 		final String url;
188 		try {
189 			url = linkBuilder.file(actionPath).toLink(request);
190 		} catch (final MalformedURLException e) {
191 			throw new JspException(e);
192 		}
193 
194 		try {
195 			final JspWriter out = pageContext.getOut();
196 			if (tag == null) {
197 				out.write(url);
198 				final BodyContent bodyContent = getBodyContent();
199 				if (bodyContent != null) {
200 					bodyContent.writeOut(out);
201 				}
202 			} else {
203 				attrs.put(attr, url);
204 				out.write("<");
205 				out.write(tag);
206 				out.write(" ");
207 				out.write(toAttr(attrs));
208 				out.write(">");
209 				final BodyContent bodyContent = getBodyContent();
210 				if (bodyContent != null) {
211 					bodyContent.writeOut(out);
212 				}
213 				out.write("</");
214 				out.write(tag);
215 				out.write(">");
216 			}
217 		} catch (final IOException e) {
218 			throw new JspException(e);
219 		}
220 		reset();
221 		return EVAL_PAGE;
222 	}
223 
224 	/**
225 	 * このタグをリセットします。
226 	 */
227 	private void reset() {
228 		linkSupport.clear();
229 		linkBuilder.clear();
230 		attrs.clear();
231 		tag = null;
232 		attr = null;
233 		encodeURL = true;
234 	}
235 
236 }