Source Code Cross Referenced for Cache.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » cache » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » Laszlo 4.0.10 » org.openlaszlo.cache 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /******************************************************************************
0002:         * Cache.java
0003:         * ****************************************************************************/package org.openlaszlo.cache;
0004:
0005:        import java.net.*;
0006:        import java.io.*;
0007:        import java.util.Map;
0008:        import java.util.Properties;
0009:        import java.util.Iterator;
0010:
0011:        import org.openlaszlo.xml.internal.XMLUtils;
0012:        import org.openlaszlo.utils.FileUtils;
0013:        import org.openlaszlo.utils.ChainedException;
0014:        import org.openlaszlo.utils.LZHttpUtils;
0015:        import org.openlaszlo.utils.MathUtils;
0016:        import org.openlaszlo.server.LPS;
0017:
0018:        import org.openlaszlo.data.Data;
0019:        import org.openlaszlo.data.DataSource;
0020:        import org.openlaszlo.data.DataSourceException;
0021:
0022:        import org.apache.commons.collections.SequencedHashMap;
0023:
0024:        import org.apache.log4j.*;
0025:
0026:        import EDU.oswego.cs.dl.util.concurrent.ReentrantLock;
0027:        import EDU.oswego.cs.dl.util.concurrent.Sync;
0028:
0029:        /**
0030:         * A base class for maintaining a disk-backed cache of requests.
0031:         *
0032:         * Cache has 2 sequenced hash map of Items.  Each item uniquely
0033:         * represents something to be cached (and transcoded).  The
0034:         * first map contains items that are "in memory".  Items that
0035:         * are "in memory" are also stored on disk.  The second map
0036:         * contains items that are only on disk.
0037:         *
0038:         * The cache chucks out (via LRU) items from each map when it is beyond 
0039:         * its maximum size for that map.  Each time an item is requested,
0040:         * it is moved to the front of the "in-memory" map.
0041:         *
0042:         * Each item has its own lock.  When an item is requested, 
0043:         * we lock it and then go to the DataSource to see if 
0044:         * we need to refresh any copy of it we have.
0045:         * When an item has it's size change or it marked dirty, it
0046:         * is also marked as needing its size changed reckoned with the
0047:         * cache sizes.  Whenever the cache is locked and runs into
0048:         * an item that needs reckoning, it updates the cache sizes
0049:         * to reflect the item.
0050:         *
0051:         * The cache supports multiple encodings of individual items.
0052:         *
0053:         * @author <a href="mailto:bloch@laszlosystems.com">Eric Bloch</a>
0054:         */
0055:        public abstract class Cache {
0056:
0057:            public final String DEFAULT_DISK_MAX = "500000000";
0058:            public final String DEFAULT_MEM_MAX = "1000000";
0059:            public final String DEFAULT_MEM_ITEM_MAX = "0";
0060:
0061:            /** Logger. */
0062:            private static Logger mLogger = Logger.getLogger(Cache.class);
0063:            private static Logger mLockLogger = Logger
0064:                    .getLogger("trace.cache.lock");
0065:
0066:            /** Name */
0067:            private final String mName;
0068:
0069:            /** See the constructor. */
0070:            private File mCacheDirectory;
0071:
0072:            /** Sequenced Maps of Cached Items keyed by request.  
0073:             * All access to these maps must must be synchronized
0074:             */
0075:            private SequencedHashMap mDiskMap = null;
0076:            private SequencedHashMap mMemMap = null;
0077:            private SequencedHashMap mActiveMap = null;
0078:
0079:            /** Maxmimum size for the on-disk cache in bytes */
0080:            private long mMaxDiskSize = 0;
0081:
0082:            /** Maxmimum size for the in-memory cache in bytes */
0083:            private long mMaxMemSize = 0;
0084:
0085:            /** Maxmimum size for the in-memory cache item in bytes */
0086:            private long mMaxMemItemSize = 0;
0087:
0088:            /** Current size of the in-disk cache in bytes */
0089:            private long mDiskSize = 0;
0090:
0091:            /** Current size of the in-memory cache in bytes */
0092:            private long mMemSize = 0;
0093:
0094:            /** Current cache id */
0095:            private long mCurName = 0;
0096:            private Object mNameLock = new Object();
0097:
0098:            /**
0099:             * Creates a new <code>Cache</code> instance.
0100:             *
0101:             * @param name
0102:             * @param cacheDirectory a <code>File</code> naming a directory
0103:             * where cache files should be kept
0104:             * @param props
0105:             */
0106:            public Cache(String name, File cacheDirectory, Properties props)
0107:                    throws IOException {
0108:
0109:                mCacheDirectory = cacheDirectory;
0110:                mName = name;
0111:                cacheDirectory.mkdirs();
0112:
0113:                String maxSize;
0114:                String load;
0115:                String mapsize;
0116:
0117:                // TODO: 2004-09-07 bloch catch NumberParseException's here
0118:                maxSize = props.getProperty(mName + ".disk.size",
0119:                        DEFAULT_DISK_MAX);
0120:                if (maxSize != null) {
0121:                    mMaxDiskSize = Long.parseLong(maxSize);
0122:                }
0123:                maxSize = props.getProperty(mName + ".mem.size",
0124:                        DEFAULT_MEM_MAX);
0125:                if (maxSize != null) {
0126:                    mMaxMemSize = Long.parseLong(maxSize);
0127:                }
0128:                maxSize = props.getProperty(mName + ".mem.item.max",
0129:                        DEFAULT_MEM_ITEM_MAX);
0130:                if (maxSize != null) {
0131:                    mMaxMemItemSize = Long.parseLong(maxSize);
0132:                }
0133:
0134:                load = props.getProperty(mName + ".disk.load");
0135:                if (load != null) {
0136:                    int l = Integer.parseInt(load);
0137:                    mapsize = props.getProperty(mName + ".disk.mapsize");
0138:                    if (mapsize != null) {
0139:                        float m = Float.parseFloat(mapsize);
0140:                        mDiskMap = new SequencedHashMap(l, m);
0141:                    } else {
0142:                        mDiskMap = new SequencedHashMap(l);
0143:                    }
0144:                } else {
0145:                    mDiskMap = new SequencedHashMap();
0146:                }
0147:                load = props.getProperty(mName + ".mem.load");
0148:                if (load != null) {
0149:                    int l = Integer.parseInt(load);
0150:                    mapsize = props.getProperty(mName + ".mem.mapsize");
0151:                    if (mapsize != null) {
0152:                        float m = Float.parseFloat(mapsize);
0153:                        mMemMap = new SequencedHashMap(l, m);
0154:                    } else {
0155:                        mMemMap = new SequencedHashMap(l);
0156:                    }
0157:                } else {
0158:                    mMemMap = new SequencedHashMap();
0159:                }
0160:                load = props.getProperty(mName + ".active.load");
0161:                if (load != null) {
0162:                    int l = Integer.parseInt(load);
0163:                    mapsize = props.getProperty(mName + ".active.mapsize");
0164:                    if (mapsize != null) {
0165:                        float m = Float.parseFloat(mapsize);
0166:                        mActiveMap = new SequencedHashMap(l, m);
0167:                    } else {
0168:                        mActiveMap = new SequencedHashMap(l);
0169:                    }
0170:                } else {
0171:                    mActiveMap = new SequencedHashMap();
0172:                }
0173:
0174:                long t = System.currentTimeMillis();
0175:                loadFromDirectory();
0176:                //        mLogger.debug(
0177:                /* (non-Javadoc)
0178:                 * @i18n.test
0179:                 * @org-mes="loading " + p[0] + " took " + p[1] + " seconds"
0180:                 */
0181:                //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0182:                //                                Cache.class.getName(),"051018-183", new Object[] {mName, MathUtils.formatDouble((System.currentTimeMillis() - t) / 1000.0, 2)})
0183:                //        );
0184:            }
0185:
0186:            /**
0187:             * this routine is a place holder which can be overridden to hook into
0188:             * the cache loading.  It is used by the cm/CompilationManager to get
0189:             * at the contents of the dependencyTracker as it is being loaded from
0190:             * disk and modify various paths that might have changed since
0191:             * prefetching.
0192:             */
0193:            protected void afterCacheRead(Object metaData) {
0194:            } // override me
0195:
0196:            /**
0197:             * @return an item if it exists or null otherwise
0198:             */
0199:            protected synchronized Item getItem(Serializable key) {
0200:                //        mLogger.debug("getItem");
0201:
0202:                Item item = (Item) mMemMap.get(key);
0203:                if (item != null) {
0204:                    return item;
0205:                }
0206:                return (Item) mDiskMap.get(key);
0207:            }
0208:
0209:            /**
0210:             * Find and optionally lock item in the cache that matches this key 
0211:             * If the item doesn't exist, create it.  If the item 
0212:             * does exist, move it to the top of the LRU list by removing
0213:             * and re-adding.   
0214:             * @return the locked item
0215:             */
0216:            protected synchronized Item findItem(Serializable key, String enc,
0217:                    boolean doLockAndLeaveActive) throws IOException {
0218:
0219:                //mLogger.debug("findItem");
0220:
0221:                SequencedHashMap curMap = mMemMap;
0222:                SequencedHashMap newMap = mMemMap;
0223:
0224:                boolean hasMemCache = (mMaxMemSize != 0);
0225:
0226:                if (!hasMemCache) {
0227:                    newMap = mDiskMap;
0228:                }
0229:
0230:                Item item = (Item) curMap.get(key);
0231:                if (item == null) {
0232:                    curMap = mDiskMap;
0233:                    item = (Item) curMap.get(key);
0234:                    if (item == null && doLockAndLeaveActive) {
0235:                        curMap = mActiveMap;
0236:                        item = (Item) curMap.get(key);
0237:                        // TODO: [2003-08-27 bloch] add assert in java 1.4 item.active()
0238:                    }
0239:                }
0240:
0241:                // New items default to the mem cache if it exists.
0242:                // Note that some items that are too big may
0243:                // be cached on disk (and not in mem) but may 
0244:                // temporarily be in the "mem cache" map.
0245:                // This is confusing, but simple and safe to implement
0246:                // w/out complicated locking.  This is because
0247:                // we don't want to lock the maps while we're
0248:                // fetching the items and we won't know the size
0249:                // until we fetch the item.
0250:                //
0251:                // TODO: [2003-09-04 bloch] 
0252:                // Note: this now only happens when doLockAndLeaveActive is
0253:                // false.  At some point we could rearchitect to remove
0254:                // this wart
0255:
0256:                try {
0257:                    if (item == null) {
0258:                        item = new Item(key, enc, hasMemCache);
0259:                        if (doLockAndLeaveActive) {
0260:                            item.lock();
0261:                            item.setActive(true);
0262:                        }
0263:
0264:                        //                mLogger.debug(
0265:                        /* (non-Javadoc)
0266:                         * @i18n.test
0267:                         * @org-mes="Made new item for " + p[0]
0268:                         */
0269:                        //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0270:                        //                                Cache.class.getName(),"051018-270", new Object[] {key.toString()})
0271:                        //);
0272:                    } else {
0273:                        if (doLockAndLeaveActive) {
0274:                            item.lock();
0275:                            item.setActive(true);
0276:                        }
0277:                        if (item.needsReckoning()) {
0278:                            //                    mLogger.debug(
0279:                            /* (non-Javadoc)
0280:                             * @i18n.test
0281:                             * @org-mes="Reckoning an old item for " + p[0]
0282:                             */
0283:                            //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0284:                            //                                Cache.class.getName(),"051018-285", new Object[] {key.toString()})
0285:                            //);
0286:                            item.reckon();
0287:                        }
0288:                        if (item.dirty()) {
0289:                            //                    mLogger.debug(
0290:                            /* (non-Javadoc)
0291:                             * @i18n.test
0292:                             * @org-mes="Found a dirty item for " + p[0]
0293:                             */
0294:                            //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0295:                            //                                Cache.class.getName(),"051018-296", new Object[] {key.toString()})
0296:                            //);
0297:                            if (doLockAndLeaveActive) {
0298:                                item.removeAndUnlock();
0299:                            } else {
0300:                                item.remove();
0301:                            }
0302:                            curMap.remove(key);
0303:                            item = new Item(key, enc, hasMemCache);
0304:                            if (doLockAndLeaveActive) {
0305:                                item.lock();
0306:                                item.setActive(true);
0307:                            }
0308:                            //                    mLogger.debug(
0309:                            /* (non-Javadoc)
0310:                             * @i18n.test
0311:                             * @org-mes="Removed and made new item for " + p[0]
0312:                             */
0313:                            //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0314:                            //                                Cache.class.getName(),"051018-315", new Object[] {key.toString()})
0315:                            //);
0316:                        } else {
0317:                            // Remove the item and re-add it below
0318:                            //                    mLogger.debug(
0319:                            /* (non-Javadoc)
0320:                             * @i18n.test
0321:                             * @org-mes="Found old item for " + p[0]
0322:                             */
0323:
0324:                            //                          org.openlaszlo.i18n.LaszloMessages.getMessage(
0325:                            //                                Cache.class.getName(),"051018-325", new Object[] {key.toString()})
0326:                            //);
0327:                            curMap.remove(key);
0328:                            if (curMap == mDiskMap) {
0329:                                if (newMap == mMemMap) {
0330:                                    // Update sizes when we're moving from disk to mem
0331:                                    long size = item.getSize();
0332:                                    if (size <= mMaxMemItemSize
0333:                                            || mMaxMemItemSize <= 0) {
0334:                                        item.readIntoMemory();
0335:                                        // Update sizes after we read into memory in case
0336:                                        // the above read fails for some bizarro reason.
0337:                                        mDiskSize -= size;
0338:                                        mMemSize += size;
0339:                                    } else {
0340:                                        newMap = mDiskMap;
0341:                                    }
0342:                                }
0343:                            }
0344:                        }
0345:                    }
0346:
0347:                    if (!doLockAndLeaveActive) {
0348:                        newMap.put(key, item);
0349:                    } else {
0350:                        mActiveMap.put(key, item);
0351:                    }
0352:
0353:                } catch (IOException e) {
0354:                    // If we get any kind of exception, we better unlock the item
0355:                    // since no one will be able to unlock it.
0356:                    if (doLockAndLeaveActive && item != null) {
0357:                        item.unlock();
0358:                    }
0359:                    throw e;
0360:                } catch (RuntimeException re) {
0361:                    // If we get any kind of exception, we better unlock the item
0362:                    // since no one will be able to unlock it.
0363:                    if (doLockAndLeaveActive && item != null) {
0364:                        item.unlock();
0365:                    }
0366:                    throw re;
0367:                }
0368:
0369:                return item;
0370:            }
0371:
0372:            /**
0373:             * Reckon this item and update the cache.
0374:             */
0375:            protected synchronized void updateCache(Item item) {
0376:
0377:                item.lock();
0378:                item.reckon();
0379:                item.unlock();
0380:
0381:                // While we have the cache locked, update the maps
0382:                updateMapsAndReckonItems(false /* leave at least one item in each map */);
0383:            }
0384:
0385:            /**
0386:             * Reckon and deactivate this item and update the cache.
0387:             */
0388:            protected synchronized void updateCacheAndDeactivateItem(Item item) {
0389:
0390:                item.lock();
0391:                item.reckon();
0392:
0393:                if (item.active()) {
0394:                    Object key = item.getKey();
0395:                    mActiveMap.remove(key);
0396:                    if (item.isInMemory()) {
0397:                        mMemMap.put(key, item);
0398:                    } else {
0399:                        mDiskMap.put(key, item);
0400:                    }
0401:                    item.setActive(false);
0402:                }
0403:
0404:                item.unlock();
0405:
0406:                // While we have the cache locked, update the maps
0407:                updateMapsAndReckonItems(true);
0408:            }
0409:
0410:            /**
0411:             * Set the maximum size of the on-disk cache.
0412:             * Can cause the cache to remove things.
0413:             */
0414:            public synchronized void setMaxDiskSize(long size) {
0415:                if (size >= mMaxDiskSize || size == -1) {
0416:                    mMaxDiskSize = size;
0417:                    return;
0418:                }
0419:                mMaxDiskSize = size;
0420:                updateMapsAndReckonItems(true);
0421:            }
0422:
0423:            /**
0424:             * Get the maximum size of the on-disk cache cache
0425:             */
0426:            public synchronized long getMaxDiskSize() {
0427:                return mMaxDiskSize;
0428:            }
0429:
0430:            /**
0431:             * Get the current size of the on-disk cache
0432:             */
0433:            public synchronized long getDiskSize() {
0434:                return mDiskSize;
0435:            }
0436:
0437:            /**
0438:             * Set the maxmimum size of the in-memory cache.
0439:             * Can cause the cache to remove things.
0440:             */
0441:            public synchronized void setMaxMemSize(long size) {
0442:                if (size >= mMaxMemSize || size == -1) {
0443:                    mMaxMemSize = size;
0444:                    return;
0445:                }
0446:                mMaxMemSize = size;
0447:                updateMapsAndReckonItems(true);
0448:            }
0449:
0450:            /**
0451:             * Get the maxmimum size of the in-memory cache
0452:             */
0453:            public synchronized long getMaxMemSize() {
0454:                return mMaxMemSize;
0455:            }
0456:
0457:            /**
0458:             * Get the current size of the in-memory cache
0459:             */
0460:            public synchronized long getMemSize() {
0461:                return mMemSize;
0462:            }
0463:
0464:            /**
0465:             * Update the maps and remove items that
0466:             * push us beyond the maximum size of the
0467:             * cache.  Never empty out the maps.
0468:             * Always leave at least one item if clearAll is false.
0469:             *
0470:             * Also ignore items that are in progress.
0471:             * @param clearAll if false, must leave one elt in each map
0472:             */
0473:            public synchronized void updateMapsAndReckonItems(boolean clearAll) {
0474:
0475:                long removedBytes = 0;
0476:
0477:                //mLogger.debug(
0478:                /* (non-Javadoc)
0479:                 * @i18n.test
0480:                 * @org-mes=p[0] + " cache at " + p[1] + " bytes on-disk and " + p[2] + " bytes in-memory."
0481:                 */
0482:                //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0483:                //                                Cache.class.getName(),"051018-482", new Object[] {mName, new Long(mDiskSize), new Long(mMemSize)})
0484:                //        );
0485:                // Infinite mem size... (nothing will get reckoned, hope that's ok)
0486:                if (mMaxMemSize == -1) {
0487:                    return;
0488:                }
0489:
0490:                int done = 0;
0491:                if (!clearAll) {
0492:                    done = 1;
0493:                }
0494:
0495:                // If we have a mem cache, push items from memory to disk
0496:                while (mMemSize > mMaxMemSize && mMemMap.size() > done) {
0497:                    Map.Entry first = mMemMap.getFirst();
0498:                    Object key = first.getKey();
0499:                    Item item = (Item) first.getValue();
0500:                    item.lock();
0501:
0502:                    if (item.needsReckoning()) {
0503:                        item.reckon();
0504:                    }
0505:
0506:                    if (!item.dirty()) {
0507:                        // Some items that were too large for memory
0508:                        // might be in this map, but are actually
0509:                        // accounted for in the disksize already.
0510:                        // We can skip these.
0511:                        if (item.mInfo.isInMemory()) {
0512:                            removedBytes = item.removeFromMemory();
0513:                            mMemSize -= removedBytes;
0514:                            mDiskSize += removedBytes;
0515:                        } else {
0516:                            //                    mLogger.debug(
0517:                            /* (non-Javadoc)
0518:                             * @i18n.test
0519:                             * @org-mes="mem item was already on disk"
0520:                             */
0521:                            //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0522:                            //                                Cache.class.getName(),"051018-521")
0523:                            //                    );
0524:                        }
0525:                        //                mLogger.debug(
0526:                        /* (non-Javadoc)
0527:                         * @i18n.test
0528:                         * @org-mes="Pushing item " + p[0] + " from mem to disk (" + p[1] + " bytes)"
0529:                         */
0530:                        //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0531:                        //                                Cache.class.getName(),"051018-530", new Object[] {key, new Long(removedBytes)})
0532:                        //                );
0533:                        mMemMap.remove(key);
0534:                        mDiskMap.put(key, item);
0535:                    } else {
0536:                        if (item.mInfo.isInMemory()) {
0537:                            mMemMap.remove(key);
0538:                            //                    mLogger.debug(
0539:                            /* (non-Javadoc)
0540:                             * @i18n.test
0541:                             * @org-mes="Removing dirty item " + p[0] + " from mem "
0542:                             */
0543:                            //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0544:                            //                                Cache.class.getName(),"051018-543", new Object[] {key})
0545:                            //);
0546:                        }
0547:                    }
0548:                    item.unlock();
0549:                }
0550:
0551:                // Infinite disk size... (no disk items will get reckoned, hope that's ok)
0552:                if (mMaxDiskSize == -1) {
0553:                    return;
0554:                }
0555:
0556:                while (mDiskSize > mMaxDiskSize && mDiskMap.size() > done) {
0557:                    Map.Entry first = mDiskMap.getFirst();
0558:                    Object key = first.getKey();
0559:                    Item item = (Item) first.getValue();
0560:                    item.lock();
0561:
0562:                    if (item.needsReckoning()) {
0563:                        item.reckon();
0564:                    }
0565:
0566:                    if (!item.dirty()) {
0567:                        removedBytes = item.getSize();
0568:                        item.removeAndUnlock();
0569:                        //                mLogger.debug(
0570:                        /* (non-Javadoc)
0571:                         * @i18n.test
0572:                         * @org-mes="Removing item " + p[0] + " from disk (" + p[1] + " bytes)"
0573:                         */
0574:                        //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0575:                        //                                Cache.class.getName(),"051018-574", new Object[] {key, new Long(removedBytes)})
0576:                        // );
0577:                        mDiskSize -= removedBytes;
0578:                        mDiskMap.remove(key);
0579:                    } else {
0580:                        mDiskMap.remove(key);
0581:                        //                mLogger.debug(
0582:                        /* (non-Javadoc)
0583:                         * @i18n.test
0584:                         * @org-mes="Removing dirty item " + p[0] + " from disk "
0585:                         */
0586:                        //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0587:                        //                                Cache.class.getName(),"051018-586", new Object[] {key})
0588:                        //);
0589:                    }
0590:                }
0591:                //        mLogger.debug(
0592:                /* (non-Javadoc)
0593:                 * @i18n.test
0594:                 * @org-mes=p[0] + " now at disk: " + p[1] + " bytes."
0595:                 */
0596:                //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0597:                //                                Cache.class.getName(),"051018-596", new Object[] {mName, new Long(mDiskSize)})
0598:                //);
0599:                //        mLogger.debug(
0600:                /* (non-Javadoc)
0601:                 * @i18n.test
0602:                 * @org-mes=p[0] + " now at mem: " + p[1] + " bytes."
0603:                 */
0604:                //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0605:                //                                Cache.class.getName(),"051018-604", new Object[] {mName, new Long(mMemSize)})
0606:                //);
0607:            }
0608:
0609:            /**
0610:             * Dump textual XML representation of cache to buf
0611:             *
0612:             * @param buf buffer to append
0613:             * @param name name for XML element
0614:             * @param details if true, dump details
0615:             */
0616:            public synchronized void dumpXML(StringBuffer buf, String name,
0617:                    boolean details) {
0618:
0619:                buf.append("<" + name + " \n");
0620:                buf.append("disk-total=\"");
0621:                buf.append(getMaxDiskSize());
0622:                buf.append("\" ");
0623:                buf.append("disk-in-use=\"");
0624:                buf.append(getDiskSize());
0625:                buf.append("\" ");
0626:                buf.append("mem-total=\"");
0627:                buf.append(getMaxMemSize());
0628:                buf.append("\" ");
0629:                buf.append("mem-in-use=\"");
0630:                buf.append(getMemSize());
0631:
0632:                buf.append("\" ");
0633:                buf.append("diskmap-entries=\"");
0634:                buf.append(mDiskMap.size());
0635:
0636:                buf.append("\" ");
0637:                buf.append("memmap-entries=\"");
0638:                buf.append(mMemMap.size());
0639:
0640:                buf.append("\" ");
0641:                buf.append("activemap-entries=\"");
0642:                buf.append(mActiveMap.size());
0643:
0644:                buf.append("\" ");
0645:                buf.append("    >\n");
0646:                if (details) {
0647:                    buf.append("<active>\n");
0648:                    dumpMap(buf, mActiveMap, false);
0649:                    buf.append("</active>\n");
0650:                    buf.append("<in-memory>\n");
0651:                    dumpMap(buf, mMemMap, true);
0652:                    buf.append("</in-memory>\n");
0653:                    buf.append("<disk>\n");
0654:                    dumpMap(buf, mDiskMap, true);
0655:                    buf.append("</disk>\n");
0656:                }
0657:                buf.append("</" + name + ">\n");
0658:            }
0659:
0660:            /**
0661:             * @param buf buffer to append
0662:             * @param map map to dump
0663:             */
0664:            private synchronized void dumpMap(StringBuffer buf,
0665:                    SequencedHashMap map, boolean lockItems) {
0666:
0667:                Iterator iter = map.iterator();
0668:                while (iter.hasNext()) {
0669:                    buf.append("<item ");
0670:                    Object key = iter.next();
0671:                    Item item = (Item) map.get(key);
0672:                    if (lockItems) {
0673:                        item.lock();
0674:                    }
0675:                    String keystring = key.toString();
0676:                    if (keystring.length() > 128) {
0677:                        keystring = keystring.substring(0, 127) + "...";
0678:                    }
0679:                    buf
0680:                            .append("key=\"" + XMLUtils.escapeXml(keystring)
0681:                                    + "\" ");
0682:                    buf.append("in-memory=\""
0683:                            + (new Boolean(item.isInMemory())).toString()
0684:                            + "\" ");
0685:                    buf.append("dirty=\""
0686:                            + (new Boolean(item.dirty())).toString() + "\" ");
0687:                    buf.append("active=\""
0688:                            + (new Boolean(item.active())).toString() + "\" ");
0689:                    buf.append("needs-reckon=\""
0690:                            + (new Boolean(item.needsReckoning())).toString()
0691:                            + "\" ");
0692:                    buf.append("mem-to-reckon=\"" + item.memToReckon() + "\" ");
0693:                    buf.append("disk-to-reckon=\"" + item.diskToReckon()
0694:                            + "\" ");
0695:                    buf.append("size=\"" + item.getSize() + "\" ");
0696:                    buf.append("key-size=\"" + item.getKeySize() + "\" ");
0697:                    buf.append("path-name=\"" + item.getPathName() + "\" ");
0698:                    buf.append("info-name=\"" + item.getInfoName() + "\" ");
0699:                    long lm = item.getInfo().getLastModified();
0700:                    buf.append("last-modified=\"" + lm + "\" ");
0701:                    buf.append("last-modified-gmt=\""
0702:                            + LZHttpUtils.getDateString(lm) + "\" ");
0703:                    buf.append("/>\n");
0704:                    if (lockItems) {
0705:                        item.unlock();
0706:                    }
0707:                }
0708:            }
0709:
0710:            /**
0711:             * Load the state of the cache from what is in the cache
0712:             * Then update the cache log itself to represent
0713:             * what we now know.
0714:             *
0715:             * FIXME: [2003-03-11] bloch the last-used time is lost when
0716:             * we shutdown; this means the LRU ordering isn't preserved on
0717:             * restart.  We should add lastUsed times to the cachedInfo.
0718:             */
0719:            private synchronized void loadFromDirectory() throws IOException {
0720:
0721:                String[] fileNames = mCacheDirectory.list();
0722:
0723:                for (int i = 0; i < fileNames.length; i++) {
0724:                    if (!fileNames[i].endsWith(".dat"))
0725:                        continue;
0726:
0727:                    int x = fileNames[i].indexOf(".dat");
0728:                    String name = fileNames[i].substring(0, x);
0729:                    long n;
0730:                    try {
0731:                        n = Long.parseLong(name);
0732:                        if (n > mCurName) {
0733:                            mCurName = n;
0734:                        }
0735:                    } catch (NumberFormatException ne) {
0736:                        mLogger.warn(
0737:                        /* (non-Javadoc)
0738:                         * @i18n.test
0739:                         * @org-mes="ignoring a strange .dat file in the cache named: " + p[0]
0740:                         */
0741:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0742:                                Cache.class.getName(), "051018-717",
0743:                                new Object[] { fileNames[i] }));
0744:                        continue;
0745:                    }
0746:
0747:                    Item item = null;
0748:                    File file = new File(mCacheDirectory + File.separator
0749:                            + fileNames[i]);
0750:                    try {
0751:                        item = new Item(file);
0752:                    } catch (Throwable e) {
0753:                        mLogger.error(
0754:                        /* (non-Javadoc)
0755:                         * @i18n.test
0756:                         * @org-mes="can't load cache file: " + p[0]
0757:                         */
0758:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0759:                                Cache.class.getName(), "051018-733",
0760:                                new Object[] { fileNames[i] }));
0761:
0762:                        mLogger.error(
0763:                        /* (non-Javadoc)
0764:                         * @i18n.test
0765:                         * @org-mes="exception: "
0766:                         */
0767:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0768:                                Cache.class.getName(), "051018-742"), e);
0769:                        mLogger.error(
0770:                        /* (non-Javadoc)
0771:                         * @i18n.test
0772:                         * @org-mes="deleting cache files for : " + p[0]
0773:                         */
0774:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0775:                                Cache.class.getName(), "051018-750",
0776:                                new Object[] { fileNames[i] }));
0777:                        // Deletes name* files.
0778:                        if (!FileUtils.deleteFilesStartingWith(mCacheDirectory,
0779:                                name)) {
0780:                            mLogger.error(
0781:                            /* (non-Javadoc)
0782:                             * @i18n.test
0783:                             * @org-mes="couldn't delete some files with name: " + p[0]
0784:                             */
0785:                            org.openlaszlo.i18n.LaszloMessages.getMessage(
0786:                                    Cache.class.getName(), "051018-760",
0787:                                    new Object[] { fileNames[i] }));
0788:                        }
0789:                        continue;
0790:                    }
0791:
0792:                    Object key = item.getKey();
0793:                    if (item.isInMemory()) {
0794:                        mMemMap.put(key, item);
0795:                        mMemSize += item.getSize();
0796:                    } else {
0797:                        mDiskMap.put(key, item);
0798:                        mDiskSize += item.getSize();
0799:                    }
0800:
0801:                    String keystring = key.toString();
0802:                    if (keystring.length() > 128) {
0803:                        keystring = keystring.substring(0, 127) + "...";
0804:                    }
0805:                    //            mLogger.debug(
0806:                    /* (non-Javadoc)
0807:                     * @i18n.test
0808:                     * @org-mes="loaded cached item for " + p[0]
0809:                     */
0810:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
0811:                    //                                Cache.class.getName(),"051018-785", new Object[] {keystring})
0812:                    //            );
0813:                }
0814:
0815:                updateMapsAndReckonItems(true);
0816:
0817:            }
0818:
0819:            /**
0820:             * Clear the cache
0821:             */
0822:            public synchronized boolean clearCache() {
0823:                mLogger.info(
0824:                /* (non-Javadoc)
0825:                 * @i18n.test
0826:                 * @org-mes="Clearing " + p[0]
0827:                 */
0828:                org.openlaszlo.i18n.LaszloMessages.getMessage(Cache.class
0829:                        .getName(), "051018-804", new Object[] { mName }));
0830:
0831:                boolean ok1 = clearMap(mActiveMap);
0832:                boolean ok2 = clearMap(mDiskMap);
0833:                boolean ok3 = clearMap(mMemMap);
0834:                boolean ok4 = true;
0835:
0836:                mMemSize = 0;
0837:                mDiskSize = 0;
0838:
0839:                ok4 = FileUtils.deleteFiles(mCacheDirectory);
0840:
0841:                return ok1 && ok2 && ok3 && ok4;
0842:            }
0843:
0844:            /**
0845:             * Clear entries from given map
0846:             * @param map to clear
0847:             */
0848:            private boolean clearMap(SequencedHashMap map) {
0849:
0850:                boolean ok = true;
0851:                while (map.size() > 0) {
0852:                    Map.Entry first = map.getFirst();
0853:                    Object key = first.getKey();
0854:                    Item item = (Item) first.getValue();
0855:                    item.lock();
0856:                    if (!item.removeAndUnlock()) {
0857:                        ok = false;
0858:                    }
0859:                    map.remove(key);
0860:                }
0861:
0862:                return ok;
0863:            }
0864:
0865:            /**
0866:             * Return a unique name
0867:             *
0868:             * Since time always moves fwd, we shouldn't
0869:             * have to worry about using names we've
0870:             * previously "allocated".
0871:             *
0872:             * FIXME: [2003-02-25 bloch] if someone sets the clock
0873:             * back, we need to clear the cache; we could easily
0874:             * detect this using timestamps on files in the cache.
0875:             */
0876:            private long nextUniqueName() {
0877:
0878:                long name;
0879:
0880:                synchronized (mNameLock) {
0881:                    name = System.currentTimeMillis();
0882:                    if (name <= mCurName) {
0883:                        name = mCurName + 1;
0884:                    }
0885:                    mCurName = name;
0886:                }
0887:
0888:                return name;
0889:            }
0890:
0891:            /**
0892:             * A class that represents an item in the Cache.
0893:             *
0894:             * @author <a href="mailto:bloch@laszlosystems.com">Eric Bloch</a>
0895:             */
0896:            protected class Item implements  Serializable {
0897:
0898:                transient private Sync mLock;
0899:                transient private boolean mDirty = false;
0900:                transient private boolean mNeedsReckoning = false;
0901:                /** true if the item is actively being updated */
0902:                transient private boolean mActive = false;
0903:
0904:                transient private byte mBuffer[];
0905:
0906:                transient private long mMemSizeToReckon = 0;
0907:                transient private long mDiskSizeToReckon = 0;
0908:
0909:                /**
0910:                 * Information about this cached item.
0911:                 */
0912:                CachedInfo mInfo = null;
0913:
0914:                /** 
0915:                 * Construct an Item based on this request
0916:                 * and lock it for write.
0917:                 */
0918:                public Item(Serializable key, String enc, boolean inMemory) {
0919:
0920:                    mLock = new ReentrantLock();
0921:                    mInfo = new CachedInfo(key, enc, inMemory, nextUniqueName());
0922:                    mBuffer = null;
0923:                }
0924:
0925:                /**
0926:                 * @return true if item is dirty
0927:                 */
0928:                public boolean dirty() {
0929:                    return mDirty;
0930:                }
0931:
0932:                /**
0933:                 * @return true if item is active
0934:                 */
0935:                public boolean active() {
0936:                    return mActive;
0937:                }
0938:
0939:                /** set if item is active */
0940:                public void setActive(boolean a) {
0941:                    mActive = a;
0942:                }
0943:
0944:                /**
0945:                 * @return true if item is dirty
0946:                 */
0947:                public boolean needsReckoning() {
0948:                    return mNeedsReckoning;
0949:                }
0950:
0951:                /**
0952:                 * @return mem to reckon
0953:                 */
0954:                public long memToReckon() {
0955:                    return mMemSizeToReckon;
0956:                }
0957:
0958:                /**
0959:                 * @return disk to reckon
0960:                 */
0961:                public long diskToReckon() {
0962:                    return mDiskSizeToReckon;
0963:                }
0964:
0965:                /**
0966:                 * Update cache sizes with size from item
0967:                 * that haven't been reckonned yet.
0968:                 * Must have item and entire cache locked to call this
0969:                 */
0970:                public void reckon() {
0971:                    mMemSize += mMemSizeToReckon;
0972:                    mDiskSize += mDiskSizeToReckon;
0973:
0974:                    mDiskSizeToReckon = 0;
0975:                    mMemSizeToReckon = 0;
0976:
0977:                    mNeedsReckoning = false;
0978:                    //            mLogger.debug("reckoned an item");
0979:                }
0980:
0981:                /**
0982:                 * Item should be locked during this call
0983:                 */
0984:                public void readIntoMemory() throws IOException {
0985:                    FileInputStream fis = null;
0986:                    try {
0987:                        String p = getPathName();
0988:                        fis = new FileInputStream(p);
0989:                        mBuffer = new byte[(int) mInfo.getSize()];
0990:                        fis.read(mBuffer, 0, (int) mInfo.getSize());
0991:                        mInfo.setInMemory(true);
0992:                    } catch (IOException e) {
0993:                        markDirty();
0994:                        throw e;
0995:                    } finally {
0996:                        FileUtils.close(fis);
0997:                    }
0998:                }
0999:
1000:                /**
1001:                 * Item should be locked during this call
1002:                 * @return size of item
1003:                 * caller is responsible for updating cache sizes
1004:                 */
1005:                public long removeFromMemory() {
1006:                    mBuffer = null;
1007:                    mInfo.setInMemory(false);
1008:                    return mInfo.getSize();
1009:                }
1010:
1011:                /** 
1012:                 * Construct an Item based on the contents of this file
1013:                 */
1014:                public Item(File f) throws IOException, OptionalDataException,
1015:                        StreamCorruptedException, ClassNotFoundException {
1016:                    mLock = new ReentrantLock();
1017:
1018:                    InputStream in = null;
1019:                    try {
1020:                        in = new BufferedInputStream(new FileInputStream(f));
1021:                        ObjectInputStream istr = new ObjectInputStream(in);
1022:                        mInfo = (CachedInfo) istr.readObject();
1023:                        // after reading the object, call our override routine
1024:                        afterCacheRead(mInfo.getMetaData());
1025:                    } finally {
1026:                        FileUtils.close(in);
1027:                    }
1028:
1029:                    // FIXME: [2003-08-15 pkang] isInMemory() will always evaluate to
1030:                    // true for items that are read from disk. This is because those
1031:                    // items are written out only when they're fetched and, by default,
1032:                    // they are created to exist in memory. Since it's better that we
1033:                    // don't read every item into memory during start-up, isInMemory is
1034:                    // set to false here.
1035:
1036:                    mInfo.setInMemory(false);
1037:
1038:                    //            if (mInfo.isInMemory()) {
1039:                    //                readIntoMemory();
1040:                    //            }
1041:                }
1042:
1043:                /**
1044:                 * Lock the item
1045:                 */
1046:                public void lock() {
1047:                    mLockLogger.debug(
1048:                    /* (non-Javadoc)
1049:                     * @i18n.test
1050:                     * @org-mes="acquiring lock: " + p[0]
1051:                     */
1052:                    org.openlaszlo.i18n.LaszloMessages.getMessage(Cache.class
1053:                            .getName(), "051018-1032",
1054:                            new Object[] { getKey() }));
1055:                    try {
1056:                        mLock.acquire();
1057:                    } catch (InterruptedException e) {
1058:                        throw new ChainedException(e);
1059:                    }
1060:                    mLockLogger.debug(
1061:                    /* (non-Javadoc)
1062:                     * @i18n.test
1063:                     * @org-mes="acquired lock: " + p[0]
1064:                     */
1065:                    org.openlaszlo.i18n.LaszloMessages.getMessage(Cache.class
1066:                            .getName(), "051018-1045",
1067:                            new Object[] { getKey() }));
1068:                }
1069:
1070:                /*
1071:                 * Done with item
1072:                 */
1073:                public void unlock() {
1074:                    mLockLogger.debug(
1075:                    /* (non-Javadoc)
1076:                     * @i18n.test
1077:                     * @org-mes="releasing read lock: " + p[0]
1078:                     */
1079:                    org.openlaszlo.i18n.LaszloMessages.getMessage(Cache.class
1080:                            .getName(), "051018-1059",
1081:                            new Object[] { getKey() }));
1082:                    mLock.release();
1083:                    mLockLogger.debug(
1084:                    /* (non-Javadoc)
1085:                     * @i18n.test
1086:                     * @org-mes="released read lock: " + p[0]
1087:                     */
1088:                    org.openlaszlo.i18n.LaszloMessages.getMessage(Cache.class
1089:                            .getName(), "051018-1068",
1090:                            new Object[] { getKey() }));
1091:                }
1092:
1093:                /**
1094:                 * @return the key for this item.
1095:                 */
1096:                public Serializable getKey() {
1097:                    if (mInfo != null)
1098:                        return mInfo.getKey();
1099:                    else
1100:                        return "uninitialized item";
1101:                }
1102:
1103:                /**
1104:                 * @return whether this item is in memory or not
1105:                 */
1106:                public boolean isInMemory() {
1107:                    if (mInfo != null)
1108:                        return mInfo.isInMemory();
1109:                    else
1110:                        return false;
1111:                }
1112:
1113:                /**
1114:                 * Return the cached size of this item in bytes 
1115:                 * Must have the item read locked for this.
1116:                 */
1117:                public long getSize() {
1118:                    return mInfo.getSize();
1119:                }
1120:
1121:                /**
1122:                 * Return the size of this items key in bytes.
1123:                 * May return -1 if the size is unknown/expensive to compute.
1124:                 * Must have the item read locked for this.
1125:                 */
1126:                public long getKeySize() {
1127:                    return mInfo.getKeySize();
1128:                }
1129:
1130:                /**
1131:                 * @return item's info
1132:                 */
1133:                public CachedInfo getInfo() {
1134:                    return mInfo;
1135:                }
1136:
1137:                /**
1138:                 * Return the path name of the cached version of this item
1139:                 */
1140:                public String getPathName() {
1141:                    // FIXME: [2003-03-03 bloch] unhardcode gz extension someday
1142:                    return mCacheDirectory.getAbsolutePath() + File.separator
1143:                            + mInfo.getName() + ".swf"
1144:                            + (mInfo.getEncoding() == null ? "" : ".gz");
1145:                }
1146:
1147:                /**
1148:                 * Return the path name of the cached info for this item
1149:                 */
1150:                public String getInfoName() {
1151:                    return mCacheDirectory.getAbsolutePath() + File.separator
1152:                            + mInfo.getName() + ".dat";
1153:                }
1154:
1155:                /**
1156:                 * Encoding the given item using the requested encoding.
1157:                 * Encode to a temporary file and then rename.
1158:                 *
1159:                 * @return the size in bytes of the encoded file
1160:                 * caller is responsible for updating item and cache sizes
1161:                 */
1162:                public long encode(String enc) throws IOException {
1163:
1164:                    File f = new File(getPathName());
1165:                    File tempDir = f.getParentFile();
1166:                    File tempFile = File.createTempFile("lzuc-", null, tempDir);
1167:                    //            mLogger.debug(
1168:                    /* (non-Javadoc)
1169:                     * @i18n.test
1170:                     * @org-mes="Temporary file is " + p[0]
1171:                     */
1172:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1173:                    //                                Cache.class.getName(),"051018-1152", new Object[] {tempFile.getAbsolutePath()})
1174:                    //);
1175:                    FileUtils.encode(f, tempFile, enc);
1176:                    long size = tempFile.length();
1177:                    if (!f.delete()) {
1178:                        mLogger.warn(
1179:                        /* (non-Javadoc)
1180:                         * @i18n.test
1181:                         * @org-mes="Can't delete " + p[0]
1182:                         */
1183:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1184:                                Cache.class.getName(), "051018-1163",
1185:                                new Object[] { f.getAbsolutePath() }));
1186:                    }
1187:                    if (!tempFile.renameTo(f)) {
1188:                        mLogger.error(
1189:                        /* (non-Javadoc)
1190:                         * @i18n.test
1191:                         * @org-mes="Can't rename temporary file to " + p[0]
1192:                         */
1193:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1194:                                Cache.class.getName(), "051018-1173",
1195:                                new Object[] { f.getAbsolutePath() }));
1196:                    }
1197:                    return size;
1198:                }
1199:
1200:                /**
1201:                 * Mark the item as dirty
1202:                 */
1203:                public void markDirty() {
1204:                    if (mDirty) {
1205:                        return;
1206:                    }
1207:                    // Removed the cache file and any buffer and mark the item
1208:                    // as dirty
1209:                    File f = new File(getPathName());
1210:                    if (f.exists() && !f.delete()) {
1211:                        mLogger.warn(
1212:                        /* (non-Javadoc)
1213:                         * @i18n.test
1214:                         * @org-mes="Can't delete " + p[0]
1215:                         */
1216:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1217:                                Cache.class.getName(), "051018-1163",
1218:                                new Object[] { getPathName() }));
1219:                    }
1220:                    f = new File(getInfoName());
1221:                    if (f.exists() && !f.delete()) {
1222:                        mLogger.warn(
1223:                        /* (non-Javadoc)
1224:                         * @i18n.test
1225:                         * @org-mes="Can't delete " + p[0]
1226:                         */
1227:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1228:                                Cache.class.getName(), "051018-1163",
1229:                                new Object[] { getInfoName() }));
1230:                    }
1231:                    mDirty = true;
1232:                    mBuffer = null;
1233:                    mNeedsReckoning = true;
1234:                    //            mLogger.debug(
1235:                    /* (non-Javadoc)
1236:                     * @i18n.test
1237:                     * @org-mes="Marking item dirty: " + p[0]
1238:                     */
1239:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1240:                    //                                Cache.class.getName(),"051018-1219", new Object[] {mInfo.getKey()})
1241:                    //);
1242:                    if (mInfo.isInMemory()) {
1243:                        mMemSizeToReckon -= mInfo.getSize();
1244:                    } else {
1245:                        mDiskSizeToReckon -= mInfo.getSize();
1246:                    }
1247:                    //            mLogger.debug(
1248:                    /* (non-Javadoc)
1249:                     * @i18n.test
1250:                     * @org-mes="disk to reckon : " + p[0] + ", mem to reckon : " + p[1]
1251:                     */
1252:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1253:                    //                                Cache.class.getName(),"051018-1232", new Object[] {new Long(mDiskSizeToReckon), new Long(mMemSizeToReckon)})
1254:                    //            );
1255:                    mInfo.setSize(0);
1256:                }
1257:
1258:                /**
1259:                 * @return true if this item is still valid
1260:                 * given the current data
1261:                 */
1262:                public boolean validForData(Data d) {
1263:                    // TODO: [2003-01-14 bloch] Make sure the cached 
1264:                    // ETag, Content-Length, and Content-MD5 are ok.
1265:                    // Need to add these to the CachedInfo class and put
1266:                    // logic here to deal with missing/present values.
1267:                    // Will need to get the right interface between
1268:                    // Item/CachedInfo/Data to make this work.
1269:                    //
1270:                    //if (hdr != null) {
1271:                    //}
1272:
1273:                    return true;
1274:                }
1275:
1276:                /**
1277:                 * Remove the cached version of this item and then unlock it.
1278:                 * Must have item locked for this.  Caller is responsible for updatng cache sizes
1279:                 * @return true if there were no problems
1280:                 */
1281:                public boolean removeAndUnlock() {
1282:                    boolean ok = remove();
1283:                    unlock();
1284:                    return ok;
1285:                }
1286:
1287:                /**
1288:                 * Remove the cached version of this item 
1289:                 * @return true if there were no problems
1290:                 * Caller is responsible for updatng cache sizes.
1291:                 */
1292:                private boolean remove() {
1293:
1294:                    boolean ok = true;
1295:                    //            mLogger.debug(
1296:                    /* (non-Javadoc)
1297:                     * @i18n.test
1298:                     * @org-mes="removing item for " + p[0] + " (" + p[1] + " - " + p[2] + " bytes) ."
1299:                     */
1300:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1301:                    //                                Cache.class.getName(),"051018-1280", new Object[] {mInfo.getKey(), getPathName(), new Long(getSize())})
1302:                    //            );
1303:                    File f = new File(getPathName());
1304:                    if (f.exists() && !f.delete()) {
1305:                        mLogger.warn(
1306:                        /* (non-Javadoc)
1307:                         * @i18n.test
1308:                         * @org-mes="Can't delete " + p[0]
1309:                         */
1310:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1311:                                Cache.class.getName(), "051018-1163",
1312:                                new Object[] { getPathName() }));
1313:                        ok = false;
1314:                    }
1315:                    f = new File(getInfoName());
1316:                    if (f.exists() && !f.delete()) {
1317:                        mLogger.warn(
1318:                        /* (non-Javadoc)
1319:                         * @i18n.test
1320:                         * @org-mes="Can't delete " + p[0]
1321:                         */
1322:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1323:                                Cache.class.getName(), "051018-1163",
1324:                                new Object[] { getInfoName() }));
1325:                        ok = false;
1326:                    }
1327:
1328:                    return ok;
1329:                }
1330:
1331:                /**
1332:                 * @return stream depending on whether we're in mem
1333:                 * or on disk
1334:                 */
1335:                public InputStream getStream() {
1336:                    if (mInfo.isInMemory()) {
1337:                        return new ByteArrayInputStream(mBuffer);
1338:                    } else {
1339:                        try {
1340:                            return new FileInputStream(getPathName());
1341:                        } catch (FileNotFoundException e) {
1342:                            throw new ChainedException(e.getMessage());
1343:                        }
1344:                    }
1345:                }
1346:
1347:                /**
1348:                 * @return returns raw byte-array data.
1349:                 * This should only be used to retrieve immutable data! If the caller modifies this byte array,
1350:                 * it could cause trouble.
1351:                 */
1352:                public byte[] getRawByteArray() {
1353:                    try {
1354:                        if (!mInfo.isInMemory()) {
1355:                            readIntoMemory();
1356:                        }
1357:                        if (mInfo.isInMemory()) {
1358:                            return mBuffer;
1359:                        } else {
1360:                            ByteArrayOutputStream bos = null;
1361:                            FileInputStream instream = null;
1362:                            try {
1363:                                // If it's still not in memory, maybe it was too big, so let's copy it into
1364:                                // a new byte array and return that.
1365:                                bos = new ByteArrayOutputStream();
1366:                                instream = new FileInputStream(getPathName());
1367:                                FileUtils.send(instream, bos);
1368:                                return bos.toByteArray();
1369:                            } catch (FileNotFoundException e) {
1370:                                throw new ChainedException(e.getMessage());
1371:                            } finally {
1372:                                if (bos != null) {
1373:                                    bos.close();
1374:                                }
1375:                                if (instream != null) {
1376:                                    instream.close();
1377:                                }
1378:                            }
1379:
1380:                        }
1381:                    } catch (IOException e) {
1382:                        throw new ChainedException(e.getMessage());
1383:                    }
1384:                }
1385:
1386:                /**
1387:                 * @return the file object 
1388:                 */
1389:                public File getFile() {
1390:                    return new File(getPathName());
1391:                }
1392:
1393:                /**
1394:                 * Get the meta data for the current item
1395:                 */
1396:                public Serializable getMetaData() {
1397:                    return mInfo.getMetaData();
1398:                }
1399:
1400:                /**
1401:                 * Update the item from the given input stream
1402:                 * and meta data and mark the item as clean 
1403:                 * (not dirty).
1404:                 *
1405:                 * @param in input stream; ignored if null
1406:                 * @param metaData
1407:                 */
1408:                public void update(InputStream in, Serializable metaData)
1409:                        throws IOException {
1410:
1411:                    //            mLogger.debug(
1412:                    /* (non-Javadoc)
1413:                     * @i18n.test
1414:                     * @org-mes="updating item stream and metadata"
1415:                     */
1416:                    //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1417:                    //                                Cache.class.getName(),"051018-1399")
1418:                    //);
1419:                    update(metaData);
1420:
1421:                    if (in != null) {
1422:                        update(in);
1423:                    }
1424:
1425:                    markClean();
1426:                }
1427:
1428:                /**
1429:                 * Update the item from the given input stream
1430:                 *
1431:                 * @param in input stream
1432:                 */
1433:                public void update(InputStream in) throws IOException {
1434:
1435:                    FileOutputStream out = null;
1436:
1437:                    try {
1438:
1439:                        //                mLogger.debug(
1440:                        /* (non-Javadoc)
1441:                         * @i18n.test
1442:                         * @org-mes="updating item from stream"
1443:                         */
1444:                        //                        org.openlaszlo.i18n.LaszloMessages.getMessage(
1445:                        //                                Cache.class.getName(),"051018-1428")
1446:                        //);
1447:                        out = new FileOutputStream(getPathName());
1448:                        long size = FileUtils.send(in, out);
1449:                        FileUtils.close(out);
1450:
1451:                        String enc = mInfo.getEncoding();
1452:                        if (enc != null && !enc.equals("")) {
1453:                            size = encode(enc);
1454:                        }
1455:
1456:                        long oldSize = mInfo.getSize();
1457:                        mInfo.setSize(size);
1458:                        mNeedsReckoning = true;
1459:
1460:                        // Remove size from any old item
1461:                        if (mInfo.isInMemory()) {
1462:                            mMemSizeToReckon -= oldSize;
1463:                        } else {
1464:                            mDiskSizeToReckon -= oldSize;
1465:                        }
1466:
1467:                        // Check to see if we're too big for memory
1468:                        if (mInfo.isInMemory() && mMaxMemItemSize > 0
1469:                                && size > mMaxMemItemSize) {
1470:                            mLogger.debug("this item too big for memory ");
1471:                            mInfo.setInMemory(false);
1472:                        }
1473:
1474:                        if (mInfo.isInMemory()) {
1475:                            mLogger.debug("reading item into memory ");
1476:                            readIntoMemory();
1477:                            mMemSizeToReckon += size;
1478:                        } else {
1479:                            mDiskSizeToReckon += size;
1480:                        }
1481:
1482:                    } finally {
1483:                        FileUtils.close(out);
1484:                    }
1485:                }
1486:
1487:                /**
1488:                 * Mark the item as clean
1489:                 */
1490:                public void markClean() {
1491:                    mDirty = false;
1492:                }
1493:
1494:                /**
1495:                 * Update the item's meta data.
1496:                 *
1497:                 * @param metaData
1498:                 */
1499:                public void update(Serializable metaData) throws IOException {
1500:
1501:                    mInfo.setMetaData(metaData);
1502:                    updateInfo();
1503:                }
1504:
1505:                /**
1506:                 * Update the item's info
1507:                 */
1508:                public void updateInfo() throws IOException {
1509:
1510:                    FileOutputStream out = null;
1511:
1512:                    try {
1513:
1514:                        // Write out the info (.dat) file
1515:                        out = new FileOutputStream(getInfoName());
1516:                        ObjectOutputStream ostr = new ObjectOutputStream(out);
1517:                        ostr.writeObject(mInfo);
1518:                        ostr.flush();
1519:                        ostr.close();
1520:
1521:                    } finally {
1522:                        FileUtils.close(out);
1523:                    }
1524:                }
1525:            }
1526:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.