1 16 17 package org.apache.axis.attachments; 18 19 20 import org.apache.axis.components.logger.LogFactory; 21 import org.apache.axis.utils.Messages; 22 import org.apache.commons.logging.Log; 23 24 import java.io.IOException ; 25 26 27 61 public class DimeDelimitedInputStream extends java.io.FilterInputStream { 62 protected static Log log = 63 LogFactory.getLog(DimeDelimitedInputStream.class.getName()); 64 65 java.io.InputStream is = null; volatile boolean closed = true; boolean theEnd = false; boolean moreChunks = false; boolean MB = false; boolean ME = false; DimeTypeNameFormat tnf = null; 72 String type = null; 73 String id = null; 74 long recordLength = 0L; long bytesRead = 0; int dataPadLength = 0; private static byte[] trash = new byte[4]; 78 protected int streamNo = 0; 79 protected IOException streamInError = null; 80 81 protected static int streamCount = 0; 83 protected static synchronized int newStreamNo() { 84 log.debug(Messages.getMessage("streamNo", "" + (streamCount + 1))); 85 return ++streamCount; 86 } 87 88 static boolean isDebugEnabled = false; 89 90 97 synchronized DimeDelimitedInputStream getNextStream() 98 throws IOException 99 { 100 if (null != streamInError) throw streamInError; 101 if (theEnd) return null; 102 if (bytesRead < recordLength || moreChunks) throw new RuntimeException (Messages.getMessage( 104 "attach.dimeReadFullyError")); 105 dataPadLength -= readPad(dataPadLength); 106 107 return new DimeDelimitedInputStream(this.is); 109 } 110 111 117 DimeDelimitedInputStream(java.io.InputStream is) throws IOException { 118 super(null); isDebugEnabled = log.isDebugEnabled(); 120 streamNo = newStreamNo(); 121 closed = false; 122 this.is = is; 123 readHeader(false); 124 } 125 126 private final int readPad(final int size) throws IOException { 127 if (0 == size) return 0; 128 int read = readFromStream(trash, 0, size); 129 130 if (size != read) { 131 streamInError = new IOException (Messages.getMessage( 132 "attach.dimeNotPaddedCorrectly")); 133 throw streamInError; 134 } 135 return read; 136 } 137 138 private final int readFromStream(final byte[] b) throws IOException { 139 return readFromStream(b, 0, b.length); 140 } 141 142 private final int readFromStream(final byte[] b, 143 final int start, final int length) 144 throws IOException { 145 if (length == 0) return 0; 146 147 int br = 0; 148 int brTotal = 0; 149 150 do { 151 try { 152 br = is.read(b, brTotal + start, length - brTotal); 153 } catch (IOException e) { 154 streamInError = e; 155 throw e; 156 } 157 if (br > 0) brTotal += br; 158 } 159 while (br > -1 && brTotal < length); 160 161 return br > -1 ? brTotal : br; 162 } 163 164 168 public String getContentId() { 169 return id; 170 } 171 172 public DimeTypeNameFormat getDimeTypeNameFormat() { 173 return tnf; 174 } 175 176 181 182 public String getType() { 183 return type; 184 } 185 186 194 public synchronized int read(byte[] b, final int off, 195 final int len) throws IOException { 196 197 if (closed) { 198 dataPadLength -= readPad(dataPadLength); 199 throw new IOException (Messages.getMessage("streamClosed")); 200 } 201 return _read(b, off, len); 202 } 203 204 protected int _read(byte[] b, final int off, final int len) 205 throws IOException { 206 if (len < 0) throw new IllegalArgumentException 207 (Messages.getMessage("attach.readLengthError", 208 "" + len)); 209 210 if (off < 0) throw new IllegalArgumentException 211 (Messages.getMessage("attach.readOffsetError", 212 "" + off)); 213 if (b == null) throw new IllegalArgumentException 214 (Messages.getMessage("attach.readArrayNullError")); 215 if (b.length < off + len) throw new IllegalArgumentException 216 (Messages.getMessage("attach.readArraySizeError", 217 "" + b.length, "" + len, "" + off)); 218 219 if (null != streamInError) throw streamInError; 220 221 if (0 == len) return 0; 223 if(recordLength == 0 && bytesRead == 0 && !moreChunks){ 224 ++bytesRead; if(ME){ 226 finalClose(); 227 } 228 return 0; 229 } 230 if (bytesRead >= recordLength && !moreChunks) { 231 dataPadLength -= readPad(dataPadLength); 232 if(ME){ 233 finalClose(); 234 } 235 return -1; 236 } 237 238 int totalbytesread = 0; 239 int bytes2read = 0; 240 241 do { 242 if (bytesRead >= recordLength && moreChunks) 243 readHeader(true); 244 245 bytes2read = (int) Math.min(recordLength - bytesRead, 246 (long) len - totalbytesread); 247 bytes2read = (int) Math.min(recordLength - bytesRead, 248 (long) len - totalbytesread); 249 try { 250 bytes2read = is.read(b, off + totalbytesread, 251 bytes2read); 252 } catch (IOException e) { 253 streamInError = e; 254 throw e; 255 } 256 257 if (0 < bytes2read) { 258 totalbytesread += bytes2read; 259 bytesRead += bytes2read; 260 } 261 262 } 263 while (bytes2read > -1 && totalbytesread < len && 264 (bytesRead < recordLength || moreChunks)); 265 266 if (0 > bytes2read) { 267 if (moreChunks) { 268 streamInError = new IOException (Messages.getMessage( 269 "attach.DimeStreamError0")); 270 throw streamInError; 271 } 272 if (bytesRead < recordLength) { 273 streamInError = new IOException (Messages.getMessage 274 ("attach.DimeStreamError1", 275 "" + (recordLength - bytesRead))); 276 throw streamInError; 277 } 278 if (!ME) { 279 streamInError = new IOException (Messages.getMessage( 280 "attach.DimeStreamError0")); 281 throw streamInError; 282 } 283 dataPadLength = 0; 285 286 } else if (bytesRead >= recordLength) { 287 try { 289 dataPadLength -= readPad(dataPadLength); 290 } catch (IOException e) { 291 if (!ME) throw e; 293 else { 294 dataPadLength = 0; 295 streamInError = null; 296 } 297 } 298 } 299 300 if (bytesRead >= recordLength && ME) { 301 finalClose(); 302 } 303 304 return totalbytesread >= 0 ? totalbytesread : -1; 305 } 306 307 void readHeader(boolean isChunk) throws IOException { 308 309 bytesRead = 0; if (isChunk) { 311 if (!moreChunks) throw new RuntimeException ( 312 Messages.getMessage("attach.DimeStreamError2")); 313 dataPadLength -= readPad(dataPadLength); } 315 316 byte[] header = new byte[12]; 317 318 if (header.length != readFromStream(header)) { 319 streamInError = new IOException (Messages.getMessage( 320 "attach.DimeStreamError3", 321 "" + header.length)); 322 throw streamInError; 323 } 324 325 byte version = (byte) ((header[0] >>> 3) & 0x1f); 327 328 if (version > DimeMultiPart.CURRENT_VERSION) { 329 streamInError = new IOException (Messages.getMessage("attach.DimeStreamError4", 330 "" + version, 331 "" + DimeMultiPart.CURRENT_VERSION)); 332 throw streamInError; 333 } 334 335 MB = 0 != (0x4 & header[0]); 337 ME = 0 != (0x2 & header[0]); 338 moreChunks = 0 != (0x1 & header[0]); 339 340 if (!isChunk) 342 tnf = DimeTypeNameFormat.parseByte((byte) ((header[1] >>> 4) & (byte) 0xf)); 343 344 int optionsLength = 346 ((((int) header[2]) << 8) & 0xff00) | ((int) header[3]); 347 348 int idLength = 350 ((((int) header[4]) << 8) & 0xff00) | ((int) header[5]); 351 352 int typeLength = ((((int) header[6]) << 8) & 0xff00) 354 | ((int) header[7]); 355 356 recordLength = ((((long) header[8]) << 24) & 0xff000000L) | 358 ((((long) header[9]) << 16) & 0xff0000L) | 359 ((((long) header[10]) << 8) & 0xff00L) | 360 ((long) header[11] & 0xffL); 361 362 364 if (0 != optionsLength) { 365 byte[] optBytes = new byte[optionsLength]; 366 367 if (optionsLength != readFromStream(optBytes)) { 368 streamInError = new IOException (Messages.getMessage( 369 "attach.DimeStreamError5", 370 "" + optionsLength)); 371 throw streamInError; 372 } 373 optBytes = null; 375 int pad = DimeBodyPart.dimePadding(optionsLength); 376 377 if (pad != readFromStream(header, 0, pad)) { 378 streamInError = new IOException ( 379 Messages.getMessage("attach.DimeStreamError7")); 380 throw streamInError; 381 } 382 } 383 384 if (0 < idLength) { 386 byte[] idBytes = new byte[ idLength]; 387 388 if (idLength != readFromStream(idBytes)) { 389 streamInError = new IOException ( 390 Messages.getMessage("attach.DimeStreamError8")); 391 throw streamInError; 392 } 393 if (idLength != 0 && !isChunk) { 394 id = new String (idBytes); 395 } 396 int pad = DimeBodyPart.dimePadding(idLength); 397 398 if (pad != readFromStream(header, 0, pad)) { 399 streamInError = new IOException (Messages.getMessage( 400 "attach.DimeStreamError9")); 401 throw streamInError; 402 } 403 } 404 405 if (0 < typeLength) { 407 byte[] typeBytes = new byte[typeLength]; 408 409 if (typeLength != readFromStream(typeBytes)) { 410 streamInError = new IOException (Messages.getMessage( 411 "attach.DimeStreamError10")); 412 throw streamInError; 413 } 414 if (typeLength != 0 && !isChunk) { 415 type = new String (typeBytes); 416 } 417 int pad = DimeBodyPart.dimePadding(typeLength); 418 419 if (pad != readFromStream(header, 0, pad)) { 420 streamInError = new IOException (Messages.getMessage( 421 "attach.DimeStreamError11")); 422 423 throw streamInError; 424 } 425 } 426 log.debug("MB:" + MB + ", ME:" + ME + ", CF:" + moreChunks + 427 "Option length:" + optionsLength + 428 ", ID length:" + idLength + 429 ", typeLength:" + typeLength + ", TYPE_T:" + tnf); 430 log.debug("id:\"" + id + "\""); 431 log.debug("type:\"" + type + "\""); 432 log.debug("recordlength:\"" + recordLength + "\""); 433 434 dataPadLength = DimeBodyPart.dimePadding(recordLength); 435 } 436 437 444 public int read(byte[] b) throws IOException { 445 return read(b, 0, b.length); 446 } 447 448 455 public int read() throws IOException { 456 byte[] b = new byte[1]; 457 int read = read(b, 0, 1); 458 459 if (read < 0) 460 return -1; return (b[0] & 0xff); } 463 464 474 public void close() throws IOException { 475 synchronized(this){ 476 if (closed) return; 477 closed = true; } 479 log.debug(Messages.getMessage("bStreamClosed", "" + streamNo)); 480 if (bytesRead < recordLength || moreChunks) { 481 byte[] readrest = new byte[1024 * 16]; 484 int bread = 0; 485 486 do { 487 bread = _read(readrest, 0, readrest.length); } 489 while (bread > -1); 490 } 491 dataPadLength -= readPad(dataPadLength); 492 } 493 494 499 public void mark(int readlimit) { } 501 502 public void reset() throws IOException { 503 streamInError = new IOException (Messages.getMessage( 504 "attach.bounday.mns")); 505 throw streamInError; 506 } 507 508 public boolean markSupported() { 509 return false; 510 } 511 512 public synchronized int available() throws IOException { 513 if (null != streamInError) throw streamInError; 514 int chunkAvail = (int) Math.min((long) 515 Integer.MAX_VALUE, recordLength - bytesRead); 516 517 int streamAvail = 0; 518 519 try { 520 streamAvail = is.available(); 521 } catch (IOException e) { 522 streamInError = e; 523 throw e; 524 } 525 526 if (chunkAvail == 0 && moreChunks && (12 + dataPadLength) 527 <= streamAvail) { 528 dataPadLength -= readPad(dataPadLength); 529 readHeader(true); 530 return available(); 531 } 532 return Math.min(streamAvail, chunkAvail); 533 } 534 535 protected void finalClose() throws IOException { 536 try{ 537 theEnd = true; 538 if(null != is) is.close(); 539 }finally{ 540 is= null; 541 } 542 } 543 } 544 | Popular Tags |