|
Lines 1-13
Link Here
|
| 1 |
/** |
1 |
/** |
| 2 |
* <copyright> |
2 |
* <copyright> |
| 3 |
* |
3 |
* |
| 4 |
* Copyright (c) 2002-2005 IBM Corporation and others. |
4 |
* Copyright (c) 2002-2005 IBM Corporation and others. |
| 5 |
* All rights reserved. This program and the accompanying materials |
5 |
* All rights reserved. This program and the accompanying materials |
| 6 |
* are made available under the terms of the Eclipse Public License v1.0 |
6 |
* are made available under the terms of the Eclipse Public License v1.0 |
| 7 |
* which accompanies this distribution, and is available at |
7 |
* which accompanies this distribution, and is available at |
| 8 |
* http://www.eclipse.org/legal/epl-v10.html |
8 |
* http://www.eclipse.org/legal/epl-v10.html |
| 9 |
* |
9 |
* |
| 10 |
* Contributors: |
10 |
* Contributors: |
| 11 |
* IBM - Initial API and implementation |
11 |
* IBM - Initial API and implementation |
| 12 |
* |
12 |
* |
| 13 |
* </copyright> |
13 |
* </copyright> |
|
Lines 16-29
Link Here
|
| 16 |
*/ |
16 |
*/ |
| 17 |
package org.eclipse.emf.common.util; |
17 |
package org.eclipse.emf.common.util; |
| 18 |
|
18 |
|
| 19 |
import java.io.File; |
19 |
//import java.io.File; |
| 20 |
import java.lang.ref.WeakReference; |
20 |
//import java.lang.ref.WeakReference; |
| 21 |
import java.util.ArrayList; |
21 |
import java.util.ArrayList; |
| 22 |
import java.util.Arrays; |
22 |
import java.util.Arrays; |
| 23 |
import java.util.Collections; |
23 |
import java.util.Collections; |
| 24 |
import java.util.HashMap; |
24 |
import java.util.HashMap; |
| 25 |
import java.util.HashSet; |
25 |
import java.util.HashSet; |
| 26 |
import java.util.Iterator; |
26 |
//import java.util.Iterator; |
| 27 |
import java.util.List; |
27 |
import java.util.List; |
| 28 |
import java.util.Map; |
28 |
import java.util.Map; |
| 29 |
import java.util.Set; |
29 |
import java.util.Set; |
|
Lines 75-81
Link Here
|
| 75 |
* can be used, in which a non-null <code>device</code> parameter can be |
75 |
* can be used, in which a non-null <code>device</code> parameter can be |
| 76 |
* specified. |
76 |
* specified. |
| 77 |
* |
77 |
* |
| 78 |
* <p><a name="archive_explanation"> |
78 |
* <p><a name="archive_explanation"> |
| 79 |
* The other enhancement provides support for the almost-hierarchical |
79 |
* The other enhancement provides support for the almost-hierarchical |
| 80 |
* form used for files within archives, such as the JAR scheme, defined |
80 |
* form used for files within archives, such as the JAR scheme, defined |
| 81 |
* for the Java Platform in the documentation for {@link |
81 |
* for the Java Platform in the documentation for {@link |
|
Lines 103-109
Link Here
|
| 103 |
* createURI(String) createURI} to have parsed them correctly from a single |
103 |
* createURI(String) createURI} to have parsed them correctly from a single |
| 104 |
* URI string. If necessary in the future, these tests may be made more |
104 |
* URI string. If necessary in the future, these tests may be made more |
| 105 |
* strict, to better coform to the RFC. |
105 |
* strict, to better coform to the RFC. |
| 106 |
* |
106 |
* |
| 107 |
* <p>Another group of static methods, whose names begin with "encode", use |
107 |
* <p>Another group of static methods, whose names begin with "encode", use |
| 108 |
* percent escaping to encode any characters that are not permitted in the |
108 |
* percent escaping to encode any characters that are not permitted in the |
| 109 |
* various URI components. Another static method is provided to {@link |
109 |
* various URI components. Another static method is provided to {@link |
|
Lines 153-203
Link Here
|
| 153 |
private final boolean absolutePath; |
153 |
private final boolean absolutePath; |
| 154 |
private final String[] segments; // empty last segment -> trailing separator |
154 |
private final String[] segments; // empty last segment -> trailing separator |
| 155 |
private final String query; |
155 |
private final String query; |
|
|
156 |
private static final char File_separatorChar = '/'; |
| 156 |
|
157 |
|
| 157 |
// A cache of URIs, keyed by the strings from which they were created. |
158 |
// A cache of URIs, keyed by the strings from which they were created. |
| 158 |
// The fragment of any URI is removed before caching it here, to minimize |
159 |
// The fragment of any URI is removed before caching it here, to minimize |
| 159 |
// the size of the cache in the usual case where most URIs only differ by |
160 |
// the size of the cache in the usual case where most URIs only differ by |
| 160 |
// the fragment. |
161 |
// the fragment. |
| 161 |
private static final Map uriCache = |
162 |
private static final Map uriCache = |
| 162 |
new HashMap() |
163 |
new HashMap() |
| 163 |
{ |
164 |
// { |
| 164 |
static final int MIN_LIMIT = 1000; |
165 |
// static final int MIN_LIMIT = 1000; |
| 165 |
int count; |
166 |
// int count; |
| 166 |
int limit = MIN_LIMIT; |
167 |
// int limit = MIN_LIMIT; |
| 167 |
|
168 |
// |
| 168 |
public synchronized Object get(Object key) |
169 |
// public synchronized Object get(Object key) |
| 169 |
{ |
170 |
// { |
| 170 |
WeakReference reference = (WeakReference)super.get(key); |
171 |
// WeakReference reference = (WeakReference)super.get(key); |
| 171 |
return reference == null ? null : reference.get(); |
172 |
// return reference == null ? null : reference.get(); |
| 172 |
} |
173 |
// } |
| 173 |
|
174 |
// |
| 174 |
public synchronized Object put(Object key, Object value) |
175 |
// public synchronized Object put(Object key, Object value) |
| 175 |
{ |
176 |
// { |
| 176 |
super.put(key, new WeakReference(value)); |
177 |
// super.put(key, new WeakReference(value)); |
| 177 |
if (++count > limit) |
178 |
// if (++count > limit) |
| 178 |
{ |
179 |
// { |
| 179 |
cleanGCedValues(); |
180 |
// cleanGCedValues(); |
| 180 |
} |
181 |
// } |
| 181 |
|
182 |
// |
| 182 |
// The return value is not used. |
183 |
// // The return value is not used. |
| 183 |
return null; |
184 |
// return null; |
| 184 |
} |
185 |
// } |
| 185 |
|
186 |
// |
| 186 |
private void cleanGCedValues() |
187 |
// private void cleanGCedValues() |
| 187 |
{ |
188 |
// { |
| 188 |
for (Iterator i = entrySet().iterator(); i.hasNext(); ) |
189 |
// for (Iterator i = entrySet().iterator(); i.hasNext(); ) |
| 189 |
{ |
190 |
// { |
| 190 |
Map.Entry entry = (Map.Entry)i.next(); |
191 |
// Map.Entry entry = (Map.Entry)i.next(); |
| 191 |
WeakReference reference = (WeakReference)entry.getValue(); |
192 |
// WeakReference reference = (WeakReference)entry.getValue(); |
| 192 |
if (reference.get() == null) |
193 |
// if (reference.get() == null) |
| 193 |
{ |
194 |
// { |
| 194 |
i.remove(); |
195 |
// i.remove(); |
| 195 |
} |
196 |
// } |
| 196 |
} |
197 |
// } |
| 197 |
count = 0; |
198 |
// count = 0; |
| 198 |
limit = Math.max(MIN_LIMIT, size() / 2); |
199 |
// limit = Math.max(MIN_LIMIT, size() / 2); |
| 199 |
} |
200 |
// } |
| 200 |
}; |
201 |
// } |
|
|
202 |
; |
| 201 |
|
203 |
|
| 202 |
// The lower-cased schemes that will be used to identify archive URIs. |
204 |
// The lower-cased schemes that will be used to identify archive URIs. |
| 203 |
private static final Set archiveSchemes; |
205 |
private static final Set archiveSchemes; |
|
Lines 246-252
Link Here
|
| 246 |
private static final long ALPHANUM_LO = ALPHA_LO | DIGIT_LO; |
248 |
private static final long ALPHANUM_LO = ALPHA_LO | DIGIT_LO; |
| 247 |
private static final long HEX_HI = DIGIT_HI | highBitmask('A', 'F') | highBitmask('a', 'f'); |
249 |
private static final long HEX_HI = DIGIT_HI | highBitmask('A', 'F') | highBitmask('a', 'f'); |
| 248 |
private static final long HEX_LO = DIGIT_LO | lowBitmask('A', 'F') | lowBitmask('a', 'f'); |
250 |
private static final long HEX_LO = DIGIT_LO | lowBitmask('A', 'F') | lowBitmask('a', 'f'); |
| 249 |
private static final long UNRESERVED_HI = ALPHANUM_HI | highBitmask("-_.!~*'()"); |
251 |
private static final long UNRESERVED_HI = ALPHANUM_HI | highBitmask("-_.!~*'()"); |
| 250 |
private static final long UNRESERVED_LO = ALPHANUM_LO | lowBitmask("-_.!~*'()"); |
252 |
private static final long UNRESERVED_LO = ALPHANUM_LO | lowBitmask("-_.!~*'()"); |
| 251 |
private static final long RESERVED_HI = highBitmask(";/?:@&=+$,"); |
253 |
private static final long RESERVED_HI = highBitmask(";/?:@&=+$,"); |
| 252 |
private static final long RESERVED_LO = lowBitmask(";/?:@&=+$,"); |
254 |
private static final long RESERVED_LO = lowBitmask(";/?:@&=+$,"); |
|
Lines 254-260
Link Here
|
| 254 |
private static final long URIC_LO = RESERVED_LO | UNRESERVED_LO; |
256 |
private static final long URIC_LO = RESERVED_LO | UNRESERVED_LO; |
| 255 |
|
257 |
|
| 256 |
// Additional useful character classes, including characters valid in certain |
258 |
// Additional useful character classes, including characters valid in certain |
| 257 |
// URI components and separators used in parsing them out of a string. |
259 |
// URI components and separators used in parsing them out of a string. |
| 258 |
// |
260 |
// |
| 259 |
private static final long SEGMENT_CHAR_HI = UNRESERVED_HI | highBitmask(";:@&=+$,"); // | ucschar | escaped |
261 |
private static final long SEGMENT_CHAR_HI = UNRESERVED_HI | highBitmask(";:@&=+$,"); // | ucschar | escaped |
| 260 |
private static final long SEGMENT_CHAR_LO = UNRESERVED_LO | lowBitmask(";:@&=+$,"); |
262 |
private static final long SEGMENT_CHAR_LO = UNRESERVED_LO | lowBitmask(";:@&=+$,"); |
|
Lines 267-284
Link Here
|
| 267 |
private static final long SEGMENT_END_HI = highBitmask("/?#"); |
269 |
private static final long SEGMENT_END_HI = highBitmask("/?#"); |
| 268 |
private static final long SEGMENT_END_LO = lowBitmask("/?#"); |
270 |
private static final long SEGMENT_END_LO = lowBitmask("/?#"); |
| 269 |
|
271 |
|
| 270 |
// We can't want to do encoding of platform resource URIs by default yet. |
272 |
// We can't want to do encoding of platform resource URIs by default yet. |
| 271 |
// |
273 |
// |
| 272 |
private static final boolean ENCODE_PLATFORM_RESOURCE_URIS = |
274 |
private static final boolean ENCODE_PLATFORM_RESOURCE_URIS = |
| 273 |
System.getProperty("org.eclipse.emf.common.util.URI.encodePlatformResourceURIs") != null && |
275 |
// System.getProperty("org.eclipse.emf.common.util.URI.encodePlatformResourceURIs") != null && |
| 274 |
!"false".equalsIgnoreCase(System.getProperty("org.eclipse.emf.common.util.URI.encodePlatformResourceURIs")); |
276 |
// !"false".equalsIgnoreCase(System.getProperty("org.eclipse.emf.common.util.URI.encodePlatformResourceURIs")); |
|
|
277 |
false; |
| 275 |
|
278 |
|
| 276 |
// Static initializer for archiveSchemes. |
279 |
// Static initializer for archiveSchemes. |
| 277 |
static |
280 |
static |
| 278 |
{ |
281 |
{ |
| 279 |
Set set = new HashSet(); |
282 |
Set set = new HashSet(); |
| 280 |
String propertyValue = System.getProperty("org.eclipse.emf.common.util.URI.archiveSchemes"); |
283 |
// String propertyValue = System.getProperty("org.eclipse.emf.common.util.URI.archiveSchemes"); |
| 281 |
|
284 |
String propertyValue = null; |
| 282 |
if (propertyValue == null) |
285 |
if (propertyValue == null) |
| 283 |
{ |
286 |
{ |
| 284 |
set.add(SCHEME_JAR); |
287 |
set.add(SCHEME_JAR); |
|
Lines 286-298
Link Here
|
| 286 |
set.add(SCHEME_ARCHIVE); |
289 |
set.add(SCHEME_ARCHIVE); |
| 287 |
} |
290 |
} |
| 288 |
else |
291 |
else |
| 289 |
{ |
292 |
{ |
| 290 |
for (StringTokenizer t = new StringTokenizer(propertyValue); t.hasMoreTokens(); ) |
293 |
for (StringTokenizer t = new StringTokenizer(propertyValue); t.hasMoreTokens(); ) |
| 291 |
{ |
294 |
{ |
| 292 |
set.add(t.nextToken().toLowerCase()); |
295 |
set.add(t.nextToken().toLowerCase()); |
| 293 |
} |
296 |
} |
| 294 |
} |
297 |
} |
| 295 |
|
298 |
|
| 296 |
archiveSchemes = Collections.unmodifiableSet(set); |
299 |
archiveSchemes = Collections.unmodifiableSet(set); |
| 297 |
} |
300 |
} |
| 298 |
|
301 |
|
|
Lines 449-464
Link Here
|
| 449 |
/** |
452 |
/** |
| 450 |
* Static factory method for a hierarchical URI with absolute path. |
453 |
* Static factory method for a hierarchical URI with absolute path. |
| 451 |
* The URI will be relative if <code>scheme</code> is non-null, and |
454 |
* The URI will be relative if <code>scheme</code> is non-null, and |
| 452 |
* absolute otherwise. |
455 |
* absolute otherwise. |
| 453 |
* |
456 |
* |
| 454 |
* @param segments an array of non-null strings, each representing one |
457 |
* @param segments an array of non-null strings, each representing one |
| 455 |
* segment of the path. As an absolute path, it is automatically |
458 |
* segment of the path. As an absolute path, it is automatically |
| 456 |
* preceeded by a <code>/</code> separator. If desired, a trailing |
459 |
* preceeded by a <code>/</code> separator. If desired, a trailing |
| 457 |
* separator should be represented by an empty-string segment as the last |
460 |
* separator should be represented by an empty-string segment as the last |
| 458 |
* element of the array. |
461 |
* element of the array. |
| 459 |
* |
462 |
* |
| 460 |
* @exception java.lang.IllegalArgumentException if <code>scheme</code> is |
463 |
* @exception java.lang.IllegalArgumentException if <code>scheme</code> is |
| 461 |
* an <a href="#archive_explanation">archive URI</a> scheme and |
464 |
* an <a href="#archive_explanation">archive URI</a> scheme and |
| 462 |
* <code>device</code> is non-null, or if <code>scheme</code>, |
465 |
* <code>device</code> is non-null, or if <code>scheme</code>, |
| 463 |
* <code>authority</code>, <code>device</code>, <code>segments</code>, |
466 |
* <code>authority</code>, <code>device</code>, <code>segments</code>, |
| 464 |
* <code>query</code>, or <code>fragment</code> is not valid according to |
467 |
* <code>query</code>, or <code>fragment</code> is not valid according to |
|
Lines 491-497
Link Here
|
| 491 |
* empty-string segment at the end of the array. |
494 |
* empty-string segment at the end of the array. |
| 492 |
* |
495 |
* |
| 493 |
* @exception java.lang.IllegalArgumentException if <code>segments</code>, |
496 |
* @exception java.lang.IllegalArgumentException if <code>segments</code>, |
| 494 |
* <code>query</code>, or <code>fragment</code> is not valid according to |
497 |
* <code>query</code>, or <code>fragment</code> is not valid according to |
| 495 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
498 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
| 496 |
* {@link #validFragment validFragment}, respectively. |
499 |
* {@link #validFragment validFragment}, respectively. |
| 497 |
*/ |
500 |
*/ |
|
Lines 507-517
Link Here
|
| 507 |
// immutability. |
510 |
// immutability. |
| 508 |
private static String[] fix(String[] segments) |
511 |
private static String[] fix(String[] segments) |
| 509 |
{ |
512 |
{ |
| 510 |
return segments == null ? NO_SEGMENTS : (String[])segments.clone(); |
513 |
// return segments == null ? NO_SEGMENTS : (String[])segments.clone(); |
|
|
514 |
return segments == null ? NO_SEGMENTS : clone(segments); |
| 511 |
} |
515 |
} |
| 512 |
|
516 |
|
|
|
517 |
private static String[] clone(String[] s) { |
| 518 |
String[] rv = new String[s.length]; |
| 519 |
for( int i = 0; i < s.length; i++ ) { |
| 520 |
rv[i] = s[i]; |
| 521 |
} |
| 522 |
|
| 523 |
return rv; |
| 524 |
} |
| 525 |
|
| 513 |
/** |
526 |
/** |
| 514 |
* Static factory method based on parsing a URI string, with |
527 |
* Static factory method based on parsing a URI string, with |
| 515 |
* <a href="#device_explanation">explicit device support</a> and handling |
528 |
* <a href="#device_explanation">explicit device support</a> and handling |
| 516 |
* for <a href="#archive_explanation">archive URIs</a> enabled. The |
529 |
* for <a href="#archive_explanation">archive URIs</a> enabled. The |
| 517 |
* specified string is parsed as described in <a |
530 |
* specified string is parsed as described in <a |
|
Lines 532-538
Link Here
|
| 532 |
*/ |
545 |
*/ |
| 533 |
public static URI createURI(String uri) |
546 |
public static URI createURI(String uri) |
| 534 |
{ |
547 |
{ |
| 535 |
return createURIWithCache(uri); |
548 |
return createURIWithCache(uri); |
| 536 |
} |
549 |
} |
| 537 |
|
550 |
|
| 538 |
/** |
551 |
/** |
|
Lines 540-551
Link Here
|
| 540 |
* Appropriate encoding is performed for each component of the URI. |
553 |
* Appropriate encoding is performed for each component of the URI. |
| 541 |
* If more than one <code>#</code> is in the string, the last one is |
554 |
* If more than one <code>#</code> is in the string, the last one is |
| 542 |
* assumed to be the fragment's separator, and any others are encoded. |
555 |
* assumed to be the fragment's separator, and any others are encoded. |
| 543 |
* |
556 |
* |
| 544 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
557 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 545 |
* unescaped if they already begin a valid three-character escape sequence; |
558 |
* unescaped if they already begin a valid three-character escape sequence; |
| 546 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
559 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 547 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
560 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 548 |
* escaped. |
561 |
* escaped. |
| 549 |
* |
562 |
* |
| 550 |
* @exception java.lang.IllegalArgumentException if any component parsed |
563 |
* @exception java.lang.IllegalArgumentException if any component parsed |
| 551 |
* from <code>uri</code> is not valid according to {@link #validScheme |
564 |
* from <code>uri</code> is not valid according to {@link #validScheme |
|
Lines 582-601
Link Here
|
| 582 |
* the fragment separator, and any others should be encoded. |
595 |
* the fragment separator, and any others should be encoded. |
| 583 |
* @see #createURI(String, boolean, int) |
596 |
* @see #createURI(String, boolean, int) |
| 584 |
*/ |
597 |
*/ |
| 585 |
public static final int FRAGMENT_LAST_SEPARATOR = 2; |
598 |
public static final int FRAGMENT_LAST_SEPARATOR = 2; |
| 586 |
|
599 |
|
| 587 |
/** |
600 |
/** |
| 588 |
* Static factory method that encodes and parses the given URI string. |
601 |
* Static factory method that encodes and parses the given URI string. |
| 589 |
* Appropriate encoding is performed for each component of the URI. |
602 |
* Appropriate encoding is performed for each component of the URI. |
| 590 |
* Control is provided over which, if any, <code>#</code> should be |
603 |
* Control is provided over which, if any, <code>#</code> should be |
| 591 |
* taken as the fragment separator and which should be encoded. |
604 |
* taken as the fragment separator and which should be encoded. |
| 592 |
* |
605 |
* |
| 593 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
606 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 594 |
* unescaped if they already begin a valid three-character escape sequence; |
607 |
* unescaped if they already begin a valid three-character escape sequence; |
| 595 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
608 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 596 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
609 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 597 |
* escaped. |
610 |
* escaped. |
| 598 |
* |
611 |
* |
| 599 |
* @param fragmentLocationStyle one of {@link #FRAGMENT_NONE}, |
612 |
* @param fragmentLocationStyle one of {@link #FRAGMENT_NONE}, |
| 600 |
* {@link #FRAGMENT_FIRST_SEPARATOR}, or {@link #FRAGMENT_LAST_SEPARATOR}, |
613 |
* {@link #FRAGMENT_FIRST_SEPARATOR}, or {@link #FRAGMENT_LAST_SEPARATOR}, |
| 601 |
* indicating which, if any, of the <code>#</code> characters should be |
614 |
* indicating which, if any, of the <code>#</code> characters should be |
|
Lines 615-622
Link Here
|
| 615 |
} |
628 |
} |
| 616 |
|
629 |
|
| 617 |
/** |
630 |
/** |
| 618 |
* Static factory method based on parsing a URI string, with |
631 |
* Static factory method based on parsing a URI string, with |
| 619 |
* <a href="#device_explanation">explicit device support</a> enabled. |
632 |
* <a href="#device_explanation">explicit device support</a> enabled. |
| 620 |
* Note that validity testing is not a strict as in the RFC; essentially, |
633 |
* Note that validity testing is not a strict as in the RFC; essentially, |
| 621 |
* only separator characters are considered. So, for example, non-Latin |
634 |
* only separator characters are considered. So, for example, non-Latin |
| 622 |
* alphabet characters appearing in the scheme would not be considered an |
635 |
* alphabet characters appearing in the scheme would not be considered an |
|
Lines 647-653
Link Here
|
| 647 |
// by string-parsing factory methods, instead of parseIntoURI() directly. |
660 |
// by string-parsing factory methods, instead of parseIntoURI() directly. |
| 648 |
/** |
661 |
/** |
| 649 |
* This method was included in the public API by mistake. |
662 |
* This method was included in the public API by mistake. |
| 650 |
* |
663 |
* |
| 651 |
* @deprecated Please use {@link #createURI createURI} instead. |
664 |
* @deprecated Please use {@link #createURI createURI} instead. |
| 652 |
*/ |
665 |
*/ |
| 653 |
public static URI createURIWithCache(String uri) |
666 |
public static URI createURIWithCache(String uri) |
|
Lines 725-731
Link Here
|
| 725 |
{ |
738 |
{ |
| 726 |
j = find(uri, i + 1, SEGMENT_END_HI, SEGMENT_END_LO); |
739 |
j = find(uri, i + 1, SEGMENT_END_HI, SEGMENT_END_LO); |
| 727 |
String s = uri.substring(i + 1, j); |
740 |
String s = uri.substring(i + 1, j); |
| 728 |
|
741 |
|
| 729 |
if (s.length() > 0 && s.charAt(s.length() - 1) == DEVICE_IDENTIFIER) |
742 |
if (s.length() > 0 && s.charAt(s.length() - 1) == DEVICE_IDENTIFIER) |
| 730 |
{ |
743 |
{ |
| 731 |
device = s; |
744 |
device = s; |
|
Lines 817-823
Link Here
|
| 817 |
* |
830 |
* |
| 818 |
* <p>A relative path with a specified device (something like |
831 |
* <p>A relative path with a specified device (something like |
| 819 |
* <code>C:myfile.txt</code>) cannot be expressed as a valid URI. |
832 |
* <code>C:myfile.txt</code>) cannot be expressed as a valid URI. |
| 820 |
* |
833 |
* |
| 821 |
* @exception java.lang.IllegalArgumentException if <code>pathName</code> |
834 |
* @exception java.lang.IllegalArgumentException if <code>pathName</code> |
| 822 |
* specifies a device and a relative path, or if any component of the path |
835 |
* specifies a device and a relative path, or if any component of the path |
| 823 |
* is not valid according to {@link #validAuthority validAuthority}, {@link |
836 |
* is not valid according to {@link #validAuthority validAuthority}, {@link |
|
Lines 826-840
Link Here
|
| 826 |
*/ |
839 |
*/ |
| 827 |
public static URI createFileURI(String pathName) |
840 |
public static URI createFileURI(String pathName) |
| 828 |
{ |
841 |
{ |
| 829 |
File file = new File(pathName); |
842 |
// File file = new File(pathName); |
| 830 |
String uri = File.separatorChar != '/' ? pathName.replace(File.separatorChar, SEGMENT_SEPARATOR) : pathName; |
843 |
String uri = File_separatorChar != '/' ? pathName.replace(File_separatorChar, SEGMENT_SEPARATOR) : pathName; |
| 831 |
uri = encode(uri, PATH_CHAR_HI, PATH_CHAR_LO, false); |
844 |
uri = encode(uri, PATH_CHAR_HI, PATH_CHAR_LO, false); |
| 832 |
if (file.isAbsolute()) |
845 |
// if (file.isAbsolute()) |
| 833 |
{ |
846 |
// { |
| 834 |
URI result = createURI((uri.charAt(0) == SEGMENT_SEPARATOR ? "file:" : "file:/") + uri); |
847 |
// URI result = createURI((uri.charAt(0) == SEGMENT_SEPARATOR ? "file:" : "file:/") + uri); |
| 835 |
return result; |
848 |
// return result; |
| 836 |
} |
849 |
// } |
| 837 |
else |
850 |
// else |
| 838 |
{ |
851 |
{ |
| 839 |
URI result = createURI(uri); |
852 |
URI result = createURI(uri); |
| 840 |
if (result.scheme() != null) |
853 |
if (result.scheme() != null) |
|
Lines 863-872
Link Here
|
| 863 |
* stand-alone EMF. |
876 |
* stand-alone EMF. |
| 864 |
* |
877 |
* |
| 865 |
* <p>Path encoding is performed only if the |
878 |
* <p>Path encoding is performed only if the |
| 866 |
* <code>org.eclipse.emf.common.util.URI.encodePlatformResourceURIs</code> |
879 |
* <code>org.eclipse.emf.common.util.URI.encodePlatformResourceURIs</code> |
| 867 |
* system property is set to "true". Decoding can be performed with the |
880 |
* system property is set to "true". Decoding can be performed with the |
| 868 |
* static {@link #decode(String) decode} method. |
881 |
* static {@link #decode(String) decode} method. |
| 869 |
* |
882 |
* |
| 870 |
* @exception java.lang.IllegalArgumentException if any component parsed |
883 |
* @exception java.lang.IllegalArgumentException if any component parsed |
| 871 |
* from the path is not valid according to {@link #validDevice validDevice}, |
884 |
* from the path is not valid according to {@link #validDevice validDevice}, |
| 872 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
885 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
|
Lines 903-909
Link Here
|
| 903 |
* and other characters disallowed in URIs, as well as <code>?</code>, |
916 |
* and other characters disallowed in URIs, as well as <code>?</code>, |
| 904 |
* which would delimit a path from a query. Decoding can be performed with |
917 |
* which would delimit a path from a query. Decoding can be performed with |
| 905 |
* the static {@link #decode(String) decode} method. |
918 |
* the static {@link #decode(String) decode} method. |
| 906 |
* |
919 |
* |
| 907 |
* @exception java.lang.IllegalArgumentException if any component parsed |
920 |
* @exception java.lang.IllegalArgumentException if any component parsed |
| 908 |
* from the path is not valid according to {@link #validDevice validDevice}, |
921 |
* from the path is not valid according to {@link #validDevice validDevice}, |
| 909 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
922 |
* {@link #validSegments validSegments}, {@link #validQuery validQuery}, or |
|
Lines 913-921
Link Here
|
| 913 |
*/ |
926 |
*/ |
| 914 |
public static URI createPlatformResourceURI(String pathName, boolean encode) |
927 |
public static URI createPlatformResourceURI(String pathName, boolean encode) |
| 915 |
{ |
928 |
{ |
| 916 |
if (File.separatorChar != SEGMENT_SEPARATOR) |
929 |
if (File_separatorChar != SEGMENT_SEPARATOR) |
| 917 |
{ |
930 |
{ |
| 918 |
pathName = pathName.replace(File.separatorChar, SEGMENT_SEPARATOR); |
931 |
pathName = pathName.replace(File_separatorChar, SEGMENT_SEPARATOR); |
| 919 |
} |
932 |
} |
| 920 |
|
933 |
|
| 921 |
if (encode) |
934 |
if (encode) |
|
Lines 925-931
Link Here
|
| 925 |
URI result = createURI((pathName.charAt(0) == SEGMENT_SEPARATOR ? "platform:/resource" : "platform:/resource/") + pathName); |
938 |
URI result = createURI((pathName.charAt(0) == SEGMENT_SEPARATOR ? "platform:/resource" : "platform:/resource/") + pathName); |
| 926 |
return result; |
939 |
return result; |
| 927 |
} |
940 |
} |
| 928 |
|
941 |
|
| 929 |
// Private constructor for use of static factory methods. |
942 |
// Private constructor for use of static factory methods. |
| 930 |
private URI(boolean hierarchical, String scheme, String authority, |
943 |
private URI(boolean hierarchical, String scheme, String authority, |
| 931 |
String device, boolean absolutePath, String[] segments, |
944 |
String device, boolean absolutePath, String[] segments, |
|
Lines 976-982
Link Here
|
| 976 |
this.hashCode = hashCode; |
989 |
this.hashCode = hashCode; |
| 977 |
//this.iri = iri; |
990 |
//this.iri = iri; |
| 978 |
this.hierarchical = hierarchical; |
991 |
this.hierarchical = hierarchical; |
| 979 |
this.scheme = scheme == null ? null : scheme.intern(); |
992 |
this.scheme = scheme == null ? null : new String(scheme); |
| 980 |
this.authority = authority; |
993 |
this.authority = authority; |
| 981 |
this.device = device; |
994 |
this.device = device; |
| 982 |
this.absolutePath = absolutePath; |
995 |
this.absolutePath = absolutePath; |
|
Lines 984-990
Link Here
|
| 984 |
this.query = query; |
997 |
this.query = query; |
| 985 |
this.fragment = fragment; |
998 |
this.fragment = fragment; |
| 986 |
} |
999 |
} |
| 987 |
|
1000 |
|
| 988 |
// Validates all of the URI components. Factory methods should call this |
1001 |
// Validates all of the URI components. Factory methods should call this |
| 989 |
// before using the constructor, though they must ensure that the |
1002 |
// before using the constructor, though they must ensure that the |
| 990 |
// inter-component requirements described in their own Javadocs are all |
1003 |
// inter-component requirements described in their own Javadocs are all |
|
Lines 1044-1050
Link Here
|
| 1044 |
*/ |
1057 |
*/ |
| 1045 |
public static boolean validScheme(String value) |
1058 |
public static boolean validScheme(String value) |
| 1046 |
{ |
1059 |
{ |
| 1047 |
return value == null || !contains(value, MAJOR_SEPARATOR_HI, MAJOR_SEPARATOR_LO); |
1060 |
return value == null || !contains(value, MAJOR_SEPARATOR_HI, MAJOR_SEPARATOR_LO); |
| 1048 |
|
1061 |
|
| 1049 |
// <p>A valid scheme may be null, or consist of a single letter followed |
1062 |
// <p>A valid scheme may be null, or consist of a single letter followed |
| 1050 |
// by any number of letters, numbers, and the following characters: |
1063 |
// by any number of letters, numbers, and the following characters: |
|
Lines 1072-1078
Link Here
|
| 1072 |
|
1085 |
|
| 1073 |
// <p>A valid opaque part must be non-null and non-empty. It may contain |
1086 |
// <p>A valid opaque part must be non-null and non-empty. It may contain |
| 1074 |
// any allowed URI characters, but its first character may not be |
1087 |
// any allowed URI characters, but its first character may not be |
| 1075 |
// <code>/</code> |
1088 |
// <code>/</code> |
| 1076 |
|
1089 |
|
| 1077 |
//return value != null && value.length() != 0 && |
1090 |
//return value != null && value.length() != 0 && |
| 1078 |
// value.charAt(0) != SEGMENT_SEPARATOR && |
1091 |
// value.charAt(0) != SEGMENT_SEPARATOR && |
|
Lines 1128-1134
Link Here
|
| 1128 |
* URI</a>. This method has been replaced by {@link #validArchiveAuthority |
1141 |
* URI</a>. This method has been replaced by {@link #validArchiveAuthority |
| 1129 |
* validArchiveAuthority} since the same form of URI is now supported |
1142 |
* validArchiveAuthority} since the same form of URI is now supported |
| 1130 |
* for schemes other than "jar". This now simply calls that method. |
1143 |
* for schemes other than "jar". This now simply calls that method. |
| 1131 |
* |
1144 |
* |
| 1132 |
* @deprecated As of EMF 2.0, replaced by {@link #validArchiveAuthority |
1145 |
* @deprecated As of EMF 2.0, replaced by {@link #validArchiveAuthority |
| 1133 |
* validArchiveAuthority}. |
1146 |
* validArchiveAuthority}. |
| 1134 |
*/ |
1147 |
*/ |
|
Lines 1146-1152
Link Here
|
| 1146 |
* character must be <code>:</code> |
1159 |
* character must be <code>:</code> |
| 1147 |
*/ |
1160 |
*/ |
| 1148 |
public static boolean validDevice(String value) |
1161 |
public static boolean validDevice(String value) |
| 1149 |
{ |
1162 |
{ |
| 1150 |
if (value == null) return true; |
1163 |
if (value == null) return true; |
| 1151 |
int len = value.length(); |
1164 |
int len = value.length(); |
| 1152 |
return len > 0 && value.charAt(len - 1) == DEVICE_IDENTIFIER && |
1165 |
return len > 0 && value.charAt(len - 1) == DEVICE_IDENTIFIER && |
|
Lines 1174-1180
Link Here
|
| 1174 |
return value != null && !contains(value, SEGMENT_END_HI, SEGMENT_END_LO); |
1187 |
return value != null && !contains(value, SEGMENT_END_HI, SEGMENT_END_LO); |
| 1175 |
|
1188 |
|
| 1176 |
// <p>A valid path segment must be non-null and may contain any allowed URI |
1189 |
// <p>A valid path segment must be non-null and may contain any allowed URI |
| 1177 |
// characters except for the following: <code>/ ?</code> |
1190 |
// characters except for the following: <code>/ ?</code> |
| 1178 |
|
1191 |
|
| 1179 |
//return value != null && validate(value, SEGMENT_CHAR_HI, SEGMENT_CHAR_LO, true, true); |
1192 |
//return value != null && validate(value, SEGMENT_CHAR_HI, SEGMENT_CHAR_LO, true, true); |
| 1180 |
} |
1193 |
} |
|
Lines 1198-1204
Link Here
|
| 1198 |
|
1211 |
|
| 1199 |
// Returns null if the specicied value is null or would be a valid path |
1212 |
// Returns null if the specicied value is null or would be a valid path |
| 1200 |
// segment array of a URI; otherwise, the value of the first invalid |
1213 |
// segment array of a URI; otherwise, the value of the first invalid |
| 1201 |
// segment. |
1214 |
// segment. |
| 1202 |
private static String firstInvalidSegment(String[] value) |
1215 |
private static String firstInvalidSegment(String[] value) |
| 1203 |
{ |
1216 |
{ |
| 1204 |
if (value == null) return null; |
1217 |
if (value == null) return null; |
|
Lines 1262-1268
Link Here
|
| 1262 |
boolean allowNonASCII, boolean allowEscaped) |
1275 |
boolean allowNonASCII, boolean allowEscaped) |
| 1263 |
{ |
1276 |
{ |
| 1264 |
for (int i = 0, len = value.length(); i < len; i++) |
1277 |
for (int i = 0, len = value.length(); i < len; i++) |
| 1265 |
{ |
1278 |
{ |
| 1266 |
char c = value.charAt(i); |
1279 |
char c = value.charAt(i); |
| 1267 |
|
1280 |
|
| 1268 |
if (matches(c, highBitmask, lowBitmask)) continue; |
1281 |
if (matches(c, highBitmask, lowBitmask)) continue; |
|
Lines 1298-1304
Link Here
|
| 1298 |
|
1311 |
|
| 1299 |
/** |
1312 |
/** |
| 1300 |
* Returns <code>true</code> if this is a hierarcical URI with an authority |
1313 |
* Returns <code>true</code> if this is a hierarcical URI with an authority |
| 1301 |
* component; <code>false</code> otherwise. |
1314 |
* component; <code>false</code> otherwise. |
| 1302 |
*/ |
1315 |
*/ |
| 1303 |
public boolean hasAuthority() |
1316 |
public boolean hasAuthority() |
| 1304 |
{ |
1317 |
{ |
|
Lines 1361-1367
Link Here
|
| 1361 |
|
1374 |
|
| 1362 |
/** |
1375 |
/** |
| 1363 |
* Returns <code>true</code> if this is a hierarchical URI with an empty |
1376 |
* Returns <code>true</code> if this is a hierarchical URI with an empty |
| 1364 |
* relative path; <code>false</code> otherwise. |
1377 |
* relative path; <code>false</code> otherwise. |
| 1365 |
* |
1378 |
* |
| 1366 |
* <p>Note that <code>!hasEmpty()</code> does <em>not</em> imply that this |
1379 |
* <p>Note that <code>!hasEmpty()</code> does <em>not</em> imply that this |
| 1367 |
* URI has any path segments; however, <code>hasRelativePath && |
1380 |
* URI has any path segments; however, <code>hasRelativePath && |
|
Lines 1458-1464
Link Here
|
| 1458 |
// By default, "jar", "zip", and "archive" are considered archives. |
1471 |
// By default, "jar", "zip", and "archive" are considered archives. |
| 1459 |
return value != null && archiveSchemes.contains(value.toLowerCase()); |
1472 |
return value != null && archiveSchemes.contains(value.toLowerCase()); |
| 1460 |
} |
1473 |
} |
| 1461 |
|
1474 |
|
| 1462 |
/** |
1475 |
/** |
| 1463 |
* Returns the hash code. |
1476 |
* Returns the hash code. |
| 1464 |
*/ |
1477 |
*/ |
|
Lines 1487-1493
Link Here
|
| 1487 |
equals(scheme, uri.scheme(), true) && |
1500 |
equals(scheme, uri.scheme(), true) && |
| 1488 |
equals(authority, hierarchical ? uri.authority() : uri.opaquePart()) && |
1501 |
equals(authority, hierarchical ? uri.authority() : uri.opaquePart()) && |
| 1489 |
equals(device, uri.device()) && |
1502 |
equals(device, uri.device()) && |
| 1490 |
equals(query, uri.query()) && |
1503 |
equals(query, uri.query()) && |
| 1491 |
equals(fragment, uri.fragment()) && |
1504 |
equals(fragment, uri.fragment()) && |
| 1492 |
segmentsEqual(uri); |
1505 |
segmentsEqual(uri); |
| 1493 |
} |
1506 |
} |
|
Lines 1551-1559
Link Here
|
| 1551 |
* user info portion, returns it; <code>null</code> otherwise. |
1564 |
* user info portion, returns it; <code>null</code> otherwise. |
| 1552 |
*/ |
1565 |
*/ |
| 1553 |
public String userInfo() |
1566 |
public String userInfo() |
| 1554 |
{ |
1567 |
{ |
| 1555 |
if (!hasAuthority()) return null; |
1568 |
if (!hasAuthority()) return null; |
| 1556 |
|
1569 |
|
| 1557 |
int i = authority.indexOf(USER_INFO_SEPARATOR); |
1570 |
int i = authority.indexOf(USER_INFO_SEPARATOR); |
| 1558 |
return i < 0 ? null : authority.substring(0, i); |
1571 |
return i < 0 ? null : authority.substring(0, i); |
| 1559 |
} |
1572 |
} |
|
Lines 1565-1571
Link Here
|
| 1565 |
public String host() |
1578 |
public String host() |
| 1566 |
{ |
1579 |
{ |
| 1567 |
if (!hasAuthority()) return null; |
1580 |
if (!hasAuthority()) return null; |
| 1568 |
|
1581 |
|
| 1569 |
int i = authority.indexOf(USER_INFO_SEPARATOR); |
1582 |
int i = authority.indexOf(USER_INFO_SEPARATOR); |
| 1570 |
int j = authority.indexOf(PORT_SEPARATOR); |
1583 |
int j = authority.indexOf(PORT_SEPARATOR); |
| 1571 |
return j < 0 ? authority.substring(i + 1) : authority.substring(i + 1, j); |
1584 |
return j < 0 ? authority.substring(i + 1) : authority.substring(i + 1, j); |
|
Lines 1601-1607
Link Here
|
| 1601 |
*/ |
1614 |
*/ |
| 1602 |
public String[] segments() |
1615 |
public String[] segments() |
| 1603 |
{ |
1616 |
{ |
| 1604 |
return (String[])segments.clone(); |
1617 |
return clone(segments); |
| 1605 |
} |
1618 |
} |
| 1606 |
|
1619 |
|
| 1607 |
/** |
1620 |
/** |
|
Lines 1669-1677
Link Here
|
| 1669 |
|
1682 |
|
| 1670 |
/** |
1683 |
/** |
| 1671 |
* If this is a hierarchical URI with a path, returns a string |
1684 |
* If this is a hierarchical URI with a path, returns a string |
| 1672 |
* representation of the path, including the authority and the |
1685 |
* representation of the path, including the authority and the |
| 1673 |
* <a href="#device_explanation">device component</a>; |
1686 |
* <a href="#device_explanation">device component</a>; |
| 1674 |
* <code>null</code> otherwise. |
1687 |
* <code>null</code> otherwise. |
| 1675 |
* |
1688 |
* |
| 1676 |
* <p>If there is no authority, the format of this string is: |
1689 |
* <p>If there is no authority, the format of this string is: |
| 1677 |
* <pre> |
1690 |
* <pre> |
|
Lines 1734-1740
Link Here
|
| 1734 |
throw new IllegalArgumentException( |
1747 |
throw new IllegalArgumentException( |
| 1735 |
"invalid query portion: " + query); |
1748 |
"invalid query portion: " + query); |
| 1736 |
} |
1749 |
} |
| 1737 |
return new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, fragment); |
1750 |
return new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, fragment); |
| 1738 |
} |
1751 |
} |
| 1739 |
|
1752 |
|
| 1740 |
/** |
1753 |
/** |
|
Lines 1749-1755
Link Here
|
| 1749 |
} |
1762 |
} |
| 1750 |
else |
1763 |
else |
| 1751 |
{ |
1764 |
{ |
| 1752 |
return new URI(hierarchical, scheme, authority, device, absolutePath, segments, null, fragment); |
1765 |
return new URI(hierarchical, scheme, authority, device, absolutePath, segments, null, fragment); |
| 1753 |
} |
1766 |
} |
| 1754 |
} |
1767 |
} |
| 1755 |
|
1768 |
|
|
Lines 1776-1782
Link Here
|
| 1776 |
throw new IllegalArgumentException( |
1789 |
throw new IllegalArgumentException( |
| 1777 |
"invalid fragment portion: " + fragment); |
1790 |
"invalid fragment portion: " + fragment); |
| 1778 |
} |
1791 |
} |
| 1779 |
URI result = new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, fragment); |
1792 |
URI result = new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, fragment); |
| 1780 |
|
1793 |
|
| 1781 |
if (!hasFragment()) |
1794 |
if (!hasFragment()) |
| 1782 |
{ |
1795 |
{ |
|
Lines 1797-1803
Link Here
|
| 1797 |
} |
1810 |
} |
| 1798 |
else if (cachedTrimFragment == null) |
1811 |
else if (cachedTrimFragment == null) |
| 1799 |
{ |
1812 |
{ |
| 1800 |
cachedTrimFragment = new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, null); |
1813 |
cachedTrimFragment = new URI(hierarchical, scheme, authority, device, absolutePath, segments, query, null); |
| 1801 |
} |
1814 |
} |
| 1802 |
|
1815 |
|
| 1803 |
return cachedTrimFragment; |
1816 |
return cachedTrimFragment; |
|
Lines 1866-1872
Link Here
|
| 1866 |
String newQuery = query; |
1879 |
String newQuery = query; |
| 1867 |
// note: it's okay for two URIs to share a segments array, since |
1880 |
// note: it's okay for two URIs to share a segments array, since |
| 1868 |
// neither will ever modify it |
1881 |
// neither will ever modify it |
| 1869 |
|
1882 |
|
| 1870 |
if (authority == null) |
1883 |
if (authority == null) |
| 1871 |
{ |
1884 |
{ |
| 1872 |
// no authority: use base's |
1885 |
// no authority: use base's |
|
Lines 1888-1894
Link Here
|
| 1888 |
{ |
1901 |
{ |
| 1889 |
// relative path: merge with base and keep query (note: if the |
1902 |
// relative path: merge with base and keep query (note: if the |
| 1890 |
// base has no path and this a non-empty relative path, there is |
1903 |
// base has no path and this a non-empty relative path, there is |
| 1891 |
// an implied root in the resulting path) |
1904 |
// an implied root in the resulting path) |
| 1892 |
newAbsolutePath = base.hasAbsolutePath() || !hasEmptyPath(); |
1905 |
newAbsolutePath = base.hasAbsolutePath() || !hasEmptyPath(); |
| 1893 |
newSegments = newAbsolutePath ? mergePath(base, preserveRootParents) |
1906 |
newSegments = newAbsolutePath ? mergePath(base, preserveRootParents) |
| 1894 |
: NO_SEGMENTS; |
1907 |
: NO_SEGMENTS; |
|
Lines 1898-1904
Link Here
|
| 1898 |
// else keep device, path, and query |
1911 |
// else keep device, path, and query |
| 1899 |
} |
1912 |
} |
| 1900 |
// else keep authority, device, path, and query |
1913 |
// else keep authority, device, path, and query |
| 1901 |
|
1914 |
|
| 1902 |
// always keep fragment, even if null, and use scheme from base; |
1915 |
// always keep fragment, even if null, and use scheme from base; |
| 1903 |
// no validation needed since all components are from existing URIs |
1916 |
// no validation needed since all components are from existing URIs |
| 1904 |
return new URI(true, base.scheme(), newAuthority, newDevice, |
1917 |
return new URI(true, base.scheme(), newAuthority, newDevice, |
|
Lines 1937-1943
Link Here
|
| 1937 |
sp = accumulate(stack, sp, segments[i], preserveRootParents); |
1950 |
sp = accumulate(stack, sp, segments[i], preserveRootParents); |
| 1938 |
} |
1951 |
} |
| 1939 |
|
1952 |
|
| 1940 |
// if the relative path is empty or ends in an empty segment, a parent |
1953 |
// if the relative path is empty or ends in an empty segment, a parent |
| 1941 |
// reference, or a self referenfce, add a trailing separator to a |
1954 |
// reference, or a self referenfce, add a trailing separator to a |
| 1942 |
// non-empty path |
1955 |
// non-empty path |
| 1943 |
if (sp > 0 && (segmentCount == 0 || |
1956 |
if (sp > 0 && (segmentCount == 0 || |
|
Lines 1986-1992
Link Here
|
| 1986 |
/** |
1999 |
/** |
| 1987 |
* Finds the shortest relative or, if necessary, the absolute URI that, |
2000 |
* Finds the shortest relative or, if necessary, the absolute URI that, |
| 1988 |
* when resolved against the given <code>base</code> absolute hierarchical |
2001 |
* when resolved against the given <code>base</code> absolute hierarchical |
| 1989 |
* URI using {@link #resolve(URI) resolve}, will yield this absolute URI. |
2002 |
* URI using {@link #resolve(URI) resolve}, will yield this absolute URI. |
| 1990 |
* |
2003 |
* |
| 1991 |
* @exception java.lang.IllegalArgumentException if <code>base</code> is |
2004 |
* @exception java.lang.IllegalArgumentException if <code>base</code> is |
| 1992 |
* non-hierarchical or is relative. |
2005 |
* non-hierarchical or is relative. |
|
Lines 2034-2040
Link Here
|
| 2034 |
|
2047 |
|
| 2035 |
// note: these assertions imply that neither this nor the base URI has a |
2048 |
// note: these assertions imply that neither this nor the base URI has a |
| 2036 |
// relative path; thus, both have either an absolute path or no path |
2049 |
// relative path; thus, both have either an absolute path or no path |
| 2037 |
|
2050 |
|
| 2038 |
// different scheme: need complete, absolute URI |
2051 |
// different scheme: need complete, absolute URI |
| 2039 |
if (!scheme.equalsIgnoreCase(base.scheme())) return this; |
2052 |
if (!scheme.equalsIgnoreCase(base.scheme())) return this; |
| 2040 |
|
2053 |
|
|
Lines 2224-2230
Link Here
|
| 2224 |
if (sp > 0 && (SEGMENT_EMPTY.equals(segments[segmentCount - 1]) || |
2237 |
if (sp > 0 && (SEGMENT_EMPTY.equals(segments[segmentCount - 1]) || |
| 2225 |
SEGMENT_PARENT.equals(segments[segmentCount - 1]) || |
2238 |
SEGMENT_PARENT.equals(segments[segmentCount - 1]) || |
| 2226 |
SEGMENT_SELF.equals(segments[segmentCount - 1]))) |
2239 |
SEGMENT_SELF.equals(segments[segmentCount - 1]))) |
| 2227 |
{ |
2240 |
{ |
| 2228 |
stack[sp++] = SEGMENT_EMPTY; |
2241 |
stack[sp++] = SEGMENT_EMPTY; |
| 2229 |
} |
2242 |
} |
| 2230 |
|
2243 |
|
|
Lines 2239-2245
Link Here
|
| 2239 |
* non-hierarchical URI, this looks like: |
2252 |
* non-hierarchical URI, this looks like: |
| 2240 |
* <pre> |
2253 |
* <pre> |
| 2241 |
* scheme:opaquePart#fragment</pre> |
2254 |
* scheme:opaquePart#fragment</pre> |
| 2242 |
* |
2255 |
* |
| 2243 |
* <p>For a hierarchical URI, it looks like: |
2256 |
* <p>For a hierarchical URI, it looks like: |
| 2244 |
* <pre> |
2257 |
* <pre> |
| 2245 |
* scheme://authority/device/pathSegment1/pathSegment2...?query#fragment</pre> |
2258 |
* scheme://authority/device/pathSegment1/pathSegment2...?query#fragment</pre> |
|
Lines 2335-2341
Link Here
|
| 2335 |
|
2348 |
|
| 2336 |
/** |
2349 |
/** |
| 2337 |
* If this URI may refer directly to a locally accessible file, as |
2350 |
* If this URI may refer directly to a locally accessible file, as |
| 2338 |
* determined by {@link #isFile isFile}, {@link decode decodes} and formats |
2351 |
* determined by {@link #isFile isFile}, {@link decode decodes} and formats |
| 2339 |
* the URI as a pathname to that file; returns null otherwise. |
2352 |
* the URI as a pathname to that file; returns null otherwise. |
| 2340 |
* |
2353 |
* |
| 2341 |
* <p>If there is no authority, the format of this string is: |
2354 |
* <p>If there is no authority, the format of this string is: |
|
Lines 2345-2351
Link Here
|
| 2345 |
* <p>If there is an authority, it is: |
2358 |
* <p>If there is an authority, it is: |
| 2346 |
* <pre> |
2359 |
* <pre> |
| 2347 |
* //authority/device/pathSegment1/pathSegment2...</pre> |
2360 |
* //authority/device/pathSegment1/pathSegment2...</pre> |
| 2348 |
* |
2361 |
* |
| 2349 |
* <p>However, the character used as a separator is system-dependant and |
2362 |
* <p>However, the character used as a separator is system-dependant and |
| 2350 |
* obtained from {@link java.io.File#separatorChar}. |
2363 |
* obtained from {@link java.io.File#separatorChar}. |
| 2351 |
*/ |
2364 |
*/ |
|
Lines 2354-2360
Link Here
|
| 2354 |
if (!isFile()) return null; |
2367 |
if (!isFile()) return null; |
| 2355 |
|
2368 |
|
| 2356 |
StringBuffer result = new StringBuffer(); |
2369 |
StringBuffer result = new StringBuffer(); |
| 2357 |
char separator = File.separatorChar; |
2370 |
char separator = File_separatorChar; |
| 2358 |
|
2371 |
|
| 2359 |
if (hasAuthority()) |
2372 |
if (hasAuthority()) |
| 2360 |
{ |
2373 |
{ |
|
Lines 2433-2446
Link Here
|
| 2433 |
if (!isHierarchical()) return this; |
2446 |
if (!isHierarchical()) return this; |
| 2434 |
|
2447 |
|
| 2435 |
// absolute path or no path -> absolute path |
2448 |
// absolute path or no path -> absolute path |
| 2436 |
boolean newAbsolutePath = !hasRelativePath(); |
2449 |
boolean newAbsolutePath = !hasRelativePath(); |
| 2437 |
|
2450 |
|
| 2438 |
int len = this.segments.length; |
2451 |
int len = this.segments.length; |
| 2439 |
int segmentsCount = segments.length; |
2452 |
int segmentsCount = segments.length; |
| 2440 |
String[] newSegments = new String[len + segmentsCount]; |
2453 |
String[] newSegments = new String[len + segmentsCount]; |
| 2441 |
System.arraycopy(this.segments, 0, newSegments, 0, len); |
2454 |
System.arraycopy(this.segments, 0, newSegments, 0, len); |
| 2442 |
System.arraycopy(segments, 0, newSegments, len, segmentsCount); |
2455 |
System.arraycopy(segments, 0, newSegments, len, segmentsCount); |
| 2443 |
|
2456 |
|
| 2444 |
return new URI(true, scheme, authority, device, newAbsolutePath, |
2457 |
return new URI(true, scheme, authority, device, newAbsolutePath, |
| 2445 |
newSegments, query, fragment); |
2458 |
newSegments, query, fragment); |
| 2446 |
} |
2459 |
} |
|
Lines 2453-2463
Link Here
|
| 2453 |
* |
2466 |
* |
| 2454 |
* <p>Note that if all segments are trimmed from an absolute path, the |
2467 |
* <p>Note that if all segments are trimmed from an absolute path, the |
| 2455 |
* root absolute path remains. |
2468 |
* root absolute path remains. |
| 2456 |
* |
2469 |
* |
| 2457 |
* @param i the number of segments to be trimmed in the returned URI. If |
2470 |
* @param i the number of segments to be trimmed in the returned URI. If |
| 2458 |
* less than 1, this URI is returned unchanged; if equal to or greater |
2471 |
* less than 1, this URI is returned unchanged; if equal to or greater |
| 2459 |
* than the number of segments in this URI's path, all segments are |
2472 |
* than the number of segments in this URI's path, all segments are |
| 2460 |
* trimmed. |
2473 |
* trimmed. |
| 2461 |
*/ |
2474 |
*/ |
| 2462 |
public URI trimSegments(int i) |
2475 |
public URI trimSegments(int i) |
| 2463 |
{ |
2476 |
{ |
|
Lines 2484-2490
Link Here
|
| 2484 |
*/ |
2497 |
*/ |
| 2485 |
public boolean hasTrailingPathSeparator() |
2498 |
public boolean hasTrailingPathSeparator() |
| 2486 |
{ |
2499 |
{ |
| 2487 |
return segments.length > 0 && |
2500 |
return segments.length > 0 && |
| 2488 |
SEGMENT_EMPTY.equals(segments[segments.length - 1]); |
2501 |
SEGMENT_EMPTY.equals(segments[segments.length - 1]); |
| 2489 |
} |
2502 |
} |
| 2490 |
|
2503 |
|
|
Lines 2540-2549
Link Here
|
| 2540 |
String[] newSegments = new String[len]; |
2553 |
String[] newSegments = new String[len]; |
| 2541 |
System.arraycopy(segments, 0, newSegments, 0, len - 1); |
2554 |
System.arraycopy(segments, 0, newSegments, 0, len - 1); |
| 2542 |
newSegments[len - 1] = newLastSegment.toString(); |
2555 |
newSegments[len - 1] = newLastSegment.toString(); |
| 2543 |
|
2556 |
|
| 2544 |
// note: segments.length > 0 -> hierarchical |
2557 |
// note: segments.length > 0 -> hierarchical |
| 2545 |
return new URI(true, scheme, authority, device, absolutePath, |
2558 |
return new URI(true, scheme, authority, device, absolutePath, |
| 2546 |
newSegments, query, fragment); |
2559 |
newSegments, query, fragment); |
| 2547 |
} |
2560 |
} |
| 2548 |
|
2561 |
|
| 2549 |
/** |
2562 |
/** |
|
Lines 2566-2572
Link Here
|
| 2566 |
|
2579 |
|
| 2567 |
// note: segments.length > 0 -> hierarchical |
2580 |
// note: segments.length > 0 -> hierarchical |
| 2568 |
return new URI(true, scheme, authority, device, absolutePath, |
2581 |
return new URI(true, scheme, authority, device, absolutePath, |
| 2569 |
newSegments, query, fragment); |
2582 |
newSegments, query, fragment); |
| 2570 |
} |
2583 |
} |
| 2571 |
|
2584 |
|
| 2572 |
/** |
2585 |
/** |
|
Lines 2674-2680
Link Here
|
| 2674 |
{ |
2687 |
{ |
| 2675 |
return NO_SEGMENTS; |
2688 |
return NO_SEGMENTS; |
| 2676 |
} |
2689 |
} |
| 2677 |
|
2690 |
|
| 2678 |
// Otherwise, the path needs only the remaining segments. |
2691 |
// Otherwise, the path needs only the remaining segments. |
| 2679 |
String[] newSegments = new String[segments.length - i]; |
2692 |
String[] newSegments = new String[segments.length - i]; |
| 2680 |
System.arraycopy(segments, i, newSegments, 0, newSegments.length); |
2693 |
System.arraycopy(segments, i, newSegments, 0, newSegments.length); |
|
Lines 2685-2696
Link Here
|
| 2685 |
* Encodes a string so as to produce a valid opaque part value, as defined |
2698 |
* Encodes a string so as to produce a valid opaque part value, as defined |
| 2686 |
* by the RFC. All excluded characters, such as space and <code>#</code>, |
2699 |
* by the RFC. All excluded characters, such as space and <code>#</code>, |
| 2687 |
* are escaped, as is <code>/</code> if it is the first character. |
2700 |
* are escaped, as is <code>/</code> if it is the first character. |
| 2688 |
* |
2701 |
* |
| 2689 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
2702 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 2690 |
* unescaped if they already begin a valid three-character escape sequence; |
2703 |
* unescaped if they already begin a valid three-character escape sequence; |
| 2691 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
2704 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 2692 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
2705 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 2693 |
* escaped. |
2706 |
* escaped. |
| 2694 |
*/ |
2707 |
*/ |
| 2695 |
public static String encodeOpaquePart(String value, boolean ignoreEscaped) |
2708 |
public static String encodeOpaquePart(String value, boolean ignoreEscaped) |
| 2696 |
{ |
2709 |
{ |
|
Lines 2704-2715
Link Here
|
| 2704 |
* Encodes a string so as to produce a valid authority, as defined by the |
2717 |
* Encodes a string so as to produce a valid authority, as defined by the |
| 2705 |
* RFC. All excluded characters, such as space and <code>#</code>, |
2718 |
* RFC. All excluded characters, such as space and <code>#</code>, |
| 2706 |
* are escaped, as are <code>/</code> and <code>?</code> |
2719 |
* are escaped, as are <code>/</code> and <code>?</code> |
| 2707 |
* |
2720 |
* |
| 2708 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
2721 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 2709 |
* unescaped if they already begin a valid three-character escape sequence; |
2722 |
* unescaped if they already begin a valid three-character escape sequence; |
| 2710 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
2723 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 2711 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
2724 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 2712 |
* escaped. |
2725 |
* escaped. |
| 2713 |
*/ |
2726 |
*/ |
| 2714 |
public static String encodeAuthority(String value, boolean ignoreEscaped) |
2727 |
public static String encodeAuthority(String value, boolean ignoreEscaped) |
| 2715 |
{ |
2728 |
{ |
|
Lines 2720-2731
Link Here
|
| 2720 |
* Encodes a string so as to produce a valid segment, as defined by the |
2733 |
* Encodes a string so as to produce a valid segment, as defined by the |
| 2721 |
* RFC. All excluded characters, such as space and <code>#</code>, |
2734 |
* RFC. All excluded characters, such as space and <code>#</code>, |
| 2722 |
* are escaped, as are <code>/</code> and <code>?</code> |
2735 |
* are escaped, as are <code>/</code> and <code>?</code> |
| 2723 |
* |
2736 |
* |
| 2724 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
2737 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 2725 |
* unescaped if they already begin a valid three-character escape sequence; |
2738 |
* unescaped if they already begin a valid three-character escape sequence; |
| 2726 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
2739 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 2727 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
2740 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 2728 |
* escaped. |
2741 |
* escaped. |
| 2729 |
*/ |
2742 |
*/ |
| 2730 |
public static String encodeSegment(String value, boolean ignoreEscaped) |
2743 |
public static String encodeSegment(String value, boolean ignoreEscaped) |
| 2731 |
{ |
2744 |
{ |
|
Lines 2735-2746
Link Here
|
| 2735 |
/** |
2748 |
/** |
| 2736 |
* Encodes a string so as to produce a valid query, as defined by the RFC. |
2749 |
* Encodes a string so as to produce a valid query, as defined by the RFC. |
| 2737 |
* Only excluded characters, such as space and <code>#</code>, are escaped. |
2750 |
* Only excluded characters, such as space and <code>#</code>, are escaped. |
| 2738 |
* |
2751 |
* |
| 2739 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
2752 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 2740 |
* unescaped if they already begin a valid three-character escape sequence; |
2753 |
* unescaped if they already begin a valid three-character escape sequence; |
| 2741 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
2754 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 2742 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
2755 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 2743 |
* escaped. |
2756 |
* escaped. |
| 2744 |
*/ |
2757 |
*/ |
| 2745 |
public static String encodeQuery(String value, boolean ignoreEscaped) |
2758 |
public static String encodeQuery(String value, boolean ignoreEscaped) |
| 2746 |
{ |
2759 |
{ |
|
Lines 2751-2762
Link Here
|
| 2751 |
* Encodes a string so as to produce a valid fragment, as defined by the |
2764 |
* Encodes a string so as to produce a valid fragment, as defined by the |
| 2752 |
* RFC. Only excluded characters, such as space and <code>#</code>, are |
2765 |
* RFC. Only excluded characters, such as space and <code>#</code>, are |
| 2753 |
* escaped. |
2766 |
* escaped. |
| 2754 |
* |
2767 |
* |
| 2755 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
2768 |
* @param ignoreEscaped <code>true</code> to leave <code>%</code> characters |
| 2756 |
* unescaped if they already begin a valid three-character escape sequence; |
2769 |
* unescaped if they already begin a valid three-character escape sequence; |
| 2757 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
2770 |
* <code>false</code> to encode all <code>%</code> characters. Note that |
| 2758 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
2771 |
* if a <code>%</code> is not followed by 2 hex digits, it will always be |
| 2759 |
* escaped. |
2772 |
* escaped. |
| 2760 |
*/ |
2773 |
*/ |
| 2761 |
public static String encodeFragment(String value, boolean ignoreEscaped) |
2774 |
public static String encodeFragment(String value, boolean ignoreEscaped) |
| 2762 |
{ |
2775 |
{ |
|
Lines 2779-2785
Link Here
|
| 2779 |
result.append(scheme); |
2792 |
result.append(scheme); |
| 2780 |
result.append(SCHEME_SEPARATOR); |
2793 |
result.append(SCHEME_SEPARATOR); |
| 2781 |
} |
2794 |
} |
| 2782 |
|
2795 |
|
| 2783 |
int j = |
2796 |
int j = |
| 2784 |
fragmentLocationStyle == FRAGMENT_FIRST_SEPARATOR ? uri.indexOf(FRAGMENT_SEPARATOR) : |
2797 |
fragmentLocationStyle == FRAGMENT_FIRST_SEPARATOR ? uri.indexOf(FRAGMENT_SEPARATOR) : |
| 2785 |
fragmentLocationStyle == FRAGMENT_LAST_SEPARATOR ? uri.lastIndexOf(FRAGMENT_SEPARATOR) : -1; |
2798 |
fragmentLocationStyle == FRAGMENT_LAST_SEPARATOR ? uri.lastIndexOf(FRAGMENT_SEPARATOR) : -1; |
|
Lines 2798-2804
Link Here
|
| 2798 |
String sspart = uri.substring(++i); |
2811 |
String sspart = uri.substring(++i); |
| 2799 |
result.append(encode(sspart, URIC_HI, URIC_LO, ignoreEscaped)); |
2812 |
result.append(encode(sspart, URIC_HI, URIC_LO, ignoreEscaped)); |
| 2800 |
} |
2813 |
} |
| 2801 |
|
2814 |
|
| 2802 |
return result.toString(); |
2815 |
return result.toString(); |
| 2803 |
} |
2816 |
} |
| 2804 |
|
2817 |
|
|
Lines 2871-2877
Link Here
|
| 2871 |
|
2884 |
|
| 2872 |
for (int i = 0, len = value.length(); i < len; i++) |
2885 |
for (int i = 0, len = value.length(); i < len; i++) |
| 2873 |
{ |
2886 |
{ |
| 2874 |
if (isEscaped(value, i)) |
2887 |
if (isEscaped(value, i)) |
| 2875 |
{ |
2888 |
{ |
| 2876 |
if (result == null) |
2889 |
if (result == null) |
| 2877 |
{ |
2890 |
{ |
|
Lines 2918-2929
Link Here
|
| 2918 |
* Returns <code>true</code> if this URI contains non-ASCII characters; |
2931 |
* Returns <code>true</code> if this URI contains non-ASCII characters; |
| 2919 |
* <code>false</code> otherwise. |
2932 |
* <code>false</code> otherwise. |
| 2920 |
* |
2933 |
* |
| 2921 |
* This unused code is included for possible future use... |
2934 |
* This unused code is included for possible future use... |
| 2922 |
*/ |
2935 |
*/ |
| 2923 |
/* |
2936 |
/* |
| 2924 |
public boolean isIRI() |
2937 |
public boolean isIRI() |
| 2925 |
{ |
2938 |
{ |
| 2926 |
return iri; |
2939 |
return iri; |
| 2927 |
} |
2940 |
} |
| 2928 |
|
2941 |
|
| 2929 |
// Returns true if the given string contains any non-ASCII characters; |
2942 |
// Returns true if the given string contains any non-ASCII characters; |
|
Lines 2962-2968
Link Here
|
| 2962 |
{ |
2975 |
{ |
| 2963 |
eSegments[i] = encodeAsASCII(segments[i]); |
2976 |
eSegments[i] = encodeAsASCII(segments[i]); |
| 2964 |
} |
2977 |
} |
| 2965 |
cachedASCIIURI = new URI(hierarchical, scheme, eAuthority, eDevice, absolutePath, eSegments, eQuery, eFragment); |
2978 |
cachedASCIIURI = new URI(hierarchical, scheme, eAuthority, eDevice, absolutePath, eSegments, eQuery, eFragment); |
| 2966 |
|
2979 |
|
| 2967 |
} |
2980 |
} |
| 2968 |
return cachedASCIIURI; |
2981 |
return cachedASCIIURI; |