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