Source Code Cross Referenced for AbstractDiskPersistenceListener.java in  » Cache » OSCache » com » opensymphony » oscache » plugins » diskpersistence » 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
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Cache » OSCache » com.opensymphony.oscache.plugins.diskpersistence 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2002-2003 by OpenSymphony
003:         * All rights reserved.
004:         */
005:        package com.opensymphony.oscache.plugins.diskpersistence;
006:
007:        import com.opensymphony.oscache.base.Config;
008:        import com.opensymphony.oscache.base.persistence.CachePersistenceException;
009:        import com.opensymphony.oscache.base.persistence.PersistenceListener;
010:        import com.opensymphony.oscache.web.ServletCacheAdministrator;
011:
012:        import org.apache.commons.logging.Log;
013:        import org.apache.commons.logging.LogFactory;
014:
015:        import java.io.*;
016:
017:        import java.util.Set;
018:
019:        import javax.servlet.jsp.PageContext;
020:
021:        /**
022:         * Persist the cache data to disk.
023:         *
024:         * The code in this class is totally not thread safe it is the resonsibility
025:         * of the cache using this persistence listener to handle the concurrency.
026:         *
027:         * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
028:         * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
029:         * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
030:         * @author <a href="mailto:amarch@soe.sony.com">Andres March</a>
031:         */
032:        public abstract class AbstractDiskPersistenceListener implements 
033:                PersistenceListener, Serializable {
034:            public final static String CACHE_PATH_KEY = "cache.path";
035:
036:            /**
037:             * File extension for disk cache file
038:             */
039:            protected final static String CACHE_EXTENSION = "cache";
040:
041:            /**
042:             * The directory that cache groups are stored under
043:             */
044:            protected final static String GROUP_DIRECTORY = "__groups__";
045:
046:            /**
047:             * Sub path name for application cache
048:             */
049:            protected final static String APPLICATION_CACHE_SUBPATH = "application";
050:
051:            /**
052:             * Sub path name for session cache
053:             */
054:            protected final static String SESSION_CACHE_SUBPATH = "session";
055:
056:            /**
057:             * Property to get the temporary working directory of the servlet container.
058:             */
059:            protected static final String CONTEXT_TMPDIR = "javax.servlet.context.tempdir";
060:            private static transient final Log log = LogFactory
061:                    .getLog(AbstractDiskPersistenceListener.class);
062:
063:            /**
064:             * Base path where the disk cache reside.
065:             */
066:            private File cachePath = null;
067:            private File contextTmpDir;
068:
069:            /**
070:             * Root path for disk cache
071:             */
072:            private String root = null;
073:
074:            /**
075:             *        Get the physical cache path on disk.
076:             *
077:             *        @return        A file representing the physical cache location.
078:             */
079:            public File getCachePath() {
080:                return cachePath;
081:            }
082:
083:            /**
084:             *        Get the root directory for persisting the cache on disk.
085:             *        This path includes scope and sessionId, if any.
086:             *
087:             *        @return        A String representing the root directory.
088:             */
089:            public String getRoot() {
090:                return root;
091:            }
092:
093:            /**
094:             *        Get the servlet context tmp directory.
095:             *
096:             *        @return        A file representing the servlet context tmp directory.
097:             */
098:            public File getContextTmpDir() {
099:                return contextTmpDir;
100:            }
101:
102:            /**
103:             * Verify if a group exists in the cache
104:             *
105:             * @param group The group name to check
106:             * @return True if it exists
107:             * @throws CachePersistenceException
108:             */
109:            public boolean isGroupStored(String group)
110:                    throws CachePersistenceException {
111:                try {
112:                    File file = getCacheGroupFile(group);
113:
114:                    return file.exists();
115:                } catch (Exception e) {
116:                    throw new CachePersistenceException("Unable verify group '"
117:                            + group + "' exists in the cache: " + e);
118:                }
119:            }
120:
121:            /**
122:             * Verify if an object is currently stored in the cache
123:             *
124:             * @param key The object key
125:             * @return True if it exists
126:             * @throws CachePersistenceException
127:             */
128:            public boolean isStored(String key)
129:                    throws CachePersistenceException {
130:                try {
131:                    File file = getCacheFile(key);
132:
133:                    return file.exists();
134:                } catch (Exception e) {
135:                    throw new CachePersistenceException("Unable verify id '"
136:                            + key + "' is stored in the cache: " + e);
137:                }
138:            }
139:
140:            /**
141:             * Clears the whole cache directory, starting from the root
142:             *
143:             * @throws CachePersistenceException
144:             */
145:            public void clear() throws CachePersistenceException {
146:                clear(root);
147:            }
148:
149:            /**
150:             * Initialises this <tt>DiskPersistenceListener</tt> using the supplied
151:             * configuration.
152:             *
153:             * @param config The OSCache configuration
154:             */
155:            public PersistenceListener configure(Config config) {
156:                String sessionId = null;
157:                int scope = 0;
158:                initFileCaching(config.getProperty(CACHE_PATH_KEY));
159:
160:                if (config
161:                        .getProperty(ServletCacheAdministrator.HASH_KEY_SESSION_ID) != null) {
162:                    sessionId = config
163:                            .getProperty(ServletCacheAdministrator.HASH_KEY_SESSION_ID);
164:                }
165:
166:                if (config
167:                        .getProperty(ServletCacheAdministrator.HASH_KEY_SCOPE) != null) {
168:                    scope = Integer
169:                            .parseInt(config
170:                                    .getProperty(ServletCacheAdministrator.HASH_KEY_SCOPE));
171:                }
172:
173:                StringBuffer root = new StringBuffer(getCachePath().getPath());
174:                root.append("/");
175:                root.append(getPathPart(scope));
176:
177:                if ((sessionId != null) && (sessionId.length() > 0)) {
178:                    root.append("/");
179:                    root.append(sessionId);
180:                }
181:
182:                this .root = root.toString();
183:                this .contextTmpDir = (File) config
184:                        .get(ServletCacheAdministrator.HASH_KEY_CONTEXT_TMPDIR);
185:
186:                return this ;
187:            }
188:
189:            /**
190:             * Delete a single cache entry.
191:             *
192:             * @param key The object key to delete
193:             * @throws CachePersistenceException
194:             */
195:            public void remove(String key) throws CachePersistenceException {
196:                File file = getCacheFile(key);
197:                remove(file);
198:            }
199:
200:            /**
201:             * Deletes an entire group from the cache.
202:             *
203:             * @param groupName The name of the group to delete
204:             * @throws CachePersistenceException
205:             */
206:            public void removeGroup(String groupName)
207:                    throws CachePersistenceException {
208:                File file = getCacheGroupFile(groupName);
209:                remove(file);
210:            }
211:
212:            /**
213:             * Retrieve an object from the disk
214:             *
215:             * @param key The object key
216:             * @return The retrieved object
217:             * @throws CachePersistenceException
218:             */
219:            public Object retrieve(String key) throws CachePersistenceException {
220:                return retrieve(getCacheFile(key));
221:            }
222:
223:            /**
224:             * Retrieves a group from the cache, or <code>null</code> if the group
225:             * file could not be found.
226:             *
227:             * @param groupName The name of the group to retrieve.
228:             * @return A <code>Set</code> containing keys of all of the cache
229:             * entries that belong to this group.
230:             * @throws CachePersistenceException
231:             */
232:            public Set retrieveGroup(String groupName)
233:                    throws CachePersistenceException {
234:                File groupFile = getCacheGroupFile(groupName);
235:
236:                try {
237:                    return (Set) retrieve(groupFile);
238:                } catch (ClassCastException e) {
239:                    throw new CachePersistenceException("Group file "
240:                            + groupFile + " was not persisted as a Set: " + e);
241:                }
242:            }
243:
244:            /**
245:             * Stores an object in cache
246:             *
247:             * @param key The object's key
248:             * @param obj The object to store
249:             * @throws CachePersistenceException
250:             */
251:            public void store(String key, Object obj)
252:                    throws CachePersistenceException {
253:                File file = getCacheFile(key);
254:                store(file, obj);
255:            }
256:
257:            /**
258:             * Stores a group in the persistent cache. This will overwrite any existing
259:             * group with the same name
260:             */
261:            public void storeGroup(String groupName, Set group)
262:                    throws CachePersistenceException {
263:                File groupFile = getCacheGroupFile(groupName);
264:                store(groupFile, group);
265:            }
266:
267:            /**
268:             * Allows to translate to the temp dir of the servlet container if cachePathStr
269:             * is javax.servlet.context.tempdir.
270:             *
271:             * @param cachePathStr  Cache path read from the properties file.
272:             * @return Adjusted cache path
273:             */
274:            protected String adjustFileCachePath(String cachePathStr) {
275:                if (cachePathStr.compareToIgnoreCase(CONTEXT_TMPDIR) == 0) {
276:                    cachePathStr = contextTmpDir.getAbsolutePath();
277:                }
278:
279:                return cachePathStr;
280:            }
281:
282:            /**
283:             *        Set caching to file on or off.
284:             *  If the <code>cache.path</code> property exists, we assume file caching is turned on.
285:             *        By the same token, to turn off file caching just remove this property.
286:             */
287:            protected void initFileCaching(String cachePathStr) {
288:                if (cachePathStr != null) {
289:                    cachePath = new File(cachePathStr);
290:
291:                    try {
292:                        if (!cachePath.exists()) {
293:                            if (log.isInfoEnabled()) {
294:                                log.info("cache.path '" + cachePathStr
295:                                        + "' does not exist, creating");
296:                            }
297:
298:                            cachePath.mkdirs();
299:                        }
300:
301:                        if (!cachePath.isDirectory()) {
302:                            log.error("cache.path '" + cachePathStr
303:                                    + "' is not a directory");
304:                            cachePath = null;
305:                        } else if (!cachePath.canWrite()) {
306:                            log.error("cache.path '" + cachePathStr
307:                                    + "' is not a writable location");
308:                            cachePath = null;
309:                        }
310:                    } catch (Exception e) {
311:                        log.error("cache.path '" + cachePathStr
312:                                + "' could not be used", e);
313:                        cachePath = null;
314:                    }
315:                } else {
316:                    // Use default value
317:                }
318:            }
319:
320:            // try 30s to delete the file
321:            private static final long DELETE_THREAD_SLEEP = 500;
322:            private static final int DELETE_COUNT = 60;
323:
324:            protected void remove(File file) throws CachePersistenceException {
325:                int count = DELETE_COUNT;
326:                try {
327:                    // Loop until we are able to delete (No current read).
328:                    // The cache must ensure that there are never two concurrent threads
329:                    // doing write (store and delete) operations on the same item.
330:                    // Delete only should be enough but file.exists prevents infinite loop
331:                    while (file.exists() && !file.delete() && count != 0) {
332:                        count--;
333:                        try {
334:                            Thread.sleep(DELETE_THREAD_SLEEP);
335:                        } catch (InterruptedException ignore) {
336:                        }
337:                    }
338:                } catch (Exception e) {
339:                    throw new CachePersistenceException("Unable to remove '"
340:                            + file + "' from the cache: " + e);
341:                }
342:                if (file.exists() && count == 0) {
343:                    throw new CachePersistenceException("Unable to delete '"
344:                            + file + "' from the cache. " + DELETE_COUNT
345:                            + " attempts at " + DELETE_THREAD_SLEEP
346:                            + " milliseconds intervals.");
347:                }
348:            }
349:
350:            /**
351:             * Stores an object using the supplied file object
352:             *
353:             * @param file The file to use for storing the object
354:             * @param obj the object to store
355:             * @throws CachePersistenceException
356:             */
357:            protected void store(File file, Object obj)
358:                    throws CachePersistenceException {
359:                // check if file exists before testing if parent exists
360:                if (!file.exists()) {
361:                    // check if the directory structure required exists and create it if it doesn't
362:                    File filepath = new File(file.getParent());
363:
364:                    try {
365:                        if (!filepath.exists()) {
366:                            filepath.mkdirs();
367:                        }
368:                    } catch (Exception e) {
369:                        throw new CachePersistenceException(
370:                                "Unable to create the directory " + filepath);
371:                    }
372:                }
373:
374:                // Write the object to disk
375:                try {
376:                    FileOutputStream fout = new FileOutputStream(file);
377:                    try {
378:                        ObjectOutputStream oout = new ObjectOutputStream(
379:                                new BufferedOutputStream(fout));
380:                        try {
381:                            oout.writeObject(obj);
382:                            oout.flush();
383:                        } finally {
384:                            try {
385:                                oout.close();
386:                            } catch (Exception e) {
387:                            }
388:                        }
389:                    } finally {
390:                        try {
391:                            fout.close();
392:                        } catch (Exception e) {
393:                        }
394:                    }
395:                } catch (Exception e) {
396:                    int count = DELETE_COUNT;
397:                    while (file.exists() && !file.delete() && count != 0) {
398:                        count--;
399:                        try {
400:                            Thread.sleep(DELETE_THREAD_SLEEP);
401:                        } catch (InterruptedException ignore) {
402:                        }
403:                    }
404:                    throw new CachePersistenceException("Unable to write '"
405:                            + file + "' in the cache. Exception: "
406:                            + e.getClass().getName() + ", Message: "
407:                            + e.getMessage());
408:                }
409:            }
410:
411:            /**
412:             * Build fully qualified cache file for the specified cache entry key.
413:             *
414:             * @param key   Cache Entry Key.
415:             * @return File reference.
416:             */
417:            protected File getCacheFile(String key) {
418:                char[] fileChars = getCacheFileName(key);
419:
420:                File file = new File(root, new String(fileChars) + "."
421:                        + CACHE_EXTENSION);
422:
423:                return file;
424:            }
425:
426:            /**
427:             * Build cache file name for the specified cache entry key.
428:             *
429:             * @param key   Cache Entry Key.
430:             * @return char[] file name.
431:             */
432:            protected abstract char[] getCacheFileName(String key);
433:
434:            /**
435:             * Builds a fully qualified file name that specifies a cache group entry.
436:             *
437:             * @param group The name of the group
438:             * @return A File reference
439:             */
440:            private File getCacheGroupFile(String group) {
441:                int AVERAGE_PATH_LENGTH = 30;
442:
443:                if ((group == null) || (group.length() == 0)) {
444:                    throw new IllegalArgumentException("Invalid group '"
445:                            + group + "' specified to getCacheGroupFile.");
446:                }
447:
448:                StringBuffer path = new StringBuffer(AVERAGE_PATH_LENGTH);
449:
450:                // Build a fully qualified file name for this group
451:                path.append(GROUP_DIRECTORY).append('/');
452:                path.append(getCacheFileName(group)).append('.').append(
453:                        CACHE_EXTENSION);
454:
455:                return new File(root, path.toString());
456:            }
457:
458:            /**
459:             * This allows to persist different scopes in different path in the case of
460:             * file caching.
461:             *
462:             * @param scope   Cache scope.
463:             * @return The scope subpath
464:             */
465:            private String getPathPart(int scope) {
466:                if (scope == PageContext.SESSION_SCOPE) {
467:                    return SESSION_CACHE_SUBPATH;
468:                } else {
469:                    return APPLICATION_CACHE_SUBPATH;
470:                }
471:            }
472:
473:            /**
474:             * Clears a whole directory, starting from the specified
475:             * directory
476:             *
477:             * @param baseDirName The root directory to delete
478:             * @throws CachePersistenceException
479:             */
480:            private void clear(String baseDirName)
481:                    throws CachePersistenceException {
482:                File baseDir = new File(baseDirName);
483:                File[] fileList = baseDir.listFiles();
484:
485:                try {
486:                    if (fileList != null) {
487:                        // Loop through all the files and directory to delete them
488:                        for (int count = 0; count < fileList.length; count++) {
489:                            if (fileList[count].isFile()) {
490:                                fileList[count].delete();
491:                            } else {
492:                                // Make a recursive call to delete the directory
493:                                clear(fileList[count].toString());
494:                                fileList[count].delete();
495:                            }
496:                        }
497:                    }
498:
499:                    // Delete the root directory
500:                    baseDir.delete();
501:                } catch (Exception e) {
502:                    throw new CachePersistenceException(
503:                            "Unable to clear the cache directory");
504:                }
505:            }
506:
507:            /**
508:             * Retrives a serialized object from the supplied file, or returns
509:             * <code>null</code> if the file does not exist.
510:             *
511:             * @param file The file to deserialize
512:             * @return The deserialized object
513:             * @throws CachePersistenceException
514:             */
515:            private Object retrieve(File file) throws CachePersistenceException {
516:                Object readContent = null;
517:                boolean fileExist;
518:
519:                try {
520:                    fileExist = file.exists();
521:                } catch (Exception e) {
522:                    throw new CachePersistenceException("Unable to verify if "
523:                            + file + " exists: " + e);
524:                }
525:
526:                // Read the file if it exists
527:                if (fileExist) {
528:                    ObjectInputStream oin = null;
529:
530:                    try {
531:                        BufferedInputStream in = new BufferedInputStream(
532:                                new FileInputStream(file));
533:                        oin = new ObjectInputStream(in);
534:                        readContent = oin.readObject();
535:                    } catch (Exception e) {
536:                        // We expect this exception to occur.
537:                        // This is when the item will be invalidated (written or deleted)
538:                        // during read.
539:                        // The cache has the logic to retry reading.
540:                        throw new CachePersistenceException("Unable to read '"
541:                                + file.getAbsolutePath() + "' from the cache: "
542:                                + e);
543:                    } finally {
544:                        // HHDE: no need to close in. Will be closed by oin
545:                        try {
546:                            oin.close();
547:                        } catch (Exception ex) {
548:                        }
549:                    }
550:                }
551:
552:                return readContent;
553:            }
554:        }
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.