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 }