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