URIUtils.java revision 417f3b92ba4549b2f22340e3107d869d2b9c5bb8
1cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* 2cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/client/utils/URIUtils.java $ 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * $Revision: 653041 $ 4cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 2008) $ 5cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * 6cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * ==================================================================== 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Licensed to the Apache Software Foundation (ASF) under one or more 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * contributor license agreements. See the NOTICE file distributed with 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * this work for additional information regarding copyright ownership. 11cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 12cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * (the "License"); you may not use this file except in compliance with 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * the License. You may obtain a copy of the License at 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * http://www.apache.org/licenses/LICENSE-2.0 16cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Unless required by applicable law or agreed to in writing, software 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * distributed under the License is distributed on an "AS IS" BASIS, 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * See the License for the specific language governing permissions and 21cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * limitations under the License. 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * ==================================================================== 23cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * 24cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * This software consists of voluntary contributions made by many 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * individuals on behalf of the Apache Software Foundation. For more 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * information on the Apache Software Foundation, please see 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * <http://www.apache.org/>. 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wangpackage org.apache.http.client.utils; 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wangimport java.net.URI; 33cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projectimport java.net.URISyntaxException; 34cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wangimport org.apache.http.HttpHost; 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/** 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * A collection of utilities for {@link URI URIs}, to workaround 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * bugs within the class or for ease-of-use features. 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wangpublic class URIUtils { 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Constructs a {@link URI} using all the parameters. This should be 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * used instead of 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * {@link URI#URI(String, String, String, int, String, String, String)} 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * or any of the other URI multi-argument URI constructors. 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * See <a 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * href="https://issues.apache.org/jira/browse/HTTPCLIENT-730">HTTPCLIENT-730</a> 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * for more information. 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param scheme 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Scheme name 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param host 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Host name 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param port 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Port number 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param path 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Path 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param query 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Query 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param fragment 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Fragment 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @throws URISyntaxException 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * If both a scheme and a path are given but the path is 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * relative, if the URI string constructed from the given 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * components violates RFC 2396, or if the authority 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * component of the string is present but cannot be parsed 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * as a server-based authority 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang public static URI createURI( 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang final String scheme, 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang final String host, 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int port, 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang final String path, 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang final String query, 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang final String fragment) throws URISyntaxException { 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 81cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project StringBuilder buffer = new StringBuilder(); 82cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (host != null) { 83cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (scheme != null) { 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(scheme); 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append("://"); 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(host); 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (port > 0) { 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(':'); 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(port); 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (path == null || !path.startsWith("/")) { 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append('/'); 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (path != null) { 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(path); 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (query != null) { 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append('?'); 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(query); 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fragment != null) { 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append('#'); 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang buffer.append(fragment); 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return new URI(buffer.toString()); 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * A convenience method for creating a new {@link URI} whose scheme, host 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * and port are taken from the target host, but whose path, query and 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * fragment are taken from the existing URI. The fragment is only used if 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * dropFragment is false. 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param uri 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Contains the path, query and fragment to use. 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param target 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Contains the scheme, host and port to use. 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param dropFragment 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * True if the fragment should not be copied. 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @throws URISyntaxException 124cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * If the resulting URI is invalid. 125cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 126cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project public static URI rewriteURI( 127cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project final URI uri, 128cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project final HttpHost target, 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang boolean dropFragment) throws URISyntaxException { 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (uri == null) { 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang throw new IllegalArgumentException("URI may nor be null"); 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (target != null) { 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return URIUtils.createURI( 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang target.getSchemeName(), 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang target.getHostName(), 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang target.getPort(), 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang uri.getRawPath(), 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang uri.getRawQuery(), 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang dropFragment ? null : uri.getRawFragment()); 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } else { 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return URIUtils.createURI( 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang null, 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang null, 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang -1, 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang uri.getRawPath(), 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang uri.getRawQuery(), 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang dropFragment ? null : uri.getRawFragment()); 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * A convenience method for 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * {@link URIUtils#rewriteURI(URI, HttpHost, boolean)} that always keeps the 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * fragment. 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang public static URI rewriteURI( 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang final URI uri, 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang final HttpHost target) throws URISyntaxException { 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return rewriteURI(uri, target, false); 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Resolves a URI reference against a base URI. Work-around for bug in 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>) 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param baseURI the base URI 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param reference the URI reference 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @return the resulting URI 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang public static URI resolve(final URI baseURI, final String reference) { 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return URIUtils.resolve(baseURI, URI.create(reference)); 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Resolves a URI reference against a base URI. Work-around for bug in 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>) 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param baseURI the base URI 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @param reference the URI reference 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * @return the resulting URI 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang public static URI resolve(final URI baseURI, URI reference){ 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (baseURI == null) { 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang throw new IllegalArgumentException("Base URI may nor be null"); 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (reference == null) { 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang throw new IllegalArgumentException("Reference URI may nor be null"); 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang boolean emptyReference = reference.toString().length() == 0; 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (emptyReference) { 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang reference = URI.create("#"); 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang URI resolved = baseURI.resolve(reference); 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (emptyReference) { 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang String resolvedString = resolved.toString(); 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang resolved = URI.create(resolvedString.substring(0, 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang resolvedString.indexOf('#'))); 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return resolved; 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /** 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * This class should not be instantiated. 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang private URIUtils() { 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang