1 8 9 package org.jboss.axis.attachments; 10 11 12 import org.jboss.axis.utils.Messages; 13 import org.jboss.logging.Logger; 14 15 import java.io.IOException ; 16 17 18 51 public class DimeDelimitedInputStream extends java.io.FilterInputStream 52 { 53 private static Logger log = Logger.getLogger(DimeDelimitedInputStream.class.getName()); 54 55 java.io.InputStream is = null; volatile boolean closed = true; boolean theEnd = false; boolean moreChunks = false; boolean MB = false; boolean ME = false; DimeTypeNameFormat tnf = null; 62 String type = null; 63 String id = null; 64 long recordLength = 0L; long bytesRead = 0; int dataPadLength = 0; private static byte[] trash = new byte[4]; 68 protected int streamNo = 0; 69 protected IOException streamInError = null; 70 71 protected static int streamCount = 0; 73 protected static synchronized int newStreamNo() 74 { 75 log.debug(Messages.getMessage("streamNo", "" + (streamCount + 1))); 76 return ++streamCount; 77 } 78 79 static boolean isDebugEnabled = false; 80 81 86 synchronized DimeDelimitedInputStream getNextStream() 87 throws IOException 88 { 89 if (null != streamInError) throw streamInError; 90 if (theEnd) return null; 91 if (bytesRead < recordLength || moreChunks) throw new RuntimeException (Messages.getMessage("attach.dimeReadFullyError")); 93 dataPadLength -= readPad(dataPadLength); 94 95 return new DimeDelimitedInputStream(this.is); 97 } 98 99 102 DimeDelimitedInputStream(java.io.InputStream is) throws IOException 103 { 104 super(null); isDebugEnabled = log.isDebugEnabled(); 106 streamNo = newStreamNo(); 107 closed = false; 108 this.is = is; 109 readHeader(false); 110 } 111 112 private final int readPad(final int size) throws IOException 113 { 114 if (0 == size) return 0; 115 int read = readFromStream(trash, 0, size); 116 117 if (size != read) 118 { 119 streamInError = new IOException (Messages.getMessage("attach.dimeNotPaddedCorrectly")); 120 throw streamInError; 121 } 122 return read; 123 } 124 125 private final int readFromStream(final byte[] b) throws IOException 126 { 127 return readFromStream(b, 0, b.length); 128 } 129 130 private final int readFromStream(final byte[] b, 131 final int start, final int length) 132 throws IOException 133 { 134 if (length == 0) return 0; 135 136 int br = 0; 137 int brTotal = 0; 138 139 do 140 { 141 try 142 { 143 br = is.read(b, brTotal + start, length - brTotal); 144 } 145 catch (IOException e) 146 { 147 streamInError = e; 148 throw e; 149 } 150 if (br > 0) brTotal += br; 151 } 152 while (br > -1 && brTotal < length); 153 154 return br > -1 ? brTotal : br; 155 } 156 157 162 public String getContentId() 163 { 164 return id; 165 } 166 167 174 public DimeTypeNameFormat getDimeTypeNameFormat() 175 { 176 return tnf; 177 } 178 179 186 187 public String getType() 188 { 189 return type; 190 } 191 192 199 public synchronized int read(byte[] b, final int off, 200 final int len) throws IOException 201 { 202 203 if (closed) 204 { 205 dataPadLength -= readPad(dataPadLength); 206 throw new IOException (Messages.getMessage("streamClosed")); 207 } 208 return _read(b, off, len); 209 } 210 211 protected int _read(byte[] b, final int off, final int len) 212 throws IOException 213 { 214 if (len < 0) 215 throw new IllegalArgumentException 216 (Messages.getMessage("attach.readLengthError", 217 "" + len)); 218 219 if (off < 0) 220 throw new IllegalArgumentException 221 (Messages.getMessage("attach.readOffsetError", 222 "" + off)); 223 if (b == null) 224 throw new IllegalArgumentException 225 (Messages.getMessage("attach.readArrayNullError")); 226 if (b.length < off + len) 227 throw new IllegalArgumentException 228 (Messages.getMessage("attach.readArraySizeError", 229 "" + b.length, "" + len, "" + off)); 230 231 if (null != streamInError) throw streamInError; 232 233 if (0 == len) return 0; 235 if (recordLength == 0 && bytesRead == 0 && !moreChunks) 236 { 237 ++bytesRead; if (ME) 239 { 240 finalClose(); 241 } 242 return 0; 243 } 244 if (bytesRead >= recordLength && !moreChunks) 245 { 246 dataPadLength -= readPad(dataPadLength); 247 if (ME) 248 { 249 finalClose(); 250 } 251 return -1; 252 } 253 254 int totalbytesread = 0; 255 int bytes2read = 0; 256 257 do 258 { 259 if (bytesRead >= recordLength && moreChunks) 260 readHeader(true); 261 262 bytes2read = (int)Math.min(recordLength - bytesRead, 263 (long)len - totalbytesread); 264 bytes2read = (int)Math.min(recordLength - bytesRead, 265 (long)len - totalbytesread); 266 try 267 { 268 bytes2read = is.read(b, off + totalbytesread, 269 bytes2read); 270 } 271 catch (IOException e) 272 { 273 streamInError = e; 274 throw e; 275 } 276 277 if (0 < bytes2read) 278 { 279 totalbytesread += bytes2read; 280 bytesRead += bytes2read; 281 } 282 283 } 284 while (bytes2read > -1 && totalbytesread < len && 285 (bytesRead < recordLength || moreChunks)); 286 287 if (0 > bytes2read) 288 { 289 if (moreChunks) 290 { 291 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError0")); 292 throw streamInError; 293 } 294 if (bytesRead < recordLength) 295 { 296 streamInError = new IOException (Messages.getMessage 297 ("attach.DimeStreamError1", 298 "" + (recordLength - bytesRead))); 299 throw streamInError; 300 } 301 if (!ME) 302 { 303 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError0")); 304 throw streamInError; 305 } 306 dataPadLength = 0; 308 309 } 310 else if (bytesRead >= recordLength) 311 { 312 try 314 { 315 dataPadLength -= readPad(dataPadLength); 316 } 317 catch (IOException e) 318 { 319 if (!ME) 321 throw e; 322 else 323 { 324 dataPadLength = 0; 325 streamInError = null; 326 } 327 } 328 } 329 330 if (bytesRead >= recordLength && ME) 331 { 332 finalClose(); 333 } 334 335 return totalbytesread >= 0 ? totalbytesread : -1; 336 } 337 338 void readHeader(boolean isChunk) throws IOException 339 { 340 341 bytesRead = 0; if (isChunk) 343 { 344 if (!moreChunks) 345 throw new RuntimeException (Messages.getMessage("attach.DimeStreamError2")); 346 dataPadLength -= readPad(dataPadLength); } 348 349 byte[] header = new byte[12]; 350 351 if (header.length != readFromStream(header)) 352 { 353 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError3", 354 "" + header.length)); 355 throw streamInError; 356 } 357 358 byte version = (byte)((header[0] >>> 3) & 0x1f); 360 361 if (version > DimeMultiPart.CURRENT_VERSION) 362 { 363 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError4", 364 "" + version, 365 "" + DimeMultiPart.CURRENT_VERSION)); 366 throw streamInError; 367 } 368 369 MB = 0 != (0x4 & header[0]); 371 ME = 0 != (0x2 & header[0]); 372 moreChunks = 0 != (0x1 & header[0]); 373 374 if (!isChunk) 376 tnf = DimeTypeNameFormat.parseByte((byte)((header[1] >>> 4) & (byte)0xf)); 377 378 int optionsLength = 380 ((((int)header[2]) << 8) & 0xff00) | ((int)header[3]); 381 382 int idLength = 384 ((((int)header[4]) << 8) & 0xff00) | ((int)header[5]); 385 386 int typeLength = ((((int)header[6]) << 8) & 0xff00) 388 | ((int)header[7]); 389 390 recordLength = ((((long)header[8]) << 24) & 0xff000000L) | 392 ((((long)header[9]) << 16) & 0xff0000L) | 393 ((((long)header[10]) << 8) & 0xff00L) | 394 ((long)header[11] & 0xffL); 395 396 398 if (0 != optionsLength) 399 { 400 byte[] optBytes = new byte[optionsLength]; 401 402 if (optionsLength != readFromStream(optBytes)) 403 { 404 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError5", 405 "" + optionsLength)); 406 throw streamInError; 407 } 408 optBytes = null; 410 int pad = DimeBodyPart.dimePadding(optionsLength); 411 412 if (pad != readFromStream(header, 0, pad)) 413 { 414 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError7")); 415 throw streamInError; 416 } 417 } 418 419 if (0 < idLength) 421 { 422 byte[] idBytes = new byte[idLength]; 423 424 if (idLength != readFromStream(idBytes)) 425 { 426 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError8")); 427 throw streamInError; 428 } 429 if (idLength != 0 && !isChunk) 430 { 431 id = new String (idBytes); 432 } 433 int pad = DimeBodyPart.dimePadding(idLength); 434 435 if (pad != readFromStream(header, 0, pad)) 436 { 437 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError9")); 438 throw streamInError; 439 } 440 } 441 442 if (0 < typeLength) 444 { 445 byte[] typeBytes = new byte[typeLength]; 446 447 if (typeLength != readFromStream(typeBytes)) 448 { 449 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError10")); 450 throw streamInError; 451 } 452 if (typeLength != 0 && !isChunk) 453 { 454 type = new String (typeBytes); 455 } 456 int pad = DimeBodyPart.dimePadding(typeLength); 457 458 if (pad != readFromStream(header, 0, pad)) 459 { 460 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError11")); 461 462 throw streamInError; 463 } 464 } 465 log.debug("MB:" + MB + ", ME:" + ME + ", CF:" + moreChunks + 466 "Option length:" + optionsLength + 467 ", ID length:" + idLength + 468 ", typeLength:" + typeLength + ", TYPE_T:" + tnf); 469 log.debug("id:\"" + id + "\""); 470 log.debug("type:\"" + type + "\""); 471 log.debug("recordlength:\"" + recordLength + "\""); 472 473 dataPadLength = DimeBodyPart.dimePadding(recordLength); 474 } 475 476 483 public int read(byte[] b) throws IOException 484 { 485 return read(b, 0, b.length); 486 } 487 488 493 494 public int read() throws IOException 495 { 496 byte[] b = new byte[1]; 497 int read = read(b, 0, 1); 498 499 if (read < 0) 500 return -1; 501 else 502 return b[0]; 503 } 504 505 508 public void close() throws IOException 509 { 510 synchronized (this) 511 { 512 if (closed) return; 513 closed = true; } 515 log.debug(Messages.getMessage("bStreamClosed", "" + streamNo)); 516 if (bytesRead < recordLength || moreChunks) 517 { 518 byte[] readrest = new byte[1024 * 16]; 521 int bread = 0; 522 523 do 524 { 525 bread = _read(readrest, 0, readrest.length); } 527 while (bread > -1); 528 } 529 dataPadLength -= readPad(dataPadLength); 530 } 531 532 536 public void mark(int readlimit) 537 { } 539 540 544 public void reset() throws IOException 545 { 546 streamInError = new IOException (Messages.getMessage("attach.bounday.mns")); 547 throw streamInError; 548 } 549 550 554 public boolean markSupported() 555 { 556 return false; 557 } 558 559 public synchronized int available() throws IOException 560 { 561 if (null != streamInError) throw streamInError; 562 int chunkAvail = (int)Math.min((long) 563 Integer.MAX_VALUE, recordLength - bytesRead); 564 565 int streamAvail = 0; 566 567 try 568 { 569 streamAvail = is.available(); 570 } 571 catch (IOException e) 572 { 573 streamInError = e; 574 throw e; 575 } 576 577 if (chunkAvail == 0 && moreChunks && (12 + dataPadLength) 578 <= streamAvail) 579 { 580 dataPadLength -= readPad(dataPadLength); 581 readHeader(true); 582 return available(); 583 } 584 return Math.min(streamAvail, chunkAvail); 585 } 586 587 protected void finalClose() throws IOException 588 { 589 try 590 { 591 theEnd = true; 592 if (null != is) is.close(); 593 } 594 finally 595 { 596 is = null; 597 } 598 } 599 } 600 | Popular Tags |