1 package net.sf.saxon.value; 2 3 import net.sf.saxon.expr.XPathContext; 4 import net.sf.saxon.om.FastStringBuffer; 5 import net.sf.saxon.trans.DynamicError; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.*; 8 import net.sf.saxon.ConversionContext; 9 10 import java.io.ByteArrayOutputStream ; 11 12 15 16 public class Base64BinaryValue extends AtomicValue { 17 18 private byte[] binaryValue; 19 20 21 25 26 public Base64BinaryValue(CharSequence s) { 27 Base64Decoder decoder = new Base64Decoder(); 28 decoder.translate(s); 29 binaryValue = decoder.getByteArray(); 30 } 31 32 35 36 public Base64BinaryValue(byte[] value) { 37 this.binaryValue = value; 38 } 39 40 43 44 public byte[] getBinaryValue() { 45 return binaryValue; 46 } 47 48 54 55 public AtomicValue convertPrimitive(BuiltInAtomicType requiredType, boolean validate, ConversionContext conversion) { 56 switch (requiredType.getPrimitiveType()) { 57 case Type.BASE64_BINARY: 58 case Type.ATOMIC: 59 case Type.ITEM: 60 return this; 61 case Type.STRING: 62 return new StringValue(getStringValueCS()); 63 case Type.UNTYPED_ATOMIC: 64 return new UntypedAtomicValue(getStringValueCS()); 65 case Type.HEX_BINARY: 66 return new HexBinaryValue(binaryValue); 67 default: 68 ValidationException err = new ValidationException("Cannot convert base64Binary to " + 69 requiredType.getDisplayName()); 70 err.setErrorCode("FORG0001"); 71 return new ValidationErrorValue(err); 72 } 73 } 74 75 79 80 public String getStringValue() { 81 Base64Encoder encoder = new Base64Encoder(); 82 encoder.translate(binaryValue); 83 return new String (encoder.getCharArray()); 84 } 85 86 89 90 public int getLengthInOctets() { 91 return binaryValue.length; 92 } 93 94 98 99 public ItemType getItemType() { 100 return Type.BASE64_BINARY_TYPE; 101 } 102 103 106 107 public Object convertToJava(Class target, XPathContext context) throws XPathException { 108 109 if (target.isAssignableFrom(Base64BinaryValue.class)) { 110 return this; 111 } else if (target == String .class || target == CharSequence .class) { 112 return getStringValue(); 113 } else if (target == Object .class) { 114 return getStringValue(); 115 } else { 116 Object o = super.convertToJava(target, context); 117 if (o == null) { 118 throw new DynamicError("Conversion of base64Binary to " + target.getName() + 119 " is not supported"); 120 } 121 return o; 122 } 123 } 124 125 126 129 130 public boolean equals(Object other) { 131 Base64BinaryValue v2; 132 if (other instanceof Base64BinaryValue) { 133 v2 = (Base64BinaryValue)other; 134 } else if (other instanceof AtomicValue) { 135 try { 136 v2 = (Base64BinaryValue)((AtomicValue)other).convert(Type.BASE64_BINARY, null); 137 } catch (XPathException err) { 138 return false; 139 } 140 } else { 141 return false; 142 } 143 if (binaryValue.length != v2.binaryValue.length) { 144 return false; 145 } 146 ; 147 for (int i = 0; i < binaryValue.length; i++) { 148 if (binaryValue[i] != v2.binaryValue[i]) { 149 return false; 150 } 151 ; 152 } 153 return true; 154 } 155 156 public int hashCode() { 157 return byteArrayHashCode(binaryValue); 158 } 159 160 protected static int byteArrayHashCode(byte[] value) { 161 long h = 0; 162 for (int i=0; i<Math.min(value.length, 64); i++) { 163 h = (h<<1) ^ value[i]; 164 } 165 return (int)((h>>32)^h)&0xffffffff; 166 } 167 168 189 190 198 private static final class Base64Encoder { 199 200 private FastStringBuffer out = new FastStringBuffer(256); 201 202 private int buf = 0; 204 private int buf_bytes = 0; 206 private char line[] = new char[74]; 208 private int line_length = 0; 210 212 private static final char map[] = { 213 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', }; 222 223 224 private void encode_token() { 225 int i = line_length; 226 line[i] = map[0x3F & (buf >> 18)]; line[i + 1] = map[0x3F & (buf >> 12)]; line[i + 2] = map[0x3F & (buf >> 6)]; line[i + 3] = map[0x3F & buf]; line_length += 4; 231 buf = 0; 232 buf_bytes = 0; 233 } 234 235 236 private void encode_partial_token() { 237 int i = line_length; 238 line[i] = map[0x3F & (buf >> 18)]; line[i + 1] = map[0x3F & (buf >> 12)]; 241 if (buf_bytes == 1) 242 line[i + 2] = '='; 243 else 244 line[i + 2] = map[0x3F & (buf >> 6)]; 246 if (buf_bytes <= 2) 247 line[i + 3] = '='; 248 else 249 line[i + 3] = map[0x3F & buf]; line_length += 4; 251 buf = 0; 252 buf_bytes = 0; 253 } 254 255 256 private void flush_line() { 257 out.append(line, 0, line_length); 258 line_length = 0; 259 } 260 261 262 268 public final void translate(byte[] in) { 269 int in_length = in.length; 270 271 for (int i = 0; i < in_length; i++) { 272 if (buf_bytes == 0) 273 buf = (buf & 0x00FFFF) | (in[i] << 16); 274 else if (buf_bytes == 1) 275 buf = (buf & 0xFF00FF) | ((in[i] << 8) & 0x00FFFF); 276 else 277 buf = (buf & 0xFFFF00) | (in[i] & 0x0000FF); 278 279 if ((++buf_bytes) == 3) { 280 encode_token(); 281 if (line_length >= 72) { 282 flush_line(); 283 } 284 } 285 286 if (i == (in_length - 1)) { 287 if ((buf_bytes > 0) && (buf_bytes < 3)) 288 encode_partial_token(); 289 if (line_length > 0) 290 flush_line(); 291 } 292 } 293 294 for (int i = 0; i < line.length; i++) 295 line[i] = 0; 296 } 297 298 299 public char[] getCharArray() { 300 char[] ch; 301 302 if (buf_bytes != 0) 303 encode_partial_token(); 304 flush_line(); 305 for (int i = 0; i < line.length; i++) 306 line[i] = 0; 307 ch = new char[out.length()]; 308 if (out.length() > 0) 309 out.getChars(0, out.length(), ch, 0); 310 return ch; 311 } 312 } 313 314 335 336 337 345 346 private static final class Base64Decoder { 347 private ByteArrayOutputStream out = new ByteArrayOutputStream (); 348 349 private byte token[] = new byte[4]; 351 private byte bytes[] = new byte[3]; 353 private int token_length = 0; 355 private static final byte NUL = 127; 357 private static final byte EOF = 126; 359 private static final byte[] map = { 360 NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 62, NUL, NUL, NUL, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NUL, NUL, NUL, EOF, NUL, NUL, 369 NUL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NUL, NUL, NUL, NUL, NUL, NUL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NUL, NUL, NUL, NUL, NUL, 378 NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 387 NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, }; 396 397 398 private void decode_token() { 401 int num = ((token[0] << 18) | 402 (token[1] << 12) | 403 (token[2] << 6) | 404 (token[3])); 405 406 bytes[0] = (byte)(0xFF & (num >> 16)); 407 bytes[1] = (byte)(0xFF & (num >> 8)); 408 bytes[2] = (byte)(0xFF & num); 409 410 out.write(bytes, 0, 3); 411 } 412 413 414 private void decode_final_token() { 418 419 byte b0 = token[0]; 420 byte b1 = token[1]; 421 byte b2 = token[2]; 422 byte b3 = token[3]; 423 424 int eq_count = 0; 425 426 if (b0 == EOF) { 427 b0 = 0; 428 eq_count++; 429 } 430 if (b1 == EOF) { 431 b1 = 0; 432 eq_count++; 433 } 434 if (b2 == EOF) { 435 b2 = 0; 436 eq_count++; 437 } 438 if (b3 == EOF) { 439 b3 = 0; 440 eq_count++; 441 } 442 443 int num = ((b0 << 18) | (b1 << 12) | (b2 << 6) | (b3)); 444 445 453 out.write((byte)(num >> 16)); if (eq_count <= 1) { 455 out.write((byte)((num >> 8) & 0xFF)); if (eq_count == 0) { 457 out.write((byte)(num & 0xFF)); } 459 } 460 } 461 462 463 public final void translate(CharSequence str) { 464 if (token == null) return; 466 int length = str.length(); 467 for (int i = 0; i < length; i++) { 468 byte t = map[(str.charAt(i) & 0xff)]; 469 470 if (t == EOF) { 471 eof(); 472 } else if (t != NUL) { 473 token[token_length++] = t; 474 } 475 if (token_length == 4) { 476 decode_token(); 477 token_length = 0; 478 } 479 } 480 } 481 482 private void eof() { 483 if (token != null && token_length != 0) { 484 while (token_length < 4) 485 token[token_length++] = EOF; 486 decode_final_token(); 487 } 488 token_length = 0; 489 token = new byte[4]; 490 bytes = new byte[3]; 491 } 492 493 public byte[] getByteArray() { 494 eof(); 495 return out.toByteArray(); 496 } 497 } 498 499 } 500 501 520 | Popular Tags |