URIUtils.java revision 069490a5ca2fd1988d29daf45d892f47ad665115
1/*
2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/client/utils/URIUtils.java $
3 * $Revision: 653041 $
4 * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 2008) $
5 *
6 * ====================================================================
7 *
8 *  Licensed to the Apache Software Foundation (ASF) under one or more
9 *  contributor license agreements.  See the NOTICE file distributed with
10 *  this work for additional information regarding copyright ownership.
11 *  The ASF licenses this file to You under the Apache License, Version 2.0
12 *  (the "License"); you may not use this file except in compliance with
13 *  the License.  You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 *  Unless required by applicable law or agreed to in writing, software
18 *  distributed under the License is distributed on an "AS IS" BASIS,
19 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 *  See the License for the specific language governing permissions and
21 *  limitations under the License.
22 * ====================================================================
23 *
24 * This software consists of voluntary contributions made by many
25 * individuals on behalf of the Apache Software Foundation.  For more
26 * information on the Apache Software Foundation, please see
27 * <http://www.apache.org/>.
28 *
29 */
30package org.apache.http.client.utils;
31
32import java.net.URI;
33import java.net.URISyntaxException;
34
35import org.apache.http.HttpHost;
36
37/**
38 * A collection of utilities for {@link URI URIs}, to workaround
39 * bugs within the class or for ease-of-use features.
40 */
41public class URIUtils {
42
43     /**
44         * Constructs a {@link URI} using all the parameters. This should be
45         * used instead of
46         * {@link URI#URI(String, String, String, int, String, String, String)}
47         * or any of the other URI multi-argument URI constructors.
48         *
49         * See <a
50         * href="https://issues.apache.org/jira/browse/HTTPCLIENT-730">HTTPCLIENT-730</a>
51         * for more information.
52         *
53         * @param scheme
54         *            Scheme name
55         * @param host
56         *            Host name
57         * @param port
58         *            Port number
59         * @param path
60         *            Path
61         * @param query
62         *            Query
63         * @param fragment
64         *            Fragment
65         *
66         * @throws URISyntaxException
67         *             If both a scheme and a path are given but the path is
68         *             relative, if the URI string constructed from the given
69         *             components violates RFC&nbsp;2396, or if the authority
70         *             component of the string is present but cannot be parsed
71         *             as a server-based authority
72         */
73    public static URI createURI(
74            final String scheme,
75            final String host,
76            int port,
77            final String path,
78            final String query,
79            final String fragment) throws URISyntaxException {
80
81        StringBuilder buffer = new StringBuilder();
82        if (host != null) {
83            if (scheme != null) {
84                buffer.append(scheme);
85                buffer.append("://");
86            }
87            buffer.append(host);
88            if (port > 0) {
89                buffer.append(':');
90                buffer.append(port);
91            }
92        }
93        if (path == null || !path.startsWith("/")) {
94            buffer.append('/');
95        }
96        if (path != null) {
97            buffer.append(path);
98        }
99        if (query != null) {
100            buffer.append('?');
101            buffer.append(query);
102        }
103        if (fragment != null) {
104            buffer.append('#');
105            buffer.append(fragment);
106        }
107        return new URI(buffer.toString());
108    }
109
110    /**
111     * A convenience method for creating a new {@link URI} whose scheme, host
112     * and port are taken from the target host, but whose path, query and
113     * fragment are taken from the existing URI. The fragment is only used if
114     * dropFragment is false.
115     *
116     * @param uri
117     *            Contains the path, query and fragment to use.
118     * @param target
119     *            Contains the scheme, host and port to use.
120     * @param dropFragment
121     *            True if the fragment should not be copied.
122     *
123     * @throws URISyntaxException
124     *             If the resulting URI is invalid.
125     */
126    public static URI rewriteURI(
127            final URI uri,
128            final HttpHost target,
129            boolean dropFragment) throws URISyntaxException {
130        if (uri == null) {
131            throw new IllegalArgumentException("URI may nor be null");
132        }
133        if (target != null) {
134            return URIUtils.createURI(
135                    target.getSchemeName(),
136                    target.getHostName(),
137                    target.getPort(),
138                    uri.getRawPath(),
139                    uri.getRawQuery(),
140                    dropFragment ? null : uri.getRawFragment());
141        } else {
142            return URIUtils.createURI(
143                    null,
144                    null,
145                    -1,
146                    uri.getRawPath(),
147                    uri.getRawQuery(),
148                    dropFragment ? null : uri.getRawFragment());
149        }
150    }
151
152    /**
153     * A convenience method for
154     * {@link URIUtils#rewriteURI(URI, HttpHost, boolean)} that always keeps the
155     * fragment.
156     */
157    public static URI rewriteURI(
158            final URI uri,
159            final HttpHost target) throws URISyntaxException {
160        return rewriteURI(uri, target, false);
161    }
162
163    /**
164     * Resolves a URI reference against a base URI. Work-around for bug in
165     * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
166     *
167     * @param baseURI the base URI
168     * @param reference the URI reference
169     * @return the resulting URI
170     */
171    public static URI resolve(final URI baseURI, final String reference) {
172        return URIUtils.resolve(baseURI, URI.create(reference));
173    }
174
175    /**
176     * Resolves a URI reference against a base URI. Work-around for bug in
177     * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
178     *
179     * @param baseURI the base URI
180     * @param reference the URI reference
181     * @return the resulting URI
182     */
183    public static URI resolve(final URI baseURI, URI reference){
184        if (baseURI == null) {
185            throw new IllegalArgumentException("Base URI may nor be null");
186        }
187        if (reference == null) {
188            throw new IllegalArgumentException("Reference URI may nor be null");
189        }
190        boolean emptyReference = reference.toString().length() == 0;
191        if (emptyReference) {
192            reference = URI.create("#");
193        }
194        URI resolved = baseURI.resolve(reference);
195        if (emptyReference) {
196            String resolvedString = resolved.toString();
197            resolved = URI.create(resolvedString.substring(0,
198                resolvedString.indexOf('#')));
199        }
200        return resolved;
201    }
202
203    /**
204     * This class should not be instantiated.
205     */
206    private URIUtils() {
207    }
208
209}
210