1 package org.mortbay.util; 16 17 import java.io.File ; 18 import java.io.IOException ; 19 import java.io.RandomAccessFile ; 20 21 22 23 49 public class TempByteHolder { 50 51 byte[] _memory_buffer = null; 52 53 boolean _file_mode = false; 55 56 int _window_size = 0; 57 int _window_low = 0; 58 int _window_high = 0; 59 int _file_high = 0; 60 int _write_pos = 0; 61 int _read_pos = 0; 62 int _file_pos = -1; 63 int _mark_pos = 0; 64 65 66 67 TempByteHolder.OutputStream _output_stream = new TempByteHolder.OutputStream(); 68 69 TempByteHolder.InputStream _input_stream = null; 71 72 File _temp_directory = null; 73 74 File _tempfilef = null; 75 76 RandomAccessFile _tempfile = null; 77 78 79 81 87 public TempByteHolder(int in_memory_capacity) { 88 this(new byte[in_memory_capacity],0,0); 89 } 90 91 95 public TempByteHolder(byte[] byte_array) { 96 this(byte_array,0,0); 97 } 98 99 106 public TempByteHolder(byte[] byte_array, int offset, int prefilled_data_size) { 107 if (byte_array == null) throw new NullPointerException (); 108 _window_size = byte_array.length; 109 if ((offset < 0) || (offset > _window_size)) throw new IllegalArgumentException ("Bad prefilled data offset"); 110 if ((offset+prefilled_data_size > _window_size)||(prefilled_data_size < 0)) throw new IllegalArgumentException ("Bad prefilled data size"); 111 _memory_buffer = byte_array; 112 _write_pos = prefilled_data_size; 113 _window_low = -offset; 114 _window_high = _window_size-offset; 115 } 116 117 protected void finalize() { 118 try { 119 close(); 120 } catch (IOException e) { 121 } 122 } 123 124 128 public void clear() { 129 _file_mode = false; 130 _write_pos = 0; 131 _read_pos = 0; 132 _window_low = 0; 133 _window_high = _window_size; 134 _file_high = 0; 135 _mark_pos = 0; 136 } 137 138 142 public void close() throws IOException { 143 clear(); 144 if (_tempfile != null) { 145 _tempfile.close(); 146 _tempfile = null; 147 _tempfilef.delete(); 148 _tempfilef = null; 149 } 150 } 151 152 156 public void seek(int offset) throws IOException { 157 if ((offset <= _write_pos)&&(offset>=0)) { 158 _read_pos = offset; 159 } else throw new IOException ("bad seek offset"); 160 } 161 162 167 public void truncate(int offset) throws IOException { 168 if ((offset < 0)||(offset > _write_pos)) throw new IOException ("bad truncate offset"); 169 if (_read_pos > offset) _read_pos = offset; 170 if (_mark_pos > offset) _mark_pos = offset; 171 _write_pos = offset; 172 if (_file_high > offset) _file_high = offset; 173 moveWindow(_write_pos); 174 } 175 176 177 185 public void setTempDirectory(File dir) throws IOException { 186 File td = dir.getCanonicalFile(); 187 if (td.isDirectory()) { 188 _temp_directory = td; 189 } 190 } 191 192 193 194 199 public int getLength() { 200 return _write_pos; 201 } 202 203 212 public boolean isLarge() { 213 return _file_mode; 214 } 215 216 217 229 public byte[] getBytes() { 230 if (_file_mode) throw new IllegalStateException ("data too large"); 231 return _memory_buffer; 232 } 233 234 242 public String getString(String character_encoding) throws java.io.UnsupportedEncodingException { 243 if (_file_mode) throw new IllegalStateException ("data too large"); 244 return new String (_memory_buffer,0,_write_pos,character_encoding); 245 } 246 247 251 252 public java.io.OutputStream getOutputStream() { 253 return _output_stream; 254 } 255 256 257 261 public java.io.InputStream getInputStream() { 262 if (_input_stream == null) { 263 _input_stream = new TempByteHolder.InputStream(); 264 } 265 return _input_stream; 266 } 267 268 269 274 public void writeTo(java.io.OutputStream os) throws IOException { 275 writeTo(os, 0, getLength()); 276 } 277 278 279 286 public void writeTo(java.io.OutputStream os, int start_offset, int length) throws IOException { 287 int towrite = min(length, _write_pos-start_offset); 288 int writeoff = start_offset; 289 if (towrite > 0) { 290 while (towrite >= _window_size) { 291 moveWindow(writeoff); 292 os.write(_memory_buffer,0,_window_size); 293 towrite -= _window_size; 294 writeoff += _window_size; 295 } 296 if (towrite > 0) { 297 moveWindow(writeoff); 298 os.write(_memory_buffer,0,towrite); 299 } 300 } 301 } 302 303 304 309 public void readFrom(java.io.InputStream is) throws IOException { 310 int howmuch = 0; 311 do { 312 _write_pos += howmuch; 313 moveWindow(_write_pos); 314 howmuch = is.read(_memory_buffer); 315 } while (howmuch != -1); 316 } 317 318 319 321 324 private void createTempFile() throws IOException { 325 _tempfilef = File.createTempFile("org.mortbay.util.TempByteHolder-",".tmp",_temp_directory).getCanonicalFile(); 326 _tempfilef.deleteOnExit(); 327 _tempfile = new RandomAccessFile (_tempfilef,"rw"); 328 } 329 330 335 private void writeToTempFile(int at_offset, byte[] data, int offset, int len) throws IOException { 336 if (_tempfile == null) { 337 createTempFile(); 338 _file_pos = -1; 339 } 340 _file_mode = true; 341 if (at_offset != _file_pos) { 342 _tempfile.seek((long)at_offset); 343 } 344 _tempfile.write(data,offset,len); 345 _file_pos = at_offset + len; 346 _file_high = max(_file_high,_file_pos); 347 } 348 349 352 private void readFromTempFile(int at_offset, byte[] data, int offset, int len) throws IOException { 353 if (_file_pos != at_offset) { 354 _tempfile.seek((long)at_offset); 355 } 356 _tempfile.readFully(data,offset,len); 357 _file_pos = at_offset+len; 358 } 359 360 361 366 private void moveWindow(int start_offset) throws IOException { 367 if (start_offset != _window_low) { 369 int end_offset = start_offset + _window_size; 370 int dirty_low = _file_high; 372 int dirty_high = _write_pos; 373 int dirty_len = _write_pos - _file_high; 374 if (dirty_len > 0) { if ( (dirty_low < start_offset) || (dirty_high > end_offset) ) { 377 writeToTempFile(dirty_low, _memory_buffer, dirty_low - _window_low, dirty_len); 379 } 380 } 381 382 384 int stay_low = max(start_offset,_window_low); 385 int stay_high = min(_write_pos, _window_high, end_offset); 386 int stay_size = stay_high - stay_low; 388 if (stay_size > 0) { 389 System.arraycopy(_memory_buffer, stay_low-_window_low, _memory_buffer, stay_low-start_offset, stay_size); 390 } 391 392 if (stay_low > start_offset) { 394 int toread_low = start_offset; 396 int toread_high = min(stay_low,end_offset); 397 int toread_size = toread_high - toread_low; 398 if (toread_size > 0) { 399 readFromTempFile(toread_low, _memory_buffer, toread_low-start_offset, toread_size); 400 } 401 } 402 if (stay_high < end_offset) { 403 int toread_low = max(stay_high,start_offset); 405 int toread_high = min(end_offset,_file_high); 406 int toread_size = toread_high-toread_low; 407 if (toread_size > 0) { 408 readFromTempFile(toread_low, _memory_buffer, toread_low-start_offset, toread_size); 409 } 410 } 411 _window_low = start_offset; 412 _window_high = end_offset; 413 } 414 } 415 416 417 private static int min(int a, int b) { 418 return (a<b?a:b); 419 } 420 421 422 private static int max(int a, int b) { 423 return (a>b?a:b); 424 } 425 426 427 private static int min(int a, int b, int c) { 428 int r = a; 429 if (r > b) r = b; 430 if (r > c) r = c; 431 return r; 432 } 433 434 437 private static boolean contained(int range1_low, int range1_high, int range2_low, int range2_high) { 438 return ((range1_low >= range2_low)&&(range1_high <= range2_high)); 439 } 440 441 444 class OutputStream extends java.io.OutputStream { 445 446 451 public void write(byte[] data) throws IOException { 452 write(data,0,data.length); 453 } 454 455 462 public void write(byte[] data, int off, int len) throws IOException { 463 int new_write_pos = _write_pos + len; 464 boolean write_pos_in_window = (_write_pos >= _window_low)&&(_write_pos < _window_high); 465 466 if (!write_pos_in_window) { 467 moveWindow(_write_pos); } 470 471 boolean end_of_data_in_window = (new_write_pos <= _window_high); 472 473 if ( end_of_data_in_window ) { 474 System.arraycopy(data, off, _memory_buffer, _write_pos-_window_low, len); 477 _write_pos = new_write_pos; 478 } else { 479 int out_of_window = new_write_pos - _window_high; 480 if (out_of_window < _window_size) { 481 484 int part1_len = _window_high - _write_pos; 486 int part2_len = len - part1_len; 487 488 System.arraycopy(data, off, _memory_buffer, _write_pos-_window_low, part1_len); 489 _write_pos = _window_high; 490 491 moveWindow(_write_pos); 493 System.arraycopy(data, off+part1_len, _memory_buffer, 0, part2_len); 494 _write_pos = new_write_pos; 495 496 } else { 497 500 int part1_size = _window_high - _write_pos; 501 int part2_size = len - part1_size; 502 503 if (part1_size == _window_size) { 504 writeToTempFile(_write_pos, data, off, len); 507 _write_pos = new_write_pos; 508 moveWindow(_write_pos); 509 510 } else { 511 if (part1_size > 0) { 513 System.arraycopy(data, off, _memory_buffer, _write_pos-_window_low, part1_size); 514 _write_pos += part1_size; 515 moveWindow(_write_pos); } 517 writeToTempFile(_write_pos, data, off+part1_size, part2_size); 520 _write_pos = new_write_pos; 521 moveWindow(_write_pos); 522 } 523 } 524 } 525 } 526 527 532 public void write(int b) throws IOException { 533 if ((_write_pos >= _window_high) || (_write_pos < _window_low)) { 534 moveWindow(_write_pos); 535 } 536 _memory_buffer[_write_pos - _window_low] = (byte)(b &0xFF); 538 _write_pos++; 539 } 540 541 public void flush() throws IOException { 542 moveWindow(_write_pos); } 544 545 public void close() throws IOException { 546 } 548 } 549 550 551 552 553 554 557 class InputStream extends java.io.InputStream { 558 559 public int read() throws IOException { 560 int ret = -1; 561 if (!contained(_read_pos,_read_pos+1, _window_low, _window_high)) { 563 moveWindow(_read_pos); 564 } 565 if (_write_pos > _read_pos) { 566 ret = (_memory_buffer[_read_pos - _window_low])&0xFF; 567 _read_pos++; 568 } 569 return ret; 570 } 571 572 public int read(byte[] buff) throws IOException { 573 return read(buff,0, buff.length); 574 } 575 576 public int read(byte[] buff, int off, int len) throws IOException { 577 int read_size = min(len,_write_pos-_read_pos); 579 if (read_size > 0) { 580 if (read_size >= _window_size) { 581 moveWindow(_write_pos); 583 readFromTempFile(_read_pos, buff, off, read_size); 584 } else { 585 int read_low = _read_pos; 587 int read_high = read_low + read_size; 588 if (!contained(read_low,read_high, _window_low, _window_high)) { 590 moveWindow(_read_pos); 591 } 592 System.arraycopy(_memory_buffer, _read_pos - _window_low, buff, off, read_size); 593 } 594 _read_pos += read_size; 595 } 596 return read_size; 597 } 598 599 public long skip(long bytes) throws IOException { 600 if (bytes < 0 || bytes > Integer.MAX_VALUE) throw new IllegalArgumentException (); 601 int len = (int)bytes; 602 if ( (len+_read_pos) > _write_pos ) len = _write_pos - _read_pos; 603 _read_pos+=len; 604 moveWindow(_write_pos); return (long)len; 606 } 607 608 public int available() throws IOException { 609 return _write_pos - _read_pos; 610 } 611 612 613 public void mark(int readlimit) { 614 _mark_pos = _read_pos; 616 } 617 618 public void reset() throws IOException { 619 _read_pos = _mark_pos; 620 } 621 622 public boolean markSupported() { 623 return true; 624 } 625 626 627 } 628 } 629 | Popular Tags |