@@ -25,24 +25,27 @@ final class UriParser {
2525 public String path ;
2626 public String userInfo ;
2727
28- private int start , end = 0 ;
29- private String urlWithoutQuery ;
28+ private String originalUrl ;
29+ private int start , end , currentIndex = 0 ;
3030
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 ) <= ' ' ) {
3933 start ++;
34+ }
4035
41- if (originalUrl .regionMatches (true , start , "url:" , 0 , 4 ))
36+ if (originalUrl .regionMatches (true , start , "url:" , 0 , 4 )) {
4237 start += 4 ;
38+ }
4339 }
4440
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 () {
4649 return start < originalUrl .length () && originalUrl .charAt (start ) == '#' ;
4750 }
4851
@@ -52,8 +55,9 @@ private boolean isValidProtocolChar(char c) {
5255
5356 private boolean isValidProtocolChars (String protocol ) {
5457 for (int i = 1 ; i < protocol .length (); i ++) {
55- if (!isValidProtocolChar (protocol .charAt (i )))
58+ if (!isValidProtocolChar (protocol .charAt (i ))) {
5659 return false ;
60+ }
5761 }
5862 return true ;
5963 }
@@ -62,32 +66,34 @@ private boolean isValidProtocol(String protocol) {
6266 return protocol .length () > 0 && Character .isLetter (protocol .charAt (0 )) && isValidProtocolChars (protocol );
6367 }
6468
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 ++) {
6771 char c = originalUrl .charAt (i );
6872 if (c == ':' ) {
69- String s = originalUrl .substring (start , i );
73+ String s = originalUrl .substring (currentIndex , i );
7074 if (isValidProtocol (s )) {
71- scheme = s .toLowerCase ();
72- start = i + 1 ;
75+ scheme = s .toLowerCase ();
76+ currentIndex = i + 1 ;
7377 }
7478 break ;
75- } else if (c == '/' )
79+ } else if (c == '/' ) {
7680 break ;
81+ }
7782 }
7883 }
7984
80- private boolean overrideWithContext (Uri context , String originalUrl ) {
85+ private boolean overrideWithContext (Uri context ) {
8186
8287 boolean isRelative = false ;
8388
84- // only use context if the schemes match
89+ // use context only if schemes match
8590 if (context != null && (scheme == null || scheme .equalsIgnoreCase (context .getScheme ()))) {
8691
8792 // see RFC2396 5.2.3
8893 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+ }
9197
9298 if (scheme == null ) {
9399 scheme = context .getScheme ();
@@ -101,63 +107,67 @@ private boolean overrideWithContext(Uri context, String originalUrl) {
101107 return isRelative ;
102108 }
103109
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 ('#' );
106117 if (charpPosition >= 0 ) {
107118 end = charpPosition ;
108119 }
109120 }
110121
111122 private void inheritContextQuery (Uri context , boolean isRelative ) {
112123 // see RFC2396 5.2.2: query and fragment inheritance
113- if (isRelative && start == end ) {
124+ if (isRelative && currentIndex == end ) {
114125 query = context .getQuery ();
115126 }
116127 }
117128
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 ) {
125133 query = originalUrl .substring (askPosition + 1 , end );
126- if (end > askPosition )
134+ if (end > askPosition ) {
127135 end = askPosition ;
128- urlWithoutQuery = originalUrl .substring (0 , askPosition );
136+ }
137+ return askPosition == currentIndex ;
129138 }
130139 }
131-
132- return queryOnly ;
140+ return false ;
133141 }
134142
135143 private boolean currentPositionStartsWith4Slashes () {
136- return urlWithoutQuery .regionMatches (start , "////" , 0 , 4 );
144+ return originalUrl .regionMatches (currentIndex , "////" , 0 , 4 );
137145 }
138146
139147 private boolean currentPositionStartsWith2Slashes () {
140- return urlWithoutQuery .regionMatches (start , "//" , 0 , 2 );
148+ return originalUrl .regionMatches (currentIndex , "//" , 0 , 2 );
141149 }
142150
143151 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 ) {
148156 authorityEndPosition = end ;
157+ }
149158 }
150- host = authority = urlWithoutQuery .substring (start , authorityEndPosition );
151- start = authorityEndPosition ;
159+ host = authority = originalUrl .substring (currentIndex , authorityEndPosition );
160+ currentIndex = authorityEndPosition ;
152161 }
153162
154163 private void computeUserInfo () {
155164 int atPosition = authority .indexOf ('@' );
156165 if (atPosition != -1 ) {
157166 userInfo = authority .substring (0 , atPosition );
158167 host = authority .substring (atPosition + 1 );
159- } else
168+ } else {
160169 userInfo = null ;
170+ }
161171 }
162172
163173 private boolean isMaybeIPV6 () {
@@ -179,14 +189,16 @@ private void computeIPV6() {
179189 if (host .length () > portPosition ) {
180190 port = Integer .parseInt (host .substring (portPosition ));
181191 }
182- } else
192+ } else {
183193 throw new IllegalArgumentException ("Invalid authority field: " + authority );
194+ }
184195 }
185196
186197 host = host .substring (0 , positionAfterClosingSquareBrace );
187198
188- } else
199+ } else {
189200 throw new IllegalArgumentException ("Invalid authority field: " + authority );
201+ }
190202 }
191203
192204 private void computeRegularHostPort () {
@@ -218,39 +230,44 @@ private void removeEmbedded2Dots() {
218230 } else if (end == 0 ) {
219231 break ;
220232 }
221- } else
233+ } else {
222234 i = i + 3 ;
235+ }
223236 }
224237 }
225238
226239 private void removeTailing2Dots () {
227240 while (path .endsWith ("/.." )) {
228241 end = path .lastIndexOf ('/' , path .length () - 4 );
229- if (end >= 0 )
242+ if (end >= 0 ) {
230243 path = path .substring (0 , end + 1 );
231- else
244+ } else {
232245 break ;
246+ }
233247 }
234248 }
235249
236250 private void removeStartingDot () {
237- if (path .startsWith ("./" ) && path .length () > 2 )
251+ if (path .startsWith ("./" ) && path .length () > 2 ) {
238252 path = path .substring (2 );
253+ }
239254 }
240255
241256 private void removeTrailingDot () {
242- if (path .endsWith ("/." ))
257+ if (path .endsWith ("/." )) {
243258 path = path .substring (0 , path .length () - 1 );
259+ }
244260 }
245261
246262 private void handleRelativePath () {
247263 int lastSlashPosition = path .lastIndexOf ('/' );
248- String pathEnd = urlWithoutQuery .substring (start , end );
264+ String pathEnd = originalUrl .substring (currentIndex , end );
249265
250- if (lastSlashPosition == -1 )
266+ if (lastSlashPosition == -1 ) {
251267 path = authority != null ? "/" + pathEnd : pathEnd ;
252- else
268+ } else {
253269 path = path .substring (0 , lastSlashPosition + 1 ) + pathEnd ;
270+ }
254271 }
255272
256273 private void handlePathDots () {
@@ -265,36 +282,37 @@ private void handlePathDots() {
265282
266283 private void parseAuthority () {
267284 if (!currentPositionStartsWith4Slashes () && currentPositionStartsWith2Slashes ()) {
268- start += 2 ;
285+ currentIndex += 2 ;
269286
270287 computeAuthority ();
271288 computeUserInfo ();
272289
273290 if (host != null ) {
274- if (isMaybeIPV6 ())
291+ if (isMaybeIPV6 ()) {
275292 computeIPV6 ();
276- else
293+ } else {
277294 computeRegularHostPort ();
295+ }
278296 }
279297
280- if (port < -1 )
298+ if (port < -1 ) {
281299 throw new IllegalArgumentException ("Invalid port number :" + port );
300+ }
282301
283302 // see RFC2396 5.2.4: ignore context path if authority is defined
284- if (isNonEmpty (authority ))
303+ if (isNonEmpty (authority )) {
285304 path = "" ;
305+ }
286306 }
287307 }
288308
289309 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 )) {
294313 handleRelativePath ();
295-
296- else {
297- String pathEnd = urlWithoutQuery .substring (start , end );
314+ } else {
315+ String pathEnd = originalUrl .substring (currentIndex , end );
298316 path = isNonEmpty (pathEnd ) && pathEnd .charAt (0 ) != '/' ? "/" + pathEnd : pathEnd ;
299317 }
300318 handlePathDots ();
@@ -307,29 +325,31 @@ private void computeQueryOnlyPath() {
307325
308326 private void computePath (boolean queryOnly ) {
309327 // Parse the file path if any
310- if (start < end )
328+ if (currentIndex < end ) {
311329 computeRegularPath ();
312- else if (queryOnly && path != null )
330+ } else if (queryOnly && path != null ) {
313331 computeQueryOnlyPath ();
314- else if (path == null )
332+ } else if (path == null ) {
315333 path = "" ;
334+ }
316335 }
317336
318337 public void parse (Uri context , final String originalUrl ) {
319338
320339 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 ();
330351 inheritContextQuery (context , isRelative );
331-
332- boolean queryOnly = splitUrlAndQuery (originalUrl );
352+ boolean queryOnly = computeQuery ();
333353 parseAuthority ();
334354 computePath (queryOnly );
335355 }
0 commit comments