001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2014 ForgeRock AS. 015 */ 016 017package org.forgerock.openig.util; 018 019import static org.forgerock.openig.util.URIUtil.*; 020 021import java.net.URI; 022import java.net.URISyntaxException; 023 024/** 025 * A MutableUri is a modifiable {@link URI} substitute. 026 * Unlike URIs, which are immutable, a MutableUri can have its fields updated independently. 027 * That makes it easier if you just want to change a element of an Uri. 028 * 029 * @see URI 030 */ 031public final class MutableUri implements Comparable<MutableUri> { 032 033 /** 034 * Factory method for avoiding typing {@code new MutableUri("http://...")}. 035 * @param uri URL encoded URI 036 * @return a new MutableUri instance 037 * @throws URISyntaxException if the given Uri is not well-formed 038 */ 039 public static MutableUri uri(String uri) throws URISyntaxException { 040 return new MutableUri(uri); 041 } 042 043 /** 044 * The real URI, hidden by this class. Recreated each time a field is updated. 045 */ 046 private URI uri; 047 048 /** 049 * Builds a new MutableUri using the given URI. 050 * @param uri URI 051 */ 052 public MutableUri(final URI uri) { 053 this.uri = uri; 054 } 055 056 /** 057 * Builds a new MutableUri with deep copy. 058 * @param mutableUri URI 059 */ 060 public MutableUri(final MutableUri mutableUri) { 061 this.uri = mutableUri.asURI(); 062 } 063 064 /** 065 * Builds a new MutableUri using the given URL encoded String URI. 066 * @param uri URL encoded URI 067 * @throws URISyntaxException if the given Uri is not well-formed 068 */ 069 public MutableUri(final String uri) throws URISyntaxException { 070 this.uri = new URI(uri); 071 } 072 073 /** 074 * Builds a new MutableUri using the given fields values (decoded values). 075 * @param scheme Scheme name 076 * @param userInfo User name and authorization information 077 * @param host Host name 078 * @param port Port number 079 * @param path Path 080 * @param query Query 081 * @param fragment Fragment 082 * @throws URISyntaxException if the produced URI is not well-formed 083 */ 084 public MutableUri(String scheme, 085 String userInfo, 086 String host, 087 int port, 088 String path, 089 String query, 090 String fragment) 091 throws URISyntaxException { 092 uri = new URI(scheme, userInfo, host, port, path, query, fragment); 093 } 094 095 /** 096 * Returns the equivalent {@link URI} instance. 097 * @return the equivalent {@link URI} instance. 098 */ 099 public URI asURI() { 100 return uri; 101 } 102 103 /** 104 * Returns the scheme name. 105 * @return the scheme name. 106 */ 107 public String getScheme() { 108 return uri.getScheme(); 109 } 110 111 /** 112 * Update the scheme of this MutableUri. 113 * @param scheme new scheme name 114 * @throws URISyntaxException if the new equivalent URI is invalid 115 */ 116 public void setScheme(final String scheme) throws URISyntaxException { 117 this.uri = new URI(scheme, 118 uri.getUserInfo(), 119 uri.getHost(), 120 uri.getPort(), 121 uri.getPath(), 122 uri.getQuery(), 123 uri.getFragment()); 124 } 125 126 /** 127 * Returns the user info element. 128 * @return the user info element. 129 */ 130 public String getUserInfo() { 131 return uri.getUserInfo(); 132 } 133 134 /** 135 * Returns the raw (encoded) user info element. 136 * @return the raw user info element. 137 */ 138 public String getRawUserInfo() { 139 return uri.getRawUserInfo(); 140 } 141 142 /** 143 * Update the user info (not encoded) of this MutableUri. 144 * @param userInfo new user info element (not encoded) 145 * @throws URISyntaxException if the new equivalent URI is invalid 146 */ 147 public void setUserInfo(final String userInfo) throws URISyntaxException { 148 this.uri = new URI(uri.getScheme(), 149 userInfo, 150 uri.getHost(), 151 uri.getPort(), 152 uri.getPath(), 153 uri.getQuery(), 154 uri.getFragment()); 155 } 156 157 /** 158 * Update the user info (encoded) of this MutableUri. 159 * @param rawUserInfo new user info element (encoded) 160 * @throws URISyntaxException if the new equivalent URI is invalid 161 */ 162 public void setRawUserInfo(String rawUserInfo) throws URISyntaxException { 163 uri = create(uri.getScheme(), 164 rawUserInfo, 165 uri.getHost(), 166 uri.getPort(), 167 uri.getRawPath(), 168 uri.getRawQuery(), 169 uri.getRawFragment()); 170 } 171 172 /** 173 * Returns the host element. 174 * @return the host element. 175 */ 176 public String getHost() { 177 return uri.getHost(); 178 } 179 180 /** 181 * Update the host name of this MutableUri. 182 * @param host new host element 183 * @throws URISyntaxException if the new equivalent URI is invalid 184 */ 185 public void setHost(final String host) throws URISyntaxException { 186 this.uri = new URI(uri.getScheme(), 187 uri.getUserInfo(), 188 host, 189 uri.getPort(), 190 uri.getPath(), 191 uri.getQuery(), 192 uri.getFragment()); 193 } 194 195 /** 196 * Returns the port element. 197 * @return the port element. 198 */ 199 public int getPort() { 200 return uri.getPort(); 201 } 202 203 /** 204 * Update the port of this MutableUri. 205 * @param port new port number 206 * @throws URISyntaxException if the new equivalent URI is invalid 207 */ 208 public void setPort(final int port) throws URISyntaxException { 209 uri = new URI(uri.getScheme(), 210 uri.getUserInfo(), 211 uri.getHost(), 212 port, 213 uri.getPath(), 214 uri.getQuery(), 215 uri.getFragment()); 216 } 217 218 /** 219 * Returns the path element. 220 * @return the path element. 221 */ 222 public String getPath() { 223 return uri.getPath(); 224 } 225 226 /** 227 * Returns the raw (encoded) path element. 228 * @return the raw path element. 229 */ 230 public String getRawPath() { 231 return uri.getRawPath(); 232 } 233 234 /** 235 * Update the path (not encoded) of this MutableUri. 236 * @param path new path element (not encoded) 237 * @throws URISyntaxException if the new equivalent URI is invalid 238 */ 239 public void setPath(final String path) throws URISyntaxException { 240 this.uri = new URI(uri.getScheme(), 241 uri.getUserInfo(), 242 uri.getHost(), 243 uri.getPort(), 244 path, 245 uri.getQuery(), 246 uri.getFragment()); 247 248 } 249 250 /** 251 * Update the pah (encoded) of this MutableUri. 252 * @param rawPath new path element (encoded) 253 * @throws URISyntaxException if the new equivalent URI is invalid 254 */ 255 public void setRawPath(String rawPath) throws URISyntaxException { 256 uri = create(uri.getScheme(), 257 uri.getRawUserInfo(), 258 uri.getHost(), 259 uri.getPort(), 260 rawPath, 261 uri.getRawQuery(), 262 uri.getRawFragment()); 263 } 264 265 /** 266 * Returns the path element. 267 * @return the path element. 268 */ 269 public String getQuery() { 270 return uri.getQuery(); 271 } 272 273 /** 274 * Returns the raw (encoded) query element. 275 * @return the raw query element. 276 */ 277 public String getRawQuery() { 278 return uri.getRawQuery(); 279 } 280 281 /** 282 * Update the query string (not encoded) of this MutableUri. 283 * @param query new query string element (not encoded) 284 * @throws URISyntaxException if the new equivalent URI is invalid 285 */ 286 public void setQuery(final String query) throws URISyntaxException { 287 this.uri = new URI(uri.getScheme(), 288 uri.getUserInfo(), 289 uri.getHost(), 290 uri.getPort(), 291 uri.getPath(), 292 query, 293 uri.getFragment()); 294 } 295 296 /** 297 * Update the query (encoded) of this MutableUri. 298 * @param rawQuery new query element (encoded) 299 * @throws URISyntaxException if the new equivalent URI is invalid 300 */ 301 public void setRawQuery(String rawQuery) throws URISyntaxException { 302 uri = create(uri.getScheme(), 303 uri.getRawUserInfo(), 304 uri.getHost(), 305 uri.getPort(), 306 uri.getRawPath(), 307 rawQuery, 308 uri.getRawFragment()); 309 } 310 311 /** 312 * Returns the fragment element. 313 * @return the fragment element. 314 */ 315 public String getFragment() { 316 return uri.getFragment(); 317 } 318 319 /** 320 * Returns the raw (encoded) fragment element. 321 * @return the raw fragment element. 322 */ 323 public String getRawFragment() { 324 return uri.getRawFragment(); 325 } 326 327 /** 328 * Update the fragment (not encoded) of this MutableUri. 329 * @param fragment new fragment element (not encoded) 330 * @throws URISyntaxException if the new equivalent URI is invalid 331 */ 332 public void setFragment(final String fragment) throws URISyntaxException { 333 this.uri = new URI(uri.getScheme(), 334 uri.getUserInfo(), 335 uri.getHost(), 336 uri.getPort(), 337 uri.getPath(), 338 uri.getQuery(), 339 fragment); 340 } 341 342 /** 343 * Update the fragment (encoded) of this MutableUri. 344 * @param rawFragment new framgent element (encoded) 345 * @throws URISyntaxException if the new equivalent URI is invalid 346 */ 347 public void setRawFragment(String rawFragment) throws URISyntaxException { 348 uri = create(uri.getScheme(), 349 uri.getRawUserInfo(), 350 uri.getHost(), 351 uri.getPort(), 352 uri.getRawPath(), 353 uri.getRawQuery(), 354 rawFragment); 355 } 356 357 /** 358 * Returns the authority compound element. 359 * @return the authority compound element. 360 */ 361 public String getAuthority() { 362 return uri.getAuthority(); 363 } 364 365 /** 366 * Returns the raw (encoded) authority compound element. 367 * @return the authority compound element. 368 */ 369 public String getRawAuthority() { 370 return uri.getRawAuthority(); 371 } 372 373 /** 374 * Changes the base scheme, host and port of this MutableUri to that specified in a base URI, 375 * or leaves them unchanged if the base URI is {@code null}. This implementation only 376 * uses scheme, host and port. The remaining components of the URI remain intact. 377 * 378 * @param base the URI to base the other URI on. 379 * @return this (rebased) instance 380 */ 381 public MutableUri rebase(MutableUri base) { 382 if (base == null) { 383 return this; 384 } 385 String scheme = base.getScheme(); 386 String host = base.getHost(); 387 int port = base.getPort(); 388 if (scheme == null || host == null) { 389 return this; 390 } 391 try { 392 setScheme(scheme); 393 setHost(host); 394 setPort(port); 395 } catch (URISyntaxException e) { 396 throw new IllegalStateException(e); 397 } 398 return this; 399 } 400 401 /** 402 * Changes the base scheme, host and port of this MutableUri to that specified in a base URI, 403 * or leaves them unchanged if the base URI is {@code null}. This implementation only 404 * uses scheme, host and port. The remaining components of the URI remain intact. 405 * 406 * @param base the URI to base the other URI on. 407 * @return this (rebased) instance 408 */ 409 public MutableUri rebase(URI base) { 410 return rebase(new MutableUri(base)); 411 } 412 413 @Override 414 public int compareTo(final MutableUri o) { 415 return asURI().compareTo(o.asURI()); 416 } 417 418 /** 419 * Relativizes the given URI against this URI. 420 * @param uri the uri to relativizes against this instance 421 * @return this instance (mutated) 422 * @see URI#relativize(URI) 423 */ 424 public MutableUri relativize(final MutableUri uri) { 425 this.uri = this.uri.relativize(uri.asURI()); 426 return this; 427 } 428 429 /** 430 * Resolves the given URI against this URI. 431 * @param uri the uri to resolve against this instance 432 * @return this instance (mutated) 433 * @see URI#resolve(URI) 434 */ 435 public MutableUri resolve(final MutableUri uri) { 436 this.uri = this.uri.resolve(uri.asURI()); 437 return this; 438 } 439 440 @Override 441 public String toString() { 442 return uri.toString(); 443 } 444 445 /** 446 * Returns the content of this URI as a US-ASCII string. 447 * @return the content of this URI as a US-ASCII string. 448 */ 449 public String toASCIIString() { 450 return uri.toASCIIString(); 451 } 452 453 @Override 454 public boolean equals(final Object o) { 455 if (this == o) { 456 return true; 457 } 458 if (o == null || !(o instanceof MutableUri)) { 459 return false; 460 } 461 MutableUri that = (MutableUri) o; 462 return uri.equals(that.uri); 463 464 } 465 466 @Override 467 public int hashCode() { 468 return uri.hashCode(); 469 } 470}