View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.repository;
20  
21  import java.io.File;
22  import java.net.URI;
23  
24  /**
25   * URL handling for file URLs. Based on org.apache.maven.wagon.PathUtils.
26   *
27   * @since 2.0.0
28   */
29  public final class RepositoryUriUtils {
30  
31      private RepositoryUriUtils() {}
32  
33      public static URI toUri(String repositoryUrl) {
34          final String protocol = protocol(repositoryUrl);
35          if ("file".equals(protocol)
36                  || protocol.isEmpty()
37                  || protocol.length() == 1
38                          && (Character.isLetter(protocol.charAt(0)) && Character.isUpperCase(protocol.charAt(0)))) {
39              return new File(basedir(repositoryUrl)).toURI();
40          } else {
41              return URI.create(repositoryUrl);
42          }
43      }
44  
45      /**
46       * Return the protocol name.
47       *
48       * @param url the url
49       * @return the protocol or empty string.
50       */
51      private static String protocol(final String url) {
52          final int pos = url.indexOf(":");
53  
54          if (pos == -1) {
55              return "";
56          }
57          return url.substring(0, pos).trim();
58      }
59  
60      /**
61       * Derive the path portion of the given URL.
62       *
63       * @param url the file-repository URL
64       * @return the basedir of the repository
65       */
66      private static String basedir(String url) {
67          String protocol = protocol(url);
68  
69          String retValue;
70  
71          if (!protocol.isEmpty()) {
72              retValue = url.substring(protocol.length() + 1);
73          } else {
74              retValue = url;
75          }
76          retValue = decode(retValue);
77          // special case: if omitted // on protocol, keep path as is
78          if (retValue.startsWith("//")) {
79              retValue = retValue.substring(2);
80  
81              if (retValue.length() >= 2 && (retValue.charAt(1) == '|' || retValue.charAt(1) == ':')) {
82                  // special case: if there is a windows drive letter, then keep the original return value
83                  retValue = retValue.charAt(0) + ":" + retValue.substring(2);
84              } else {
85                  // Now we expect the host
86                  int index = retValue.indexOf("/");
87                  if (index >= 0) {
88                      retValue = retValue.substring(index + 1);
89                  }
90  
91                  // special case: if there is a windows drive letter, then keep the original return value
92                  if (retValue.length() >= 2 && (retValue.charAt(1) == '|' || retValue.charAt(1) == ':')) {
93                      retValue = retValue.charAt(0) + ":" + retValue.substring(2);
94                  } else if (index >= 0) {
95                      // leading / was previously stripped
96                      retValue = "/" + retValue;
97                  }
98              }
99          }
100 
101         // special case: if there is a windows drive letter using |, switch to :
102         if (retValue.length() >= 2 && retValue.charAt(1) == '|') {
103             retValue = retValue.charAt(0) + ":" + retValue.substring(2);
104         }
105 
106         return retValue.trim();
107     }
108 
109     /**
110      * Decodes the specified (portion of a) URL. <strong>Note:</strong> This decoder assumes that ISO-8859-1 is used to
111      * convert URL-encoded octets to characters.
112      *
113      * @param url The URL to decode, may be <code>null</code>.
114      * @return The decoded URL or <code>null</code> if the input was <code>null</code>.
115      */
116     private static String decode(String url) {
117         String decoded = url;
118         if (url != null) {
119             int pos = -1;
120             while ((pos = decoded.indexOf('%', pos + 1)) >= 0) {
121                 if (pos + 2 < decoded.length()) {
122                     String hexStr = decoded.substring(pos + 1, pos + 3);
123                     char ch = (char) Integer.parseInt(hexStr, 16);
124                     decoded = decoded.substring(0, pos) + ch + decoded.substring(pos + 3);
125                 }
126             }
127         }
128         return decoded;
129     }
130 }