1 21 22 27 28 package javax.mail.util; 29 30 import java.io.*; 31 import javax.mail.internet.SharedInputStream ; 32 33 46 public class SharedFileInputStream extends BufferedInputStream 47 implements SharedInputStream { 48 49 private static int defaultBufferSize = 2048; 50 51 55 protected RandomAccessFile in; 56 57 60 protected int bufsize; 61 62 66 protected long bufpos; 67 68 71 protected long start = 0; 72 73 76 protected long datalen; 77 78 82 private boolean master = true; 83 84 89 class SharedFile { 90 private int cnt; 91 private RandomAccessFile in; 92 93 SharedFile(String file) throws IOException { 94 this.in = new RandomAccessFile(file, "r"); 95 } 96 97 SharedFile(File file) throws IOException { 98 this.in = new RandomAccessFile(file, "r"); 99 } 100 101 public RandomAccessFile open() { 102 cnt++; 103 return in; 104 } 105 106 public synchronized void close() throws IOException { 107 if (cnt > 0 && --cnt <= 0) 108 in.close(); 109 } 110 111 public synchronized void forceClose() throws IOException { 112 if (cnt > 0) { 113 cnt = 0; 115 in.close(); 116 } else { 117 try { 119 in.close(); 120 } catch (IOException ioex) { } 121 } 122 } 123 124 protected void finalize() throws Throwable { 125 super.finalize(); 126 in.close(); 127 } 128 } 129 130 private SharedFile sf; 131 132 135 private void ensureOpen() throws IOException { 136 if (in == null) 137 throw new IOException("Stream closed"); 138 } 139 140 146 public SharedFileInputStream(File file) throws IOException { 147 this(file, defaultBufferSize); 148 } 149 150 156 public SharedFileInputStream(String file) throws IOException { 157 this(file, defaultBufferSize); 158 } 159 160 168 public SharedFileInputStream(File file, int size) throws IOException { 169 super(null); if (size <= 0) 171 throw new IllegalArgumentException ("Buffer size <= 0"); 172 init(new SharedFile(file), size); 173 } 174 175 183 public SharedFileInputStream(String file, int size) throws IOException { 184 super(null); if (size <= 0) 186 throw new IllegalArgumentException ("Buffer size <= 0"); 187 init(new SharedFile(file), size); 188 } 189 190 private void init(SharedFile sf, int size) throws IOException { 191 this.sf = sf; 192 this.in = sf.open(); 193 this.start = 0; 194 this.datalen = in.length(); this.bufsize = size; 196 buf = new byte[size]; 197 } 198 199 202 private SharedFileInputStream(SharedFile sf, long start, long len, 203 int bufsize) { 204 super(null); 205 this.master = false; 206 this.sf = sf; 207 this.in = sf.open(); 208 this.start = start; 209 this.bufpos = start; 210 this.datalen = len; 211 this.bufsize = bufsize; 212 buf = new byte[bufsize]; 213 } 214 215 222 private void fill() throws IOException { 223 if (markpos < 0) { 224 pos = 0; 225 bufpos += count; 226 } else if (pos >= buf.length) 227 if (markpos > 0) { 228 int sz = pos - markpos; 229 System.arraycopy(buf, markpos, buf, 0, sz); 230 pos = sz; 231 bufpos += markpos; 232 markpos = 0; 233 } else if (buf.length >= marklimit) { 234 markpos = -1; 235 pos = 0; 236 bufpos += count; 237 } else { 238 int nsz = pos * 2; 239 if (nsz > marklimit) 240 nsz = marklimit; 241 byte nbuf[] = new byte[nsz]; 242 System.arraycopy(buf, 0, nbuf, 0, pos); 243 buf = nbuf; 244 } 245 count = pos; 246 in.seek(bufpos + pos); 247 int len = buf.length - pos; 249 if (bufpos - start + pos + len > datalen) 250 len = (int)(datalen - (bufpos - start + pos)); 251 int n = in.read(buf, pos, len); 252 if (n > 0) 253 count = n + pos; 254 } 255 256 264 public synchronized int read() throws IOException { 265 ensureOpen(); 266 if (pos >= count) { 267 fill(); 268 if (pos >= count) 269 return -1; 270 } 271 return buf[pos++] & 0xff; 272 } 273 274 278 private int read1(byte[] b, int off, int len) throws IOException { 279 int avail = count - pos; 280 if (avail <= 0) { 281 if (false) { 282 286 if (len >= buf.length && markpos < 0) { 287 return in.read(b, off, len); 289 } 290 } 291 fill(); 292 avail = count - pos; 293 if (avail <= 0) return -1; 294 } 295 int cnt = (avail < len) ? avail : len; 296 System.arraycopy(buf, pos, b, off, cnt); 297 pos += cnt; 298 return cnt; 299 } 300 301 316 public synchronized int read(byte b[], int off, int len) 317 throws IOException 318 { 319 ensureOpen(); 320 if ((off | len | (off + len) | (b.length - (off + len))) < 0) { 321 throw new IndexOutOfBoundsException (); 322 } else if (len == 0) { 323 return 0; 324 } 325 326 int n = read1(b, off, len); 327 if (n <= 0) return n; 328 while ((n < len) ) { 329 int n1 = read1(b, off + n, len - n); 330 if (n1 <= 0) break; 331 n += n1; 332 } 333 return n; 334 } 335 336 344 public synchronized long skip(long n) throws IOException { 345 ensureOpen(); 346 if (n <= 0) { 347 return 0; 348 } 349 long avail = count - pos; 350 351 if (avail <= 0) { 352 357 358 fill(); 360 avail = count - pos; 361 if (avail <= 0) 362 return 0; 363 } 364 365 long skipped = (avail < n) ? avail : n; 366 pos += skipped; 367 return skipped; 368 } 369 370 378 public synchronized int available() throws IOException { 379 ensureOpen(); 380 return (count - pos) + in_available(); 381 } 382 383 private int in_available() throws IOException { 384 return (int)((start + datalen) - (bufpos + count)); 386 } 387 388 396 public synchronized void mark(int readlimit) { 397 marklimit = readlimit; 398 markpos = pos; 399 } 400 401 415 public synchronized void reset() throws IOException { 416 ensureOpen(); 417 if (markpos < 0) 418 throw new IOException("Resetting to invalid mark"); 419 pos = markpos; 420 } 421 422 433 public boolean markSupported() { 434 return true; 435 } 436 437 443 public void close() throws IOException { 444 if (in == null) 445 return; 446 try { 447 if (master) 448 sf.forceClose(); 449 else 450 sf.close(); 451 } finally { 452 sf = null; 453 in = null; 454 buf = null; 455 } 456 } 457 458 464 public long getPosition() { 465 if (in == null) 467 throw new RuntimeException ("Stream closed"); 468 return bufpos + pos - start; 469 } 470 471 483 public InputStream newStream(long start, long end) { 484 if (in == null) 485 throw new RuntimeException ("Stream closed"); 486 if (start < 0) 487 throw new IllegalArgumentException ("start < 0"); 488 if (end == -1) 489 end = datalen; 490 return new SharedFileInputStream(sf, 491 this.start + (int)start, (int)(end - start), bufsize); 492 } 493 494 511 512 515 protected void finalize() throws Throwable { 516 super.finalize(); 517 close(); 518 } 519 } 520 | Popular Tags |