1 4 5 9 10 package org.openlaszlo.cache; 11 12 import java.net.*; 13 import java.io.*; 14 import java.util.Map ; 15 import java.util.Properties ; 16 import java.util.Iterator ; 17 18 import org.openlaszlo.xml.internal.XMLUtils; 19 import org.openlaszlo.utils.FileUtils; 20 import org.openlaszlo.utils.ChainedException; 21 import org.openlaszlo.utils.LZHttpUtils; 22 import org.openlaszlo.utils.MathUtils; 23 import org.openlaszlo.server.LPS; 24 25 import org.openlaszlo.data.Data; 26 import org.openlaszlo.data.DataSource; 27 import org.openlaszlo.data.DataSourceException; 28 29 import org.apache.commons.collections.SequencedHashMap; 30 31 import org.apache.log4j.*; 32 33 import EDU.oswego.cs.dl.util.concurrent.ReentrantLock; 34 import EDU.oswego.cs.dl.util.concurrent.Sync; 35 36 62 public abstract class Cache { 63 64 public final String DEFAULT_DISK_MAX = "500000000"; 65 public final String DEFAULT_MEM_MAX = "1000000"; 66 public final String DEFAULT_MEM_ITEM_MAX = "0"; 67 68 69 private static Logger mLogger = Logger.getLogger(Cache.class); 70 private static Logger mLockLogger = Logger.getLogger("trace.cache.lock"); 71 72 73 private final String mName; 74 75 76 private File mCacheDirectory; 77 78 81 private SequencedHashMap mDiskMap = null; 82 private SequencedHashMap mMemMap = null; 83 private SequencedHashMap mActiveMap = null; 84 85 86 private long mMaxDiskSize = 0; 87 88 89 private long mMaxMemSize = 0; 90 91 92 private long mMaxMemItemSize = 0; 93 94 95 private long mDiskSize = 0; 96 97 98 private long mMemSize = 0; 99 100 101 private long mCurName = 0; 102 private Object mNameLock = new Object (); 103 104 111 public Cache(String name, File cacheDirectory, Properties props) 112 throws IOException { 113 114 mCacheDirectory = cacheDirectory; 115 mName = name; 116 cacheDirectory.mkdirs(); 117 118 String maxSize; 119 String load; 120 String mapsize; 121 122 maxSize = props.getProperty(mName + ".disk.size", DEFAULT_DISK_MAX); 124 if (maxSize != null) { 125 mMaxDiskSize = Long.parseLong(maxSize); 126 } 127 maxSize = props.getProperty(mName + ".mem.size", DEFAULT_MEM_MAX); 128 if (maxSize != null) { 129 mMaxMemSize = Long.parseLong(maxSize); 130 } 131 maxSize = props.getProperty(mName + ".mem.item.max", DEFAULT_MEM_ITEM_MAX); 132 if (maxSize != null) { 133 mMaxMemItemSize = Long.parseLong(maxSize); 134 } 135 136 load = props.getProperty(mName + ".disk.load"); 137 if (load != null) { 138 int l = Integer.parseInt(load); 139 mapsize = props.getProperty(mName + ".disk.mapsize"); 140 if (mapsize != null) { 141 float m = Float.parseFloat(mapsize); 142 mDiskMap = new SequencedHashMap(l, m); 143 } else { 144 mDiskMap = new SequencedHashMap(l); 145 } 146 } else { 147 mDiskMap = new SequencedHashMap(); 148 } 149 load = props.getProperty(mName + ".mem.load"); 150 if (load != null) { 151 int l = Integer.parseInt(load); 152 mapsize = props.getProperty(mName + ".mem.mapsize"); 153 if (mapsize != null) { 154 float m = Float.parseFloat(mapsize); 155 mMemMap = new SequencedHashMap(l, m); 156 } else { 157 mMemMap = new SequencedHashMap(l); 158 } 159 } else { 160 mMemMap = new SequencedHashMap(); 161 } 162 load = props.getProperty(mName + ".active.load"); 163 if (load != null) { 164 int l = Integer.parseInt(load); 165 mapsize = props.getProperty(mName + ".active.mapsize"); 166 if (mapsize != null) { 167 float m = Float.parseFloat(mapsize); 168 mActiveMap = new SequencedHashMap(l, m); 169 } else { 170 mActiveMap = new SequencedHashMap(l); 171 } 172 } else { 173 mActiveMap = new SequencedHashMap(); 174 } 175 176 long t = System.currentTimeMillis(); 177 loadFromDirectory(); 178 mLogger.debug("loading " + mName + " took " + 179 MathUtils.formatDouble((System.currentTimeMillis() - t)/1000.0, 2) + " seconds"); 180 } 181 182 189 protected void afterCacheRead(Object metaData) {} 191 194 protected synchronized Item getItem(Serializable key) { 195 mLogger.debug("getItem"); 196 197 Item item = (Item)mMemMap.get(key); 198 if (item != null) { 199 return item; 200 } 201 return (Item)mDiskMap.get(key); 202 } 203 204 211 protected synchronized Item findItem(Serializable key, String enc, boolean doLockAndLeaveActive) 212 throws IOException { 213 214 mLogger.debug("findItem"); 215 216 SequencedHashMap curMap = mMemMap; 217 SequencedHashMap newMap = mMemMap; 218 219 boolean hasMemCache = (mMaxMemSize != 0); 220 221 if (!hasMemCache) { 222 newMap = mDiskMap; 223 } 224 225 Item item = (Item) curMap.get(key); 226 if (item == null) { 227 curMap = mDiskMap; 228 item = (Item) curMap.get(key); 229 if (item == null && doLockAndLeaveActive) { 230 curMap = mActiveMap; 231 item = (Item) curMap.get(key); 232 } 234 } 235 236 251 try { 252 if (item == null) { 253 item = new Item(key, enc, hasMemCache); 254 if (doLockAndLeaveActive) { 255 item.lock(); 256 item.setActive(true); 257 } 258 mLogger.debug("Made new item for " + key.toString()); 259 } else { 260 if (doLockAndLeaveActive) { 261 item.lock(); 262 item.setActive(true); 263 } 264 if (item.needsReckoning()) { 265 mLogger.debug("Reckoning an old item for " + key.toString()); 266 item.reckon(); 267 } 268 if (item.dirty()) { 269 mLogger.debug("Found a dirty item for " + key.toString()); 270 if (doLockAndLeaveActive) { 271 item.removeAndUnlock(); 272 } else { 273 item.remove(); 274 } 275 curMap.remove(key); 276 item = new Item(key, enc, hasMemCache); 277 if (doLockAndLeaveActive) { 278 item.lock(); 279 item.setActive(true); 280 } 281 mLogger.debug("Removed and made new item for " + key.toString()); 282 } else { 283 mLogger.debug("Found old item for " + key.toString()); 285 curMap.remove(key); 286 if (curMap == mDiskMap) { 287 if (newMap == mMemMap) { 288 long size = item.getSize(); 290 if (size <= mMaxMemItemSize || mMaxMemItemSize <= 0) { 291 item.readIntoMemory(); 292 mDiskSize -= size; 295 mMemSize += size; 296 } else { 297 newMap = mDiskMap; 298 } 299 } 300 } 301 } 302 } 303 304 if (!doLockAndLeaveActive) { 305 newMap.put(key, item); 306 } else { 307 mActiveMap.put(key, item); 308 } 309 310 } catch (IOException e) { 311 if (doLockAndLeaveActive && item != null) { 314 item.unlock(); 315 } 316 throw e; 317 } catch (RuntimeException re) { 318 if (doLockAndLeaveActive && item != null) { 321 item.unlock(); 322 } 323 throw re; 324 } 325 326 return item; 327 } 328 329 332 protected synchronized void updateCache(Item item) { 333 334 item.lock(); 335 item.reckon(); 336 item.unlock(); 337 338 updateMapsAndReckonItems(false ); 340 } 341 342 345 protected synchronized void updateCacheAndDeactivateItem(Item item) { 346 347 item.lock(); 348 item.reckon(); 349 350 if (item.active()) { 351 Object key = item.getKey(); 352 mActiveMap.remove(key); 353 if (item.isInMemory()) { 354 mMemMap.put(key, item); 355 } else { 356 mDiskMap.put(key, item); 357 } 358 item.setActive(false); 359 } 360 361 item.unlock(); 362 363 updateMapsAndReckonItems(true); 365 } 366 367 371 public synchronized void setMaxDiskSize(long size) { 372 if (size >= mMaxDiskSize || size == -1) { 373 mMaxDiskSize = size; 374 return; 375 } 376 mMaxDiskSize = size; 377 updateMapsAndReckonItems(true); 378 } 379 380 383 public synchronized long getMaxDiskSize() { 384 return mMaxDiskSize; 385 } 386 387 390 public synchronized long getDiskSize() { 391 return mDiskSize; 392 } 393 394 398 public synchronized void setMaxMemSize(long size) { 399 if (size >= mMaxMemSize || size == -1) { 400 mMaxMemSize = size; 401 return; 402 } 403 mMaxMemSize = size; 404 updateMapsAndReckonItems(true); 405 } 406 407 410 public synchronized long getMaxMemSize() { 411 return mMaxMemSize; 412 } 413 414 417 public synchronized long getMemSize() { 418 return mMemSize; 419 } 420 421 430 public synchronized void updateMapsAndReckonItems(boolean clearAll) { 431 432 long removedBytes = 0; 433 434 mLogger.debug(mName + " cache at " + mDiskSize + " bytes on-disk and " + 435 mMemSize + " bytes in-memory."); 436 437 if (mMaxMemSize == -1) { 439 return; 440 } 441 442 int done = 0; 443 if (!clearAll) { 444 done = 1; 445 } 446 447 while (mMemSize > mMaxMemSize && mMemMap.size() > done) { 449 Map.Entry first = mMemMap.getFirst(); 450 Object key = first.getKey(); 451 Item item = (Item)first.getValue(); 452 item.lock(); 453 454 if (item.needsReckoning()){ 455 item.reckon(); 456 } 457 458 if (!item.dirty()) { 459 if (item.mInfo.isInMemory()) { 464 removedBytes = item.removeFromMemory(); 465 mMemSize -= removedBytes; 466 mDiskSize += removedBytes; 467 } else { 468 mLogger.debug("mem item was already on disk"); 469 } 470 mLogger.debug("Pushing item " + key + " from mem to disk (" 471 + removedBytes + " bytes)" ); 472 mMemMap.remove(key); 473 mDiskMap.put(key, item); 474 } else { 475 if (item.mInfo.isInMemory()) { 476 mMemMap.remove(key); 477 mLogger.debug("Removing dirty item " + key + " from mem "); 478 } 479 } 480 item.unlock(); 481 } 482 483 if (mMaxDiskSize == -1) { 485 return; 486 } 487 488 while (mDiskSize > mMaxDiskSize && mDiskMap.size() > done) { 489 Map.Entry first = mDiskMap.getFirst(); 490 Object key = first.getKey(); 491 Item item = (Item)first.getValue(); 492 item.lock(); 493 494 if (item.needsReckoning()){ 495 item.reckon(); 496 } 497 498 if (!item.dirty()) { 499 removedBytes = item.getSize(); 500 item.removeAndUnlock(); 501 mLogger.debug("Removing item " + key + " from disk (" + removedBytes + " bytes)" ); 502 mDiskSize -= removedBytes; 503 mDiskMap.remove(key); 504 } else { 505 mDiskMap.remove(key); 506 mLogger.debug("Removing dirty item " + key + " from disk "); 507 } 508 } 509 510 mLogger.debug(mName + " now at disk: " + mDiskSize + " bytes."); 511 mLogger.debug(mName + " now at mem: " + mMemSize + " bytes."); 512 } 513 514 521 public synchronized void dumpXML(StringBuffer buf, String name, boolean details) { 522 523 buf.append("<" + name + " \n"); 524 buf.append("disk-total=\""); 525 buf.append(getMaxDiskSize()); 526 buf.append("\" "); 527 buf.append("disk-in-use=\""); 528 buf.append(getDiskSize()); 529 buf.append("\" "); 530 buf.append("mem-total=\""); 531 buf.append(getMaxMemSize()); 532 buf.append("\" "); 533 buf.append("mem-in-use=\""); 534 buf.append(getMemSize()); 535 buf.append("\" "); 536 buf.append(" >\n"); 537 if (details) { 538 buf.append("<active>\n"); 539 dumpMap(buf, mActiveMap, false); 540 buf.append("</active>\n"); 541 buf.append("<in-memory>\n"); 542 dumpMap(buf, mMemMap, true); 543 buf.append("</in-memory>\n"); 544 buf.append("<disk>\n"); 545 dumpMap(buf, mDiskMap, true); 546 buf.append("</disk>\n"); 547 } 548 buf.append("</" + name + ">\n"); 549 } 550 551 555 private synchronized void dumpMap(StringBuffer buf, SequencedHashMap map, 556 boolean lockItems) { 557 558 Iterator iter = map.iterator(); 559 while (iter.hasNext()) { 560 buf.append("<item "); 561 Object key = iter.next(); 562 Item item = (Item) map.get(key); 563 if (lockItems) { 564 item.lock(); 565 } 566 String keystring = key.toString(); 567 if (keystring.length() > 128) { 568 keystring = keystring.substring(0,127) + "..."; 569 } 570 buf.append("key=\"" + XMLUtils.escapeXml(keystring) + "\" "); 571 buf.append("in-memory=\"" + (new Boolean (item.isInMemory())).toString() + "\" " ); 572 buf.append("dirty=\"" + (new Boolean (item.dirty())).toString() + "\" " ); 573 buf.append("active=\"" + (new Boolean (item.active())).toString() + "\" " ); 574 buf.append("needs-reckon=\"" + (new Boolean (item.needsReckoning())).toString() + "\" " ); 575 buf.append("mem-to-reckon=\"" + item.memToReckon() + "\" " ); 576 buf.append("disk-to-reckon=\"" + item.diskToReckon() + "\" " ); 577 buf.append("size=\"" + item.getSize() + "\" "); 578 buf.append("key-size=\"" + item.getKeySize() + "\" "); 579 buf.append("path-name=\"" + item.getPathName() + "\" "); 580 buf.append("info-name=\"" + item.getInfoName() + "\" "); 581 long lm = item.getInfo().getLastModified(); 582 buf.append("last-modified=\"" + lm + "\" "); 583 buf.append("last-modified-gmt=\"" + LZHttpUtils.getDateString(lm) + "\" "); 584 buf.append("/>\n"); 585 if (lockItems) { 586 item.unlock(); 587 } 588 } 589 } 590 591 600 private synchronized void loadFromDirectory() throws IOException { 601 602 String [] fileNames = mCacheDirectory.list(); 603 604 for(int i = 0; i < fileNames.length; i++) { 605 if (!fileNames[i].endsWith(".dat")) 606 continue; 607 608 int x = fileNames[i].indexOf(".dat"); 609 String name = fileNames[i].substring(0, x); 610 long n; 611 try { 612 n = Long.parseLong(name); 613 if (n > mCurName) { 614 mCurName = n; 615 } 616 } catch (NumberFormatException ne) { 617 mLogger.warn("ignoring a strange .dat file in the cache named: " + fileNames[i]); 618 continue; 619 } 620 621 Item item = null; 622 File file = new File(mCacheDirectory + File.separator + fileNames[i]); 623 try { 624 item = new Item(file); 625 } catch (Throwable e) { 626 mLogger.error("can't load cache file: " + fileNames[i]); 627 mLogger.error("exception: ", e); 628 mLogger.error("deleting cache files for : " + fileNames[i]); 629 if (!FileUtils.deleteFilesStartingWith(mCacheDirectory, name)) { 631 mLogger.error("couldn't delete some files with name: " + fileNames[i]); 632 } 633 continue; 634 } 635 636 Object key = item.getKey(); 637 if (item.isInMemory()) { 638 mMemMap.put(key, item); 639 mMemSize += item.getSize(); 640 } else { 641 mDiskMap.put(key, item); 642 mDiskSize += item.getSize(); 643 } 644 645 String keystring = key.toString(); 646 if (keystring.length() > 128) { 647 keystring = keystring.substring(0,127) + "..."; 648 } 649 mLogger.debug("loaded cached item for " + keystring); 650 } 651 652 updateMapsAndReckonItems(true); 653 654 } 655 656 659 public synchronized boolean clearCache() { 660 mLogger.info("Clearing " + mName); 661 662 boolean ok1 = clearMap(mActiveMap); 663 boolean ok2 = clearMap(mDiskMap); 664 boolean ok3 = clearMap(mMemMap); 665 boolean ok4 = true; 666 667 mMemSize = 0; 668 mDiskSize = 0; 669 670 ok4 = FileUtils.deleteFiles(mCacheDirectory); 671 672 return ok1 && ok2 && ok3 && ok4; 673 } 674 675 679 private boolean clearMap(SequencedHashMap map) { 680 681 boolean ok = true; 682 while (map.size() > 0) { 683 Map.Entry first = map.getFirst(); 684 Object key = first.getKey(); 685 Item item = (Item)first.getValue(); 686 item.lock(); 687 if (!item.removeAndUnlock()) { 688 ok = false; 689 } 690 map.remove(key); 691 } 692 693 return ok; 694 } 695 696 707 private long nextUniqueName() { 708 709 long name; 710 711 synchronized (mNameLock) { 712 name = System.currentTimeMillis(); 713 if (name <= mCurName) { 714 name = mCurName + 1; 715 } 716 mCurName = name; 717 } 718 719 return name; 720 } 721 722 727 protected class Item implements Serializable { 728 729 transient private Sync mLock; 730 transient private boolean mDirty = false; 731 transient private boolean mNeedsReckoning = false; 732 733 transient private boolean mActive = false; 734 735 transient private byte mBuffer[]; 736 737 transient private long mMemSizeToReckon = 0; 738 transient private long mDiskSizeToReckon = 0; 739 740 741 744 CachedInfo mInfo = null; 745 746 750 public Item(Serializable key, String enc, boolean inMemory) { 751 752 mLock = new ReentrantLock(); 753 mInfo = new CachedInfo(key, enc, inMemory, nextUniqueName()); 754 mBuffer = null; 755 } 756 757 760 public boolean dirty() { 761 return mDirty; 762 } 763 764 767 public boolean active() { 768 return mActive; 769 } 770 771 772 public void setActive(boolean a) { 773 mActive = a; 774 } 775 776 779 public boolean needsReckoning () { 780 return mNeedsReckoning; 781 } 782 783 786 public long memToReckon() { 787 return mMemSizeToReckon; 788 } 789 790 793 public long diskToReckon() { 794 return mDiskSizeToReckon; 795 } 796 797 802 public void reckon() { 803 mMemSize += mMemSizeToReckon; 804 mDiskSize += mDiskSizeToReckon; 805 806 mDiskSizeToReckon = 0; 807 mMemSizeToReckon = 0; 808 809 mNeedsReckoning = false; 810 mLogger.debug("reckoned an item"); 811 } 812 813 814 817 public void readIntoMemory() throws IOException { 818 FileInputStream fis = null; 819 try { 820 String p = getPathName(); 821 fis = new FileInputStream(p); 822 mBuffer = new byte[(int)mInfo.getSize()]; 823 fis.read(mBuffer, 0, (int)mInfo.getSize()); 824 mInfo.setInMemory(true); 825 } catch (IOException e) { 826 markDirty(); 827 throw e; 828 } finally { 829 FileUtils.close(fis); 830 } 831 } 832 833 838 public long removeFromMemory() { 839 mBuffer = null; 840 mInfo.setInMemory(false); 841 return mInfo.getSize(); 842 } 843 844 847 public Item(File f) throws IOException, OptionalDataException, 848 StreamCorruptedException, ClassNotFoundException 849 { 850 mLock = new ReentrantLock(); 851 852 FileInputStream in = null; 853 try { 854 in = new FileInputStream(f); 855 ObjectInputStream istr = new ObjectInputStream(in); 856 mInfo = (CachedInfo)istr.readObject(); 857 afterCacheRead(mInfo.getMetaData()); 859 } finally { 860 FileUtils.close(in); 861 } 862 863 870 mInfo.setInMemory(false); 871 872 } 876 877 880 public void lock() { 881 882 mLockLogger.debug("acquiring lock: " + getKey()); 883 try { 884 mLock.acquire(); 885 } catch (InterruptedException e) { 886 throw new ChainedException(e); 887 } 888 mLockLogger.debug("acquired lock: " + getKey()); 889 } 890 891 894 public void unlock() { 895 mLockLogger.debug("releasing read lock: " + getKey()); 896 mLock.release(); 897 mLockLogger.debug("released read lock: " + getKey()); 898 } 899 900 903 public Serializable getKey() { 904 if (mInfo != null) 905 return mInfo.getKey(); 906 else 907 return "uninitialized item"; 908 } 909 910 913 public boolean isInMemory() { 914 if (mInfo != null) 915 return mInfo.isInMemory(); 916 else 917 return false; 918 } 919 920 924 public long getSize() { 925 return mInfo.getSize(); 926 } 927 928 933 public long getKeySize() { 934 return mInfo.getKeySize(); 935 } 936 937 940 public CachedInfo getInfo() { 941 return mInfo; 942 } 943 944 947 public String getPathName() { 948 return mCacheDirectory.getAbsolutePath() 950 + File.separator + mInfo.getName() + ".swf" + 951 (mInfo.getEncoding() == null ? "" : ".gz") ; 952 } 953 954 957 public String getInfoName() { 958 return mCacheDirectory.getAbsolutePath() 959 + File.separator + mInfo.getName() + ".dat"; 960 } 961 962 969 public long encode(String enc) throws IOException { 970 971 File f = new File(getPathName()); 972 File tempDir = f.getParentFile(); 973 File tempFile = File.createTempFile("lzuc-", null, tempDir); 974 mLogger.debug("Temporary file is " + tempFile.getAbsolutePath()); 975 FileUtils.encode(f, tempFile, enc); 976 long size = tempFile.length(); 977 if (!f.delete()) { 978 mLogger.warn("Can't delete " + f.getAbsolutePath()); 979 } 980 if (!tempFile.renameTo(f)) { 981 mLogger.error("Can't rename temporary file to " + 982 f.getAbsolutePath()); 983 } 984 return size; 985 } 986 987 990 public void markDirty() { 991 if (mDirty) { 992 return; 993 } 994 File f = new File(getPathName()); 997 if (f.exists() && !f.delete()) { 998 mLogger.warn("can't delete " + getPathName()); 999 } 1000 f = new File(getInfoName()); 1001 if (f.exists() && !f.delete()) { 1002 mLogger.warn("can't delete " + getInfoName()); 1003 } 1004 mDirty = true; 1005 mBuffer = null; 1006 mNeedsReckoning = true; 1007 mLogger.debug("Marking item dirty: " + mInfo.getKey()); 1008 if (mInfo.isInMemory()) { 1009 mMemSizeToReckon -= mInfo.getSize(); 1010 } else { 1011 mDiskSizeToReckon -= mInfo.getSize(); 1012 } 1013 mLogger.debug("disk to reckon : " + mDiskSizeToReckon + 1014 ", mem to reckon : " + mMemSizeToReckon); 1015 mInfo.setSize(0); 1016 } 1017 1018 1022 public boolean validForData(Data d) { 1023 1033 return true; 1034 } 1035 1036 1041 public boolean removeAndUnlock() { 1042 boolean ok = remove(); 1043 unlock(); 1044 return ok; 1045 } 1046 1047 1052 private boolean remove() { 1053 1054 boolean ok = true; 1055 mLogger.debug("removing item for " + mInfo.getKey() + " (" + 1056 getPathName() + " - " + getSize() + " bytes) ." ); 1057 File f = new File(getPathName()); 1058 if (f.exists() && !f.delete()) { 1059 mLogger.warn("can't delete " + getPathName()); 1060 ok = false; 1061 } 1062 f = new File(getInfoName()); 1063 if (f.exists() && !f.delete()) { 1064 mLogger.warn("can't delete " + getInfoName()); 1065 ok = false; 1066 } 1067 1068 return ok; 1069 } 1070 1071 1075 public InputStream getStream() { 1076 if (mInfo.isInMemory()) { 1077 return new ByteArrayInputStream(mBuffer); 1078 } else { 1079 try { 1080 return new FileInputStream(getPathName()); 1081 } catch (FileNotFoundException e) { 1082 throw new ChainedException(e.getMessage()); 1083 } 1084 } 1085 } 1086 1087 1092 public byte[] getRawByteArray() { 1093 try { 1094 if (!mInfo.isInMemory()) { 1095 readIntoMemory(); 1096 } 1097 if (mInfo.isInMemory()) { 1098 return mBuffer; 1099 } else { 1100 ByteArrayOutputStream bos = null; 1101 FileInputStream instream = null; 1102 try { 1103 bos = new ByteArrayOutputStream(); 1106 instream = new FileInputStream(getPathName()); 1107 FileUtils.send(instream, bos); 1108 return bos.toByteArray(); 1109 } catch (FileNotFoundException e) { 1110 throw new ChainedException(e.getMessage()); 1111 } finally { 1112 if (bos != null) { 1113 bos.close(); 1114 } 1115 if (instream != null) { 1116 instream.close(); 1117 } 1118 } 1119 1120 } 1121 } catch (IOException e) { 1122 throw new ChainedException(e.getMessage()); 1123 } 1124 } 1125 1126 1127 1128 1129 1132 public File getFile() { 1133 return new File(getPathName()); 1134 } 1135 1136 1139 public Serializable getMetaData() { 1140 return mInfo.getMetaData(); 1141 } 1142 1143 1151 public void update(InputStream in, Serializable metaData) 1152 throws IOException { 1153 1154 mLogger.debug("updating item stream and metadata"); 1155 1156 update(metaData); 1157 1158 if (in != null) { 1159 update(in); 1160 } 1161 1162 markClean(); 1163 } 1164 1165 1170 public void update(InputStream in) 1171 throws IOException { 1172 1173 FileOutputStream out = null; 1174 1175 try { 1176 1177 mLogger.debug("updating item from stream"); 1178 1179 out = new FileOutputStream(getPathName()); 1180 long size = FileUtils.send(in, out); 1181 FileUtils.close(out); 1182 1183 String enc = mInfo.getEncoding(); 1184 if (enc != null && !enc.equals("")) { 1185 size = encode(enc); 1186 } 1187 1188 long oldSize = mInfo.getSize(); 1189 mInfo.setSize(size); 1190 mNeedsReckoning = true; 1191 1192 if (mInfo.isInMemory()) { 1194 mMemSizeToReckon -= oldSize; 1195 } else { 1196 mDiskSizeToReckon -= oldSize; 1197 } 1198 1199 if (mInfo.isInMemory() && mMaxMemItemSize > 0 && 1201 size > mMaxMemItemSize) { 1202 mLogger.debug("this item too big for memory "); 1203 mInfo.setInMemory(false); 1204 } 1205 1206 if (mInfo.isInMemory()) { 1207 mLogger.debug("reading item into memory "); 1208 readIntoMemory(); 1209 mMemSizeToReckon += size; 1210 } else { 1211 mDiskSizeToReckon += size; 1212 } 1213 1214 } finally { 1215 FileUtils.close(out); 1216 } 1217 } 1218 1219 1222 public void markClean() { 1223 mDirty = false; 1224 } 1225 1226 1232 public void update(Serializable metaData) 1233 throws IOException { 1234 1235 mInfo.setMetaData(metaData); 1236 updateInfo(); 1237 } 1238 1239 1242 public void updateInfo() throws IOException { 1243 1244 FileOutputStream out = null; 1245 1246 try { 1247 1248 out = new FileOutputStream(getInfoName()); 1250 ObjectOutputStream ostr = new ObjectOutputStream(out); 1251 ostr.writeObject(mInfo); 1252 ostr.flush(); 1253 ostr.close(); 1254 1255 } finally { 1256 FileUtils.close(out); 1257 } 1258 } 1259 } 1260} 1261 | Popular Tags |