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.util;
17  
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  
21  import javax.servlet.http.HttpServletRequest;
22  
23  /**
24   * 要求の URL をベースとしたリンク文字列を構築します。
25   * 
26   * @author baba
27   * @since 1.1.4
28   */
29  public class LinkBuilder {
30  
31  	/** プロトコル。 */
32  	private String protocol;
33  
34  	/** ホスト名。 */
35  	private String host;
36  
37  	/** ホスト上でのポート番号。 */
38  	private int port;
39  
40  	/** ホスト上のファイル。 */
41  	private String file;
42  
43  	/**
44  	 * URL ビルダオブジェクトを生成します。
45  	 */
46  	public LinkBuilder() {
47  		this.clear();
48  	}
49  
50  	/**
51  	 * このインスタンスをクリアします。
52  	 */
53  	public void clear() {
54  		this.protocol = null;
55  		this.host = null;
56  		this.port = -1;
57  		this.file = null;
58  	}
59  
60  	/**
61  	 * プロトコルを取得します。
62  	 * 
63  	 * @return プロトコル
64  	 */
65  	public String getProtocol() {
66  		return protocol;
67  	}
68  
69  	/**
70  	 * プロトコルを設定します。
71  	 * 
72  	 * @param protocol
73  	 *            プロトコル
74  	 * @throws NullPointerException
75  	 *             指定された <code>protocol</code> が <code>null</code> の場合
76  	 */
77  	public void setProtocol(final String protocol) {
78  		if (protocol == null) {
79  			throw new NullPointerException("No protocol");
80  		}
81  		this.protocol = protocol;
82  	}
83  
84  	/**
85  	 * ホスト名を取得します。
86  	 * 
87  	 * @return ホスト名
88  	 */
89  	public String getHost() {
90  		return host;
91  	}
92  
93  	/**
94  	 * ホスト名を設定します。
95  	 * 
96  	 * @param host
97  	 *            ホスト名
98  	 * @throws NullPointerException
99  	 *             指定された <code>host</code> が <code>null</code> の場合
100 	 */
101 	public void setHost(final String host) {
102 		if (host == null) {
103 			throw new NullPointerException("No host");
104 		}
105 		this.host = host;
106 	}
107 
108 	/**
109 	 * ホスト上のポート番号を取得します。
110 	 * 
111 	 * @return ホスト上のポート番号
112 	 */
113 	public int getPort() {
114 		return port;
115 	}
116 
117 	/**
118 	 * ホスト上のポート番号を設定します。
119 	 * 
120 	 * @param port
121 	 *            ホスト上のポート番号
122 	 * @throws IllegalArgumentException
123 	 *             ポート番号が負の値の場合
124 	 */
125 	public void setPort(final int port) {
126 		if (port < 0) {
127 			throw new IllegalArgumentException("Invalid port number :" + port);
128 		}
129 		this.port = port;
130 	}
131 
132 	/**
133 	 * ホスト上のファイルを取得します。
134 	 * 
135 	 * @return ホスト上のファイル
136 	 */
137 	public String getFile() {
138 		return file;
139 	}
140 
141 	/**
142 	 * ホスト上のファイルを設定します。
143 	 * 
144 	 * @param file
145 	 *            ホスト上のファイル
146 	 */
147 	public void setFile(final String file) {
148 		this.file = file;
149 	}
150 
151 	/**
152 	 * このリンクの文字列表現を構築します。
153 	 * <p>
154 	 * 指定された要求とこのオブジェクトに指定されたプロトコル、ホスト名、ホスト上のポート番号が同じ場合は相対パスであるとみなして内部形式
155 	 * のリンク文字列を、そうでない場合は外部形式のリンク文字列を構築します。
156 	 * </p>
157 	 * 
158 	 * @param request
159 	 *            要求
160 	 * @return URL の文字列表現
161 	 * @throws MalformedURLException
162 	 *             未知のプロトコルとして指定された場合
163 	 */
164 	public String toLink(final HttpServletRequest request)
165 			throws MalformedURLException {
166 		final URL requestURL = new URL(request.getRequestURL().toString());
167 		final URL newURL = new URL(getNewProtocol(requestURL.getProtocol()),
168 				getNewHost(requestURL.getHost()), getNewPort(requestURL
169 						.getPort()), getNewFile(requestURL.getFile()));
170 		if (isRelativeLink(requestURL, newURL)) {
171 			return newURL.getFile();
172 		} else {
173 			return newURL.toExternalForm();
174 		}
175 	}
176 
177 	/**
178 	 * 指定された 2 つの URL を比較して、相対パス形式の URL 文字列を生成するかどうかを示します。
179 	 * 
180 	 * @param url1
181 	 *            URL1
182 	 * @param url2
183 	 *            URL2
184 	 * @return 相対パス形式の URL 文字列を生成する場合は <code>true</code>、そうでない場合は
185 	 *         <code>false</code>
186 	 */
187 	private boolean isRelativeLink(final URL url1, final URL url2) {
188 		if (!url1.getProtocol().equals(url2.getProtocol())) {
189 			return false;
190 		}
191 		if (!url1.getHost().equals(url2.getHost())) {
192 			return false;
193 		}
194 		if (url1.getPort() != url2.getPort()) {
195 			return false;
196 		}
197 		return true;
198 	}
199 
200 	/**
201 	 * 新しい URL のプロトコルを返します。
202 	 * 
203 	 * @param requestProtocol
204 	 *            要求のプロトコル
205 	 * @return 新しい URL のプロトコル
206 	 */
207 	private String getNewProtocol(final String requestProtocol) {
208 		if (this.protocol == null) {
209 			return requestProtocol;
210 		} else {
211 			return this.protocol;
212 		}
213 	}
214 
215 	/**
216 	 * 新しい URL のホスト名を返します。
217 	 * 
218 	 * @param requestHost
219 	 *            要求のホスト名
220 	 * @return 新しい URL のホスト名
221 	 */
222 	private String getNewHost(final String requestHost) {
223 		if (this.host == null) {
224 			return requestHost;
225 		} else {
226 			return this.host;
227 		}
228 	}
229 
230 	/**
231 	 * 新しい URL のホスト上のポート番号
232 	 * 
233 	 * @param requestPort
234 	 *            要求のホスト上のポート番号
235 	 * @return 新しい URL のホスト上のポート番号
236 	 */
237 	private int getNewPort(final int requestPort) {
238 		if (this.port < 0) {
239 			return requestPort;
240 		} else {
241 			return this.port;
242 		}
243 	}
244 
245 	/**
246 	 * 新しい URL のホスト上のファイル
247 	 * 
248 	 * @param requestPort
249 	 *            要求のホスト上のファイル
250 	 * @return 新しい URL のホスト上のファイル
251 	 */
252 	private String getNewFile(final String currentFile) {
253 		if (this.file == null) {
254 			return currentFile;
255 		} else {
256 			return this.file;
257 		}
258 	}
259 
260 	/**
261 	 * プロトコルを設定します。
262 	 * 
263 	 * @param protocol
264 	 *            プロトコル
265 	 * @return このオブジェクト
266 	 */
267 	public LinkBuilder protocol(final String protocol) {
268 		this.setProtocol(protocol);
269 		return this;
270 	}
271 
272 	/**
273 	 * ホスト名を設定します。
274 	 * 
275 	 * @param host
276 	 *            ホスト名
277 	 * @return このオブジェクト
278 	 */
279 	public LinkBuilder host(final String host) {
280 		this.setHost(host);
281 		return this;
282 	}
283 
284 	/**
285 	 * ホスト上のポート場号を設定します。
286 	 * 
287 	 * @param port
288 	 *            ホスト上のポート場号
289 	 * @return このオブジェクト
290 	 */
291 	public LinkBuilder port(final int port) {
292 		this.setPort(port);
293 		return this;
294 	}
295 
296 	/**
297 	 * ホスト上のファイルを設定します。
298 	 * 
299 	 * @param file
300 	 *            ホスト上のファイル
301 	 * @return このオブジェクト
302 	 */
303 	public LinkBuilder file(final String file) {
304 		this.setFile(file);
305 		return this;
306 	}
307 
308 	/**
309 	 * {@inheritDoc}
310 	 */
311 	@Override
312 	public String toString() {
313 		final StringBuilder builder = new StringBuilder();
314 		builder.append(this);
315 		builder.append(" [host=");
316 		builder.append(host);
317 		builder.append(",protocol=");
318 		builder.append(protocol);
319 		builder.append(",port=");
320 		builder.append(port);
321 		builder.append(",file=");
322 		builder.append(file);
323 		builder.append("]");
324 		return builder.toString();
325 	}
326 
327 }