package com.sun.slp;
import java.util.*;
class ServiceLocationAttributeV1 extends ServiceLocationAttribute {
String charCode = IANACharCode.UTF8;
final private static String UNESCAPABLE_CHARS = ",=!></*()";
final private static String ESCAPABLE_CHARS =
UNESCAPABLE_CHARS + "&#;";
static class Radix64 extends Object {
private static char LUT(char cin) {
int i = (int)(cin & (char)0x00FF);
char result = ' ';
if (i < 26) {
result = (char)((char)i + 'A');
} else if (i < 52) {
result = (char)((char)(i - 26) + 'a');
} else if (i < 62) {
result = (char)((char)(i - 52) + '0');
} else if (i == 62) {
result = '+';
} else if (i == 63) {
result = '/';
}
return result;
}
private static char LUT2(char cin, String s)
throws ServiceLocationException {
int i = (int)(cin & 0x00ff);
char c = (char) 0xffff;
if (((char)i >= 'A') && ((char)i <= 'Z')) {
c = (char)((char)i - 'A');
}
if (((char)i >= 'a') && ((char)i <= 'z')) {
c = (char)((char)i - 'a' +(char) 26);
}
if (((char)i >= '0') && ((char)i <= '9')) {
c = (char)((char)i - '0' +(char) 52);
}
if ((char)i == '+') {
c = (char)62;
}
if ((char)i == '/') {
c = (char)63;
}
if ((char)i == '=') {
c = (char)0;
}
if (c == 0xffff) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
return c;
}
static Opaque radix64ToOpaque(String s)
throws ServiceLocationException {
if (s == null || s.trim().length() == 0) {
return new Opaque(new byte[0]);
}
int oplen = 0;
int scan = 0;
while (scan < s.length()) {
if (s.charAt(scan) == '(') {
break;
}
scan++;
}
scan++;
while (scan < s.length()) {
if (Character.isWhitespace(s.charAt(scan)) == false) {
break;
}
scan++;
}
while (scan < s.length()) {
if (Character.isDigit(s.charAt(scan))) {
oplen *= 10;
oplen += (s.charAt(scan) - '0');
scan++;
} else {
break;
}
}
if (scan >= s.length()) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
if (s.charAt(scan) != ':') {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
scan++;
byte b[] = new byte[oplen];
int pos = 0;
int timesthrough = (oplen/3);
if ((oplen %3) != 0) {
timesthrough++;
}
for (int i = 0; i < timesthrough; i++) {
char v[] = new char[4];
for (int x = 0; x < 4; x++) {
while ((scan < s.length()) &&
Character.isWhitespace(s.charAt(scan))) {
scan++;
}
if (scan >= s.length()) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
v[x] = LUT2(s.charAt(scan), s);
scan++;
}
b[pos++] =
(byte) (((0x3F & v[0]) << 2) + ((0x30 & v[1]) >> 4));
if (pos >= oplen) break;
b[pos++] =
(byte) (((0x0F & v[1]) << 4) + ((0x3C & v[2]) >> 2));
if (pos >= oplen) break;
b[pos++] = (byte) (((0x03 & v[2]) << 6) + (0x3F & v[3]));
}
if (scan >= s.length()) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
if (s.charAt(scan) != ')') {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_radix64_error",
new Object[] {s});
}
return new Opaque(b);
}
static String opaqueToRadix64(Opaque oq) {
byte[] b = oq.bytes;
if (b == null) {
return new String("");
}
StringBuffer sb = new StringBuffer("("+b.length+":");
int datalen;
int fill = b.length%3;
if (fill == 0) {
datalen = (b.length / 3) * 4;
} else {
datalen = ((b.length / 3) + 1) * 4;
}
int dataoffset = 0;
int more = (b.length%3);
if (more != 0) {
more = 1;
}
int a[] = new int[4];
for (int i = 0; i < ((b.length/3)+more-1); i++) {
a[0] = (int)(0xFC & (char)b[ dataoffset ]) >> 2;
a[1] = ((int)(0x03 & (char)b[ dataoffset ]) << 4) +
((int)(0xF0 & (char)b[ dataoffset + 1]) >> 4);
a[2] = ((int)(0x0F & (char)b[ dataoffset + 1]) << 2) +
((int)(0xC0 & (char)b[ dataoffset + 2]) >> 6);
a[3] = (int)(0x3F & (char)b[ dataoffset + 2]);
for (int j = 0; j < 4; j++) {
sb.append(LUT((char)a[j]));
}
dataoffset += 3;
}
byte f1 = 0, f2 = 0;
if (fill == 0) {
f1 = b[ dataoffset + 1 ];
f2 = b[ dataoffset + 2 ];
} else if (fill == 2) {
f1 = b[ dataoffset + 1 ];
}
a[0] = (int) (0xFC & (char)b[ dataoffset ]) >> 2;
a[1] = ((int) (0x03 & (char)b[ dataoffset ]) << 4) +
((int) (0xF0 & (char)f1) >> 4);
a[2] = ((int) (0x0F & (char)f1) << 2) +
((int) (0xC0 & (char)f2) >> 6);
a[3] = (int) (0x3F & (char)f2);
for (int j = 0; j < 4; j++) {
sb.append(LUT((char) a[j]));
}
sb.append(")");
return sb.toString();
}
}
ServiceLocationAttributeV1(ServiceLocationAttribute attr) {
id = attr.id;
values = attr.values;
}
ServiceLocationAttributeV1(String exp,
String charCode,
boolean allowMultiValuedBooleans)
throws ServiceLocationException {
this.charCode = charCode;
if (exp.startsWith("(") && exp.endsWith(")")) {
StringTokenizer tk =
new StringTokenizer(exp.substring(1, exp.length() - 1),
"=",
true);
try {
id =
unescapeAttributeString(tk.nextToken(), charCode);
if (id.length() <= 0) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"null_id",
new Object[] {exp});
}
tk.nextToken();
String rest = tk.nextToken("");
values = SrvLocHeader.parseCommaSeparatedListIn(rest, true);
int i, n = values.size();
Class vecClass = null;
for (i = 0; i < n; i++) {
String value = (String)values.elementAt(i);
Object o = evaluate(value, charCode);
if (o instanceof Opaque) {
o = ((Opaque)o).bytes;
}
values.setElementAt(o, i);
}
} catch (NoSuchElementException ex) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"assignment_syntax_err",
new Object[] {exp});
}
verifyValueTypes(values, allowMultiValuedBooleans);
} else {
if (exp.indexOf('(') != -1 || exp.indexOf(')') != -1) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"assignment_syntax_err",
new Object[] {exp});
}
id = unescapeAttributeString(exp, charCode);
}
}
static Object evaluate(String value, String charCode)
throws ServiceLocationException {
Object o = null;
try {
o = Integer.valueOf(value);
} catch (NumberFormatException ex) {
if (value.equalsIgnoreCase(TRUE) ||
value.equalsIgnoreCase(FALSE)) {
o = Boolean.valueOf(value);
} else {
String val = (String)value;
if (val.startsWith("(")) {
o = Radix64.radix64ToOpaque(val);
} else {
o = unescapeAttributeString(val, charCode);
}
}
}
return o;
}
String externalize()
throws ServiceLocationException {
if (values == null) {
return escapeAttributeString(id, charCode);
}
Vector v = new Vector();
for (Enumeration e = values.elements(); e.hasMoreElements(); ) {
Object o = e.nextElement();
String s = null;
s = escapeValueInternal(o, charCode);
v.addElement(s);
}
StringBuffer buf =
new StringBuffer("(" +
escapeAttributeString(id, charCode) +
"=");
buf.append(SrvLocHeader.vectorToCommaSeparatedList(v));
buf.append(")");
return buf.toString();
}
private static String escapeValueInternal(Object val, String charCode) {
String s;
if (val instanceof String) {
try {
s = escapeAttributeString((String)val, charCode);
} catch (ServiceLocationException ex) {
throw
new IllegalArgumentException(ex.getMessage());
}
} else if (val instanceof Opaque) {
s = Radix64.opaqueToRadix64((Opaque)val);
} else {
s = val.toString();
}
return s;
}
static String escapeAttributeString(String string,
String charCode)
throws ServiceLocationException {
StringBuffer buf = new StringBuffer();
int i, n = string.length();
boolean is8bit =
(charCode.equals(IANACharCode.ASCII) ||
charCode.equals(IANACharCode.LATIN1));
for (i = 0; i < n; i++) {
char c = string.charAt(i);
if (ESCAPABLE_CHARS.indexOf(c) != -1) {
buf.append("&#");
buf.append(IANACharCode.escapeChar(c, charCode));
buf.append(";");
} else {
if (is8bit && (short)c > 255) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_8bit_error",
new Object[] {Character.valueOf(c)});
}
buf.append(c);
}
}
return buf.toString();
}
static String unescapeAttributeString(String string,
String charCode)
throws ServiceLocationException {
int i, n = string.length();
StringBuffer buf = new StringBuffer(n);
for (i = 0; i < n; i++) {
char c = string.charAt(i);
int idx = -1;
if ((idx = UNESCAPABLE_CHARS.indexOf(c)) != -1) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
if (c != '&') {
buf.append(c);
} else {
if ((i + 1) >= n) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
c = string.charAt(++i);
if (c != '#') {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
StringBuffer num = new StringBuffer(n);
for (i++; i < n; i++) {
c = string.charAt(i);
if (!Character.isDigit(c)) {
break;
}
num.append(c);
}
if (num.length() <= 0) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
if (c != ';') {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
try {
buf.append(IANACharCode.unescapeChar(num.toString(),
charCode));
} catch (NumberFormatException ex) {
throw
new ServiceLocationException(
ServiceLocationException.PARSE_ERROR,
"v1_escape_error",
new Object[] {string});
}
}
}
return buf.toString();
}
}