@@ -25,24 +25,27 @@ final class UriParser {
25
25
public String path ;
26
26
public String userInfo ;
27
27
28
- private int start , end = 0 ;
29
- private String urlWithoutQuery ;
28
+ private String originalUrl ;
29
+ private int start , end , currentIndex = 0 ;
30
30
31
- private void trimRight (String originalUrl ) {
32
- end = originalUrl .length ();
33
- while (end > 0 && originalUrl .charAt (end - 1 ) <= ' ' )
34
- end --;
35
- }
36
-
37
- private void trimLeft (String originalUrl ) {
38
- while (start < end && originalUrl .charAt (start ) <= ' ' )
31
+ private void trimLeft () {
32
+ while (start < end && originalUrl .charAt (start ) <= ' ' ) {
39
33
start ++;
34
+ }
40
35
41
- if (originalUrl .regionMatches (true , start , "url:" , 0 , 4 ))
36
+ if (originalUrl .regionMatches (true , start , "url:" , 0 , 4 )) {
42
37
start += 4 ;
38
+ }
43
39
}
44
40
45
- private boolean isFragmentOnly (String originalUrl ) {
41
+ private void trimRight () {
42
+ end = originalUrl .length ();
43
+ while (end > 0 && originalUrl .charAt (end - 1 ) <= ' ' ) {
44
+ end --;
45
+ }
46
+ }
47
+
48
+ private boolean isFragmentOnly () {
46
49
return start < originalUrl .length () && originalUrl .charAt (start ) == '#' ;
47
50
}
48
51
@@ -52,8 +55,9 @@ private boolean isValidProtocolChar(char c) {
52
55
53
56
private boolean isValidProtocolChars (String protocol ) {
54
57
for (int i = 1 ; i < protocol .length (); i ++) {
55
- if (!isValidProtocolChar (protocol .charAt (i )))
58
+ if (!isValidProtocolChar (protocol .charAt (i ))) {
56
59
return false ;
60
+ }
57
61
}
58
62
return true ;
59
63
}
@@ -62,32 +66,34 @@ private boolean isValidProtocol(String protocol) {
62
66
return protocol .length () > 0 && Character .isLetter (protocol .charAt (0 )) && isValidProtocolChars (protocol );
63
67
}
64
68
65
- private void computeInitialScheme (String originalUrl ) {
66
- for (int i = start ; i < end ; i ++) {
69
+ private void computeInitialScheme () {
70
+ for (int i = currentIndex ; i < end ; i ++) {
67
71
char c = originalUrl .charAt (i );
68
72
if (c == ':' ) {
69
- String s = originalUrl .substring (start , i );
73
+ String s = originalUrl .substring (currentIndex , i );
70
74
if (isValidProtocol (s )) {
71
- scheme = s .toLowerCase ();
72
- start = i + 1 ;
75
+ scheme = s .toLowerCase ();
76
+ currentIndex = i + 1 ;
73
77
}
74
78
break ;
75
- } else if (c == '/' )
79
+ } else if (c == '/' ) {
76
80
break ;
81
+ }
77
82
}
78
83
}
79
84
80
- private boolean overrideWithContext (Uri context , String originalUrl ) {
85
+ private boolean overrideWithContext (Uri context ) {
81
86
82
87
boolean isRelative = false ;
83
88
84
- // only use context if the schemes match
89
+ // use context only if schemes match
85
90
if (context != null && (scheme == null || scheme .equalsIgnoreCase (context .getScheme ()))) {
86
91
87
92
// see RFC2396 5.2.3
88
93
String contextPath = context .getPath ();
89
- if (isNonEmpty (contextPath ) && contextPath .charAt (0 ) == '/' )
90
- scheme = null ;
94
+ if (isNonEmpty (contextPath ) && contextPath .charAt (0 ) == '/' ) {
95
+ scheme = null ;
96
+ }
91
97
92
98
if (scheme == null ) {
93
99
scheme = context .getScheme ();
@@ -101,63 +107,67 @@ private boolean overrideWithContext(Uri context, String originalUrl) {
101
107
return isRelative ;
102
108
}
103
109
104
- private void computeFragment (String originalUrl ) {
105
- int charpPosition = originalUrl .indexOf ('#' , start );
110
+ private int findWithinCurrentRange (char c ) {
111
+ int pos = originalUrl .indexOf (c , currentIndex );
112
+ return pos > end ? -1 : pos ;
113
+ }
114
+
115
+ private void trimFragment () {
116
+ int charpPosition = findWithinCurrentRange ('#' );
106
117
if (charpPosition >= 0 ) {
107
118
end = charpPosition ;
108
119
}
109
120
}
110
121
111
122
private void inheritContextQuery (Uri context , boolean isRelative ) {
112
123
// see RFC2396 5.2.2: query and fragment inheritance
113
- if (isRelative && start == end ) {
124
+ if (isRelative && currentIndex == end ) {
114
125
query = context .getQuery ();
115
126
}
116
127
}
117
128
118
- private boolean splitUrlAndQuery (String originalUrl ) {
119
- boolean queryOnly = false ;
120
- urlWithoutQuery = originalUrl ;
121
- if (start < end ) {
122
- int askPosition = originalUrl .indexOf ('?' );
123
- queryOnly = askPosition == start ;
124
- if (askPosition != -1 && askPosition < end ) {
129
+ private boolean computeQuery () {
130
+ if (currentIndex < end ) {
131
+ int askPosition = findWithinCurrentRange ('?' );
132
+ if (askPosition != -1 ) {
125
133
query = originalUrl .substring (askPosition + 1 , end );
126
- if (end > askPosition )
134
+ if (end > askPosition ) {
127
135
end = askPosition ;
128
- urlWithoutQuery = originalUrl .substring (0 , askPosition );
136
+ }
137
+ return askPosition == currentIndex ;
129
138
}
130
139
}
131
-
132
- return queryOnly ;
140
+ return false ;
133
141
}
134
142
135
143
private boolean currentPositionStartsWith4Slashes () {
136
- return urlWithoutQuery .regionMatches (start , "////" , 0 , 4 );
144
+ return originalUrl .regionMatches (currentIndex , "////" , 0 , 4 );
137
145
}
138
146
139
147
private boolean currentPositionStartsWith2Slashes () {
140
- return urlWithoutQuery .regionMatches (start , "//" , 0 , 2 );
148
+ return originalUrl .regionMatches (currentIndex , "//" , 0 , 2 );
141
149
}
142
150
143
151
private void computeAuthority () {
144
- int authorityEndPosition = urlWithoutQuery . indexOf ('/' , start );
145
- if (authorityEndPosition < 0 ) {
146
- authorityEndPosition = urlWithoutQuery . indexOf ('?' , start );
147
- if (authorityEndPosition < 0 )
152
+ int authorityEndPosition = findWithinCurrentRange ('/' );
153
+ if (authorityEndPosition == - 1 ) {
154
+ authorityEndPosition = findWithinCurrentRange ('?' );
155
+ if (authorityEndPosition == - 1 ) {
148
156
authorityEndPosition = end ;
157
+ }
149
158
}
150
- host = authority = urlWithoutQuery .substring (start , authorityEndPosition );
151
- start = authorityEndPosition ;
159
+ host = authority = originalUrl .substring (currentIndex , authorityEndPosition );
160
+ currentIndex = authorityEndPosition ;
152
161
}
153
162
154
163
private void computeUserInfo () {
155
164
int atPosition = authority .indexOf ('@' );
156
165
if (atPosition != -1 ) {
157
166
userInfo = authority .substring (0 , atPosition );
158
167
host = authority .substring (atPosition + 1 );
159
- } else
168
+ } else {
160
169
userInfo = null ;
170
+ }
161
171
}
162
172
163
173
private boolean isMaybeIPV6 () {
@@ -179,14 +189,16 @@ private void computeIPV6() {
179
189
if (host .length () > portPosition ) {
180
190
port = Integer .parseInt (host .substring (portPosition ));
181
191
}
182
- } else
192
+ } else {
183
193
throw new IllegalArgumentException ("Invalid authority field: " + authority );
194
+ }
184
195
}
185
196
186
197
host = host .substring (0 , positionAfterClosingSquareBrace );
187
198
188
- } else
199
+ } else {
189
200
throw new IllegalArgumentException ("Invalid authority field: " + authority );
201
+ }
190
202
}
191
203
192
204
private void computeRegularHostPort () {
@@ -218,39 +230,44 @@ private void removeEmbedded2Dots() {
218
230
} else if (end == 0 ) {
219
231
break ;
220
232
}
221
- } else
233
+ } else {
222
234
i = i + 3 ;
235
+ }
223
236
}
224
237
}
225
238
226
239
private void removeTailing2Dots () {
227
240
while (path .endsWith ("/.." )) {
228
241
end = path .lastIndexOf ('/' , path .length () - 4 );
229
- if (end >= 0 )
242
+ if (end >= 0 ) {
230
243
path = path .substring (0 , end + 1 );
231
- else
244
+ } else {
232
245
break ;
246
+ }
233
247
}
234
248
}
235
249
236
250
private void removeStartingDot () {
237
- if (path .startsWith ("./" ) && path .length () > 2 )
251
+ if (path .startsWith ("./" ) && path .length () > 2 ) {
238
252
path = path .substring (2 );
253
+ }
239
254
}
240
255
241
256
private void removeTrailingDot () {
242
- if (path .endsWith ("/." ))
257
+ if (path .endsWith ("/." )) {
243
258
path = path .substring (0 , path .length () - 1 );
259
+ }
244
260
}
245
261
246
262
private void handleRelativePath () {
247
263
int lastSlashPosition = path .lastIndexOf ('/' );
248
- String pathEnd = urlWithoutQuery .substring (start , end );
264
+ String pathEnd = originalUrl .substring (currentIndex , end );
249
265
250
- if (lastSlashPosition == -1 )
266
+ if (lastSlashPosition == -1 ) {
251
267
path = authority != null ? "/" + pathEnd : pathEnd ;
252
- else
268
+ } else {
253
269
path = path .substring (0 , lastSlashPosition + 1 ) + pathEnd ;
270
+ }
254
271
}
255
272
256
273
private void handlePathDots () {
@@ -265,36 +282,37 @@ private void handlePathDots() {
265
282
266
283
private void parseAuthority () {
267
284
if (!currentPositionStartsWith4Slashes () && currentPositionStartsWith2Slashes ()) {
268
- start += 2 ;
285
+ currentIndex += 2 ;
269
286
270
287
computeAuthority ();
271
288
computeUserInfo ();
272
289
273
290
if (host != null ) {
274
- if (isMaybeIPV6 ())
291
+ if (isMaybeIPV6 ()) {
275
292
computeIPV6 ();
276
- else
293
+ } else {
277
294
computeRegularHostPort ();
295
+ }
278
296
}
279
297
280
- if (port < -1 )
298
+ if (port < -1 ) {
281
299
throw new IllegalArgumentException ("Invalid port number :" + port );
300
+ }
282
301
283
302
// see RFC2396 5.2.4: ignore context path if authority is defined
284
- if (isNonEmpty (authority ))
303
+ if (isNonEmpty (authority )) {
285
304
path = "" ;
305
+ }
286
306
}
287
307
}
288
308
289
309
private void computeRegularPath () {
290
- if (urlWithoutQuery .charAt (start ) == '/' )
291
- path = urlWithoutQuery .substring (start , end );
292
-
293
- else if (isNonEmpty (path ))
310
+ if (originalUrl .charAt (currentIndex ) == '/' ) {
311
+ path = originalUrl .substring (currentIndex , end );
312
+ } else if (isNonEmpty (path )) {
294
313
handleRelativePath ();
295
-
296
- else {
297
- String pathEnd = urlWithoutQuery .substring (start , end );
314
+ } else {
315
+ String pathEnd = originalUrl .substring (currentIndex , end );
298
316
path = isNonEmpty (pathEnd ) && pathEnd .charAt (0 ) != '/' ? "/" + pathEnd : pathEnd ;
299
317
}
300
318
handlePathDots ();
@@ -307,29 +325,31 @@ private void computeQueryOnlyPath() {
307
325
308
326
private void computePath (boolean queryOnly ) {
309
327
// Parse the file path if any
310
- if (start < end )
328
+ if (currentIndex < end ) {
311
329
computeRegularPath ();
312
- else if (queryOnly && path != null )
330
+ } else if (queryOnly && path != null ) {
313
331
computeQueryOnlyPath ();
314
- else if (path == null )
332
+ } else if (path == null ) {
315
333
path = "" ;
334
+ }
316
335
}
317
336
318
337
public void parse (Uri context , final String originalUrl ) {
319
338
320
339
assertNotNull (originalUrl , "orginalUri" );
321
-
322
- boolean isRelative = false ;
323
-
324
- trimRight (originalUrl );
325
- trimLeft (originalUrl );
326
- if (!isFragmentOnly (originalUrl ))
327
- computeInitialScheme (originalUrl );
328
- overrideWithContext (context , originalUrl );
329
- computeFragment (originalUrl );
340
+ this .originalUrl = originalUrl ;
341
+ this .end = originalUrl .length ();
342
+
343
+ trimLeft ();
344
+ trimRight ();
345
+ currentIndex = start ;
346
+ if (!isFragmentOnly ()) {
347
+ computeInitialScheme ();
348
+ }
349
+ boolean isRelative = overrideWithContext (context );
350
+ trimFragment ();
330
351
inheritContextQuery (context , isRelative );
331
-
332
- boolean queryOnly = splitUrlAndQuery (originalUrl );
352
+ boolean queryOnly = computeQuery ();
333
353
parseAuthority ();
334
354
computePath (queryOnly );
335
355
}
0 commit comments