001: package org.kohsuke.rngom.util;
002:
003: import java.net.URL;
004: import java.net.MalformedURLException;
005: import java.io.UnsupportedEncodingException;
006:
007: public class Uri {
008: private static String utf8 = "UTF-8";
009:
010: public static boolean isValid(String s) {
011: return isValidPercent(s) && isValidFragment(s)
012: && isValidScheme(s);
013: }
014:
015: private static final String HEX_DIGITS = "0123456789abcdef";
016:
017: public static String escapeDisallowedChars(String s) {
018: StringBuffer buf = null;
019: int len = s.length();
020: int done = 0;
021: for (;;) {
022: int i = done;
023: for (;;) {
024: if (i == len) {
025: if (done == 0)
026: return s;
027: break;
028: }
029: if (isExcluded(s.charAt(i)))
030: break;
031: i++;
032: }
033: if (buf == null)
034: buf = new StringBuffer();
035: if (i > done) {
036: buf.append(s.substring(done, i));
037: done = i;
038: }
039: if (i == len)
040: break;
041: for (i++; i < len && isExcluded(s.charAt(i)); i++)
042: ;
043: String tem = s.substring(done, i);
044: byte[] bytes;
045: try {
046: bytes = tem.getBytes(utf8);
047: } catch (UnsupportedEncodingException e) {
048: utf8 = "UTF8";
049: try {
050: bytes = tem.getBytes(utf8);
051: } catch (UnsupportedEncodingException e2) {
052: // Give up
053: return s;
054: }
055: }
056: for (int j = 0; j < bytes.length; j++) {
057: buf.append('%');
058: buf.append(HEX_DIGITS.charAt((bytes[j] & 0xFF) >> 4));
059: buf.append(HEX_DIGITS.charAt(bytes[j] & 0xF));
060: }
061: done = i;
062: }
063: return buf.toString();
064: }
065:
066: private static final String excluded = "<>\"{}|\\^`";
067:
068: private static boolean isExcluded(char c) {
069: return c <= 0x20 || c >= 0x7F || excluded.indexOf(c) >= 0;
070: }
071:
072: private static boolean isAlpha(char c) {
073: return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
074: }
075:
076: private static boolean isHexDigit(char c) {
077: return ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
078: || isDigit(c);
079: }
080:
081: private static boolean isDigit(char c) {
082: return '0' <= c && c <= '9';
083: }
084:
085: private static boolean isSchemeChar(char c) {
086: return isAlpha(c) || isDigit(c) || c == '+' || c == '-'
087: || c == '.';
088: }
089:
090: private static boolean isValidPercent(String s) {
091: int len = s.length();
092: for (int i = 0; i < len; i++)
093: if (s.charAt(i) == '%') {
094: if (i + 2 >= len)
095: return false;
096: else if (!isHexDigit(s.charAt(i + 1))
097: || !isHexDigit(s.charAt(i + 2)))
098: return false;
099: }
100: return true;
101: }
102:
103: private static boolean isValidFragment(String s) {
104: int i = s.indexOf('#');
105: return i < 0 || s.indexOf('#', i + 1) < 0;
106: }
107:
108: private static boolean isValidScheme(String s) {
109: if (!isAbsolute(s))
110: return true;
111: int i = s.indexOf(':');
112: if (i == 0 || i + 1 == s.length() || !isAlpha(s.charAt(0)))
113: return false;
114: while (--i > 0)
115: if (!isSchemeChar(s.charAt(i)))
116: return false;
117: return true;
118: }
119:
120: public static String resolve(String baseUri, String uriReference) {
121: if (!isAbsolute(uriReference) && baseUri != null
122: && isAbsolute(baseUri)) {
123: try {
124: return new URL(new URL(baseUri), uriReference)
125: .toString();
126: } catch (MalformedURLException e) {
127: }
128: }
129: return uriReference;
130: }
131:
132: public static boolean hasFragmentId(String uri) {
133: return uri.indexOf('#') >= 0;
134: }
135:
136: public static boolean isAbsolute(String uri) {
137: int i = uri.indexOf(':');
138: if (i < 0)
139: return false;
140: while (--i >= 0) {
141: switch (uri.charAt(i)) {
142: case '#':
143: case '/':
144: case '?':
145: return false;
146: }
147: }
148: return true;
149: }
150: }
|