1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.url; |
21 |
|
|
22 |
|
import java.io.UnsupportedEncodingException; |
23 |
|
import java.net.URI; |
24 |
|
import java.net.URISyntaxException; |
25 |
|
import java.net.URL; |
26 |
|
import java.net.URLDecoder; |
27 |
|
import java.net.URLEncoder; |
28 |
|
import java.util.ArrayList; |
29 |
|
import java.util.Arrays; |
30 |
|
import java.util.Collections; |
31 |
|
import java.util.LinkedHashMap; |
32 |
|
import java.util.List; |
33 |
|
import java.util.Map; |
34 |
|
|
35 |
|
import org.apache.commons.lang3.StringUtils; |
36 |
|
import org.apache.commons.lang3.builder.EqualsBuilder; |
37 |
|
import org.apache.commons.lang3.builder.HashCodeBuilder; |
38 |
|
import org.xwiki.resource.CreateResourceReferenceException; |
39 |
|
import org.xwiki.velocity.tools.EscapeTool; |
40 |
|
|
41 |
|
|
42 |
|
@link |
43 |
|
|
44 |
|
@version |
45 |
|
@since |
46 |
|
|
|
|
| 93% |
Uncovered Elements: 8 (114) |
Complexity: 30 |
Complexity Density: 0.4 |
|
47 |
|
public class ExtendedURL implements Cloneable |
48 |
|
{ |
49 |
|
|
50 |
|
|
51 |
|
|
52 |
|
private static final String URL_SEPARATOR = "/"; |
53 |
|
|
54 |
|
private static final String UTF8 = "UTF-8"; |
55 |
|
|
56 |
|
|
57 |
|
@see |
58 |
|
|
59 |
|
private URI uri; |
60 |
|
|
61 |
|
|
62 |
|
|
63 |
|
|
64 |
|
|
65 |
|
|
66 |
|
@see |
67 |
|
|
68 |
|
private URL wrappedURL; |
69 |
|
|
70 |
|
|
71 |
|
@see |
72 |
|
|
73 |
|
private List<String> segments; |
74 |
|
|
75 |
|
private Map<String, List<String>> parameters; |
76 |
|
|
77 |
|
|
78 |
|
@link |
79 |
|
|
80 |
|
private EscapeTool escapeTool = new EscapeTool(); |
81 |
|
|
82 |
|
|
83 |
|
|
84 |
|
|
85 |
|
@param |
86 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
87 |
36 |
public ExtendedURL(List<String> segments)... |
88 |
|
{ |
89 |
36 |
this(segments, Collections.<String, List<String>>emptyMap()); |
90 |
|
} |
91 |
|
|
92 |
|
|
93 |
|
|
94 |
|
|
95 |
|
@param |
96 |
|
@param |
97 |
|
@since |
98 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
99 |
51500 |
public ExtendedURL(List<String> segments, Map<String, List<String>> parameters)... |
100 |
|
{ |
101 |
51500 |
this.segments = new ArrayList<>(segments); |
102 |
51503 |
this.parameters = parameters; |
103 |
|
} |
104 |
|
|
105 |
|
|
106 |
|
@param |
107 |
|
@param |
108 |
|
|
109 |
|
@throws |
110 |
|
|
111 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (23) |
Complexity: 5 |
Complexity Density: 0.29 |
|
112 |
35279 |
public ExtendedURL(URL url, String ignorePrefix) throws CreateResourceReferenceException... |
113 |
|
{ |
114 |
35269 |
this.wrappedURL = url; |
115 |
|
|
116 |
|
|
117 |
|
|
118 |
35193 |
URI internalURI; |
119 |
35205 |
try { |
120 |
35239 |
internalURI = url.toURI(); |
121 |
|
} catch (URISyntaxException e) { |
122 |
1 |
throw new CreateResourceReferenceException(String.format("Invalid URL [%s]", url), e); |
123 |
|
} |
124 |
35255 |
this.uri = internalURI; |
125 |
|
|
126 |
|
|
127 |
35242 |
String rawPath = getURI().getRawPath(); |
128 |
35244 |
if (!StringUtils.isEmpty(ignorePrefix)) { |
129 |
|
|
130 |
35195 |
String normalizedIgnorePrefix = ignorePrefix; |
131 |
35173 |
if (!ignorePrefix.startsWith(URL_SEPARATOR)) { |
132 |
25 |
normalizedIgnorePrefix = URL_SEPARATOR + ignorePrefix; |
133 |
|
} |
134 |
|
|
135 |
35212 |
if (!getURI().getPath().startsWith(normalizedIgnorePrefix)) { |
136 |
1 |
throw new CreateResourceReferenceException( |
137 |
|
String.format("URL Path [%s] doesn't start with [%s]", getURI().getPath(), ignorePrefix)); |
138 |
|
} |
139 |
35200 |
rawPath = rawPath.substring(normalizedIgnorePrefix.length()); |
140 |
|
} |
141 |
|
|
142 |
|
|
143 |
35207 |
rawPath = StringUtils.removeStart(rawPath, URL_SEPARATOR); |
144 |
|
|
145 |
35234 |
this.segments = extractPathSegments(rawPath); |
146 |
35288 |
this.parameters = extractParameters(internalURI); |
147 |
|
} |
148 |
|
|
149 |
|
|
150 |
|
@return |
151 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
152 |
141435 |
public List<String> getSegments()... |
153 |
|
{ |
154 |
141448 |
return this.segments; |
155 |
|
} |
156 |
|
|
157 |
|
|
158 |
|
@return |
159 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
160 |
20963 |
public URL getWrappedURL()... |
161 |
|
{ |
162 |
20962 |
return this.wrappedURL; |
163 |
|
} |
164 |
|
|
165 |
|
|
166 |
|
@return |
167 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
168 |
70375 |
public URI getURI()... |
169 |
|
{ |
170 |
70439 |
return this.uri; |
171 |
|
} |
172 |
|
|
173 |
|
|
174 |
|
@return |
175 |
|
@since |
176 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
177 |
74288 |
public Map<String, List<String>> getParameters()... |
178 |
|
{ |
179 |
74287 |
return this.parameters; |
180 |
|
} |
181 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 3 |
Complexity Density: 0.3 |
|
182 |
35236 |
private Map<String, List<String>> extractParameters(URI uri)... |
183 |
|
{ |
184 |
35254 |
Map<String, List<String>> uriParameters; |
185 |
35265 |
if (uri.getQuery() != null) { |
186 |
17530 |
uriParameters = new LinkedHashMap<>(); |
187 |
17527 |
for (String nameValue : Arrays.asList(uri.getQuery().split("&"))) { |
188 |
28545 |
String[] pair = nameValue.split("=", 2); |
189 |
|
|
190 |
28554 |
if (pair.length == 2) { |
191 |
28367 |
addParameter(pair[0], pair[1], uriParameters); |
192 |
|
} else { |
193 |
187 |
addParameter(pair[0], null, uriParameters); |
194 |
|
} |
195 |
|
} |
196 |
|
} else { |
197 |
17719 |
uriParameters = Collections.emptyMap(); |
198 |
|
} |
199 |
35239 |
return uriParameters; |
200 |
|
} |
201 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (10) |
Complexity: 3 |
Complexity Density: 0.5 |
|
202 |
28544 |
private void addParameter(String name, String value, Map<String, List<String>> parameters)... |
203 |
|
{ |
204 |
28547 |
List<String> list = parameters.get(name); |
205 |
28545 |
if (list == null) { |
206 |
28075 |
list = new ArrayList<>(); |
207 |
|
} |
208 |
28547 |
if (value != null) { |
209 |
28360 |
list.add(value); |
210 |
|
} |
211 |
28548 |
parameters.put(name, list); |
212 |
|
} |
213 |
|
|
214 |
|
|
215 |
|
|
216 |
|
|
217 |
|
|
218 |
|
|
219 |
|
|
220 |
|
|
221 |
|
|
222 |
|
@param |
223 |
|
@return |
224 |
|
|
|
|
| 92.3% |
Uncovered Elements: 1 (13) |
Complexity: 3 |
Complexity Density: 0.27 |
|
225 |
35235 |
private List<String> extractPathSegments(String rawPath)... |
226 |
|
{ |
227 |
35247 |
List<String> urlSegments = new ArrayList<String>(); |
228 |
|
|
229 |
35237 |
if (StringUtils.isEmpty(rawPath)) { |
230 |
3 |
return urlSegments; |
231 |
|
} |
232 |
|
|
233 |
|
|
234 |
|
|
235 |
|
|
236 |
35222 |
for (String pathSegment : rawPath.split(URL_SEPARATOR, -1)) { |
237 |
|
|
238 |
|
|
239 |
161561 |
String normalizedPathSegment = pathSegment.split(";", 2)[0]; |
240 |
|
|
241 |
|
|
242 |
161609 |
String decodedPathSegment; |
243 |
161642 |
try { |
244 |
|
|
245 |
|
|
246 |
|
|
247 |
|
|
248 |
|
|
249 |
161651 |
decodedPathSegment = URLDecoder.decode(normalizedPathSegment, UTF8); |
250 |
|
} catch (UnsupportedEncodingException e) { |
251 |
|
|
252 |
|
|
253 |
0 |
throw new RuntimeException( |
254 |
|
String.format("Failed to URL decode [%s] using UTF-8.", normalizedPathSegment), e); |
255 |
|
} |
256 |
|
|
257 |
161533 |
urlSegments.add(decodedPathSegment); |
258 |
|
} |
259 |
|
|
260 |
35286 |
return urlSegments; |
261 |
|
} |
262 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
263 |
0 |
@Override... |
264 |
|
public int hashCode() |
265 |
|
{ |
266 |
0 |
return new HashCodeBuilder(7, 7) |
267 |
|
.append(getURI()) |
268 |
|
.append(getSegments()) |
269 |
|
.toHashCode(); |
270 |
|
} |
271 |
|
|
|
|
| 71.4% |
Uncovered Elements: 4 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
272 |
6 |
@Override... |
273 |
|
public boolean equals(Object object) |
274 |
|
{ |
275 |
6 |
if (object == null) { |
276 |
0 |
return false; |
277 |
|
} |
278 |
6 |
if (object == this) { |
279 |
1 |
return true; |
280 |
|
} |
281 |
5 |
if (object.getClass() != getClass()) { |
282 |
0 |
return false; |
283 |
|
} |
284 |
5 |
ExtendedURL rhs = (ExtendedURL) object; |
285 |
5 |
return new EqualsBuilder() |
286 |
|
.append(getURI(), rhs.getURI()) |
287 |
|
.append(getSegments(), rhs.getSegments()) |
288 |
|
.isEquals(); |
289 |
|
} |
290 |
|
|
291 |
|
|
292 |
|
@return |
293 |
|
|
294 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (13) |
Complexity: 2 |
Complexity Density: 0.18 |
|
295 |
25754 |
public String serialize()... |
296 |
|
{ |
297 |
25754 |
StringBuilder builder = new StringBuilder(); |
298 |
25754 |
List<String> encodedSegments = new ArrayList<>(); |
299 |
25754 |
for (String path : getSegments()) { |
300 |
162206 |
encodedSegments.add(encodeSegment(path)); |
301 |
|
} |
302 |
25755 |
builder.append(URL_SEPARATOR); |
303 |
25753 |
builder.append(StringUtils.join(encodedSegments, URL_SEPARATOR)); |
304 |
25754 |
Map<String, List<String>> uriParameters = getParameters(); |
305 |
25753 |
if (!uriParameters.isEmpty()) { |
306 |
9045 |
builder.append('?'); |
307 |
9046 |
builder.append(this.escapeTool.url(uriParameters)); |
308 |
|
} |
309 |
25754 |
return builder.toString(); |
310 |
|
} |
311 |
|
|
|
|
| 66.7% |
Uncovered Elements: 1 (3) |
Complexity: 2 |
Complexity Density: 0.67 |
|
312 |
162206 |
private String encodeSegment(String value)... |
313 |
|
{ |
314 |
162206 |
try { |
315 |
162207 |
return URLEncoder.encode(value, UTF8); |
316 |
|
} catch (UnsupportedEncodingException e) { |
317 |
|
|
318 |
|
|
319 |
0 |
throw new RuntimeException(String.format("Failed to URL encode [%s] using UTF-8.", value), e); |
320 |
|
} |
321 |
|
} |
322 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
323 |
10 |
@Override... |
324 |
|
public String toString() |
325 |
|
{ |
326 |
10 |
return serialize(); |
327 |
|
} |
328 |
|
} |