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&nbsp;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