mobile/android/thirdparty/ch/boye/httpclientandroidlib/client/utils/URIUtils.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * ====================================================================
     3  *
     4  *  Licensed to the Apache Software Foundation (ASF) under one or more
     5  *  contributor license agreements.  See the NOTICE file distributed with
     6  *  this work for additional information regarding copyright ownership.
     7  *  The ASF licenses this file to You under the Apache License, Version 2.0
     8  *  (the "License"); you may not use this file except in compliance with
     9  *  the License.  You may obtain a copy of the License at
    10  *
    11  *      http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  *  Unless required by applicable law or agreed to in writing, software
    14  *  distributed under the License is distributed on an "AS IS" BASIS,
    15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  *  See the License for the specific language governing permissions and
    17  *  limitations under the License.
    18  * ====================================================================
    19  *
    20  * This software consists of voluntary contributions made by many
    21  * individuals on behalf of the Apache Software Foundation.  For more
    22  * information on the Apache Software Foundation, please see
    23  * <http://www.apache.org/>.
    24  *
    25  */
    27 package ch.boye.httpclientandroidlib.client.utils;
    29 import java.net.URI;
    30 import java.net.URISyntaxException;
    31 import java.util.Stack;
    33 import ch.boye.httpclientandroidlib.annotation.Immutable;
    35 import ch.boye.httpclientandroidlib.HttpHost;
    37 /**
    38  * A collection of utilities for {@link URI URIs}, to workaround
    39  * bugs within the class or for ease-of-use features.
    40  *
    41  * @since 4.0
    42  */
    43 @Immutable
    44 public class URIUtils {
    46      /**
    47          * Constructs a {@link URI} using all the parameters. This should be
    48          * used instead of
    49          * {@link URI#URI(String, String, String, int, String, String, String)}
    50          * or any of the other URI multi-argument URI constructors.
    51          *
    52          * @param scheme
    53          *            Scheme name
    54          * @param host
    55          *            Host name
    56          * @param port
    57          *            Port number
    58          * @param path
    59          *            Path
    60          * @param query
    61          *            Query
    62          * @param fragment
    63          *            Fragment
    64          *
    65          * @throws URISyntaxException
    66          *             If both a scheme and a path are given but the path is
    67          *             relative, if the URI string constructed from the given
    68          *             components violates RFC&nbsp;2396, or if the authority
    69          *             component of the string is present but cannot be parsed
    70          *             as a server-based authority
    71          */
    72     public static URI createURI(
    73             final String scheme,
    74             final String host,
    75             int port,
    76             final String path,
    77             final String query,
    78             final String fragment) throws URISyntaxException {
    80         StringBuilder buffer = new StringBuilder();
    81         if (host != null) {
    82             if (scheme != null) {
    83                 buffer.append(scheme);
    84                 buffer.append("://");
    85             }
    86             buffer.append(host);
    87             if (port > 0) {
    88                 buffer.append(':');
    89                 buffer.append(port);
    90             }
    91         }
    92         if (path == null || !path.startsWith("/")) {
    93             buffer.append('/');
    94         }
    95         if (path != null) {
    96             buffer.append(path);
    97         }
    98         if (query != null) {
    99             buffer.append('?');
   100             buffer.append(query);
   101         }
   102         if (fragment != null) {
   103             buffer.append('#');
   104             buffer.append(fragment);
   105         }
   106         return new URI(buffer.toString());
   107     }
   109     /**
   110      * A convenience method for creating a new {@link URI} whose scheme, host
   111      * and port are taken from the target host, but whose path, query and
   112      * fragment are taken from the existing URI. The fragment is only used if
   113      * dropFragment is false.
   114      *
   115      * @param uri
   116      *            Contains the path, query and fragment to use.
   117      * @param target
   118      *            Contains the scheme, host and port to use.
   119      * @param dropFragment
   120      *            True if the fragment should not be copied.
   121      *
   122      * @throws URISyntaxException
   123      *             If the resulting URI is invalid.
   124      */
   125     public static URI rewriteURI(
   126             final URI uri,
   127             final HttpHost target,
   128             boolean dropFragment) throws URISyntaxException {
   129         if (uri == null) {
   130             throw new IllegalArgumentException("URI may nor be null");
   131         }
   132         if (target != null) {
   133             return URIUtils.createURI(
   134                     target.getSchemeName(),
   135                     target.getHostName(),
   136                     target.getPort(),
   137                     normalizePath(uri.getRawPath()),
   138                     uri.getRawQuery(),
   139                     dropFragment ? null : uri.getRawFragment());
   140         } else {
   141             return URIUtils.createURI(
   142                     null,
   143                     null,
   144                     -1,
   145                     normalizePath(uri.getRawPath()),
   146                     uri.getRawQuery(),
   147                     dropFragment ? null : uri.getRawFragment());
   148         }
   149     }
   151     private static String normalizePath(String path) {
   152         if (path == null) {
   153             return null;
   154         }
   155         int n = 0;
   156         for (; n < path.length(); n++) {
   157             if (path.charAt(n) != '/') {
   158                 break;
   159             }
   160         }
   161         if (n > 1) {
   162             path = path.substring(n - 1);
   163         }
   164         return path;
   165     }
   167     /**
   168      * A convenience method for
   169      * {@link URIUtils#rewriteURI(URI, HttpHost, boolean)} that always keeps the
   170      * fragment.
   171      */
   172     public static URI rewriteURI(
   173             final URI uri,
   174             final HttpHost target) throws URISyntaxException {
   175         return rewriteURI(uri, target, false);
   176     }
   178     /**
   179      * Resolves a URI reference against a base URI. Work-around for bug in
   180      * java.net.URI (<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
   181      *
   182      * @param baseURI the base URI
   183      * @param reference the URI reference
   184      * @return the resulting URI
   185      */
   186     public static URI resolve(final URI baseURI, final String reference) {
   187         return URIUtils.resolve(baseURI, URI.create(reference));
   188     }
   190     /**
   191      * Resolves a URI reference against a base URI. Work-around for bugs in
   192      * java.net.URI (e.g. <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4708535>)
   193      *
   194      * @param baseURI the base URI
   195      * @param reference the URI reference
   196      * @return the resulting URI
   197      */
   198     public static URI resolve(final URI baseURI, URI reference){
   199         if (baseURI == null) {
   200             throw new IllegalArgumentException("Base URI may nor be null");
   201         }
   202         if (reference == null) {
   203             throw new IllegalArgumentException("Reference URI may nor be null");
   204         }
   205         String s = reference.toString();
   206         if (s.startsWith("?")) {
   207             return resolveReferenceStartingWithQueryString(baseURI, reference);
   208         }
   209         boolean emptyReference = s.length() == 0;
   210         if (emptyReference) {
   211             reference = URI.create("#");
   212         }
   213         URI resolved = baseURI.resolve(reference);
   214         if (emptyReference) {
   215             String resolvedString = resolved.toString();
   216             resolved = URI.create(resolvedString.substring(0,
   217                 resolvedString.indexOf('#')));
   218         }
   219         return removeDotSegments(resolved);
   220     }
   222     /**
   223      * Resolves a reference starting with a query string.
   224      *
   225      * @param baseURI the base URI
   226      * @param reference the URI reference starting with a query string
   227      * @return the resulting URI
   228      */
   229     private static URI resolveReferenceStartingWithQueryString(
   230             final URI baseURI, final URI reference) {
   231         String baseUri = baseURI.toString();
   232         baseUri = baseUri.indexOf('?') > -1 ?
   233             baseUri.substring(0, baseUri.indexOf('?')) : baseUri;
   234         return URI.create(baseUri + reference.toString());
   235     }
   237     /**
   238      * Removes dot segments according to RFC 3986, section 5.2.4
   239      *
   240      * @param uri the original URI
   241      * @return the URI without dot segments
   242      */
   243     private static URI removeDotSegments(URI uri) {
   244         String path = uri.getPath();
   245         if ((path == null) || (path.indexOf("/.") == -1)) {
   246             // No dot segments to remove
   247             return uri;
   248         }
   249         String[] inputSegments = path.split("/");
   250         Stack<String> outputSegments = new Stack<String>();
   251         for (int i = 0; i < inputSegments.length; i++) {
   252             if ((inputSegments[i].length() == 0)
   253                 || (".".equals(inputSegments[i]))) {
   254                 // Do nothing
   255             } else if ("..".equals(inputSegments[i])) {
   256                 if (!outputSegments.isEmpty()) {
   257                     outputSegments.pop();
   258                 }
   259             } else {
   260                 outputSegments.push(inputSegments[i]);
   261             }
   262         }
   263         StringBuilder outputBuffer = new StringBuilder();
   264         for (String outputSegment : outputSegments) {
   265             outputBuffer.append('/').append(outputSegment);
   266         }
   267         try {
   268             return new URI(uri.getScheme(), uri.getAuthority(),
   269                 outputBuffer.toString(), uri.getQuery(), uri.getFragment());
   270         } catch (URISyntaxException e) {
   271             throw new IllegalArgumentException(e);
   272         }
   273     }
   275     /**
   276      * Extracts target host from the given {@link URI}.
   277      * 
   278      * @param uri 
   279      * @return the target host if the URI is absolute or <code>null</null> if the URI is 
   280      * relative or does not contain a valid host name.
   281      * 
   282      * @since 4.1
   283      */
   284     public static HttpHost extractHost(final URI uri) {
   285         if (uri == null) {
   286             return null;
   287         }
   288         HttpHost target = null;
   289         if (uri.isAbsolute()) {
   290             int port = uri.getPort(); // may be overridden later
   291             String host = uri.getHost();
   292             if (host == null) { // normal parse failed; let's do it ourselves
   293                 // authority does not seem to care about the valid character-set for host names
   294                 host = uri.getAuthority();
   295                 if (host != null) {
   296                     // Strip off any leading user credentials
   297                     int at = host.indexOf('@');
   298                     if (at >= 0) {
   299                         if (host.length() > at+1 ) {
   300                             host = host.substring(at+1);
   301                         } else {
   302                             host = null; // @ on its own
   303                         }
   304                     }
   305                     // Extract the port suffix, if present
   306                     if (host != null) { 
   307                         int colon = host.indexOf(':');
   308                         if (colon >= 0) {
   309                             if (colon+1 < host.length()) {
   310                                 port = Integer.parseInt(host.substring(colon+1));
   311                             }
   312                             host = host.substring(0,colon);
   313                         }                
   314                     }                    
   315                 }
   316             }
   317             String scheme = uri.getScheme();
   318             if (host != null) {
   319                 target = new HttpHost(host, port, scheme);
   320             }
   321         }
   322         return target;
   323     }
   325     /**
   326      * This class should not be instantiated.
   327      */
   328     private URIUtils() {
   329     }
   331 }

mercurial