1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.tuigwaa.cms.core.wiki.base;
17
18 import java.util.Date;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.apache.commons.collections.map.ReferenceMap;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.seasar.tuigwaa.cms.core.Page;
26 import org.seasar.tuigwaa.cms.core.wiki.engine.Node;
27
28
29 /***
30 * Caching parse tree for specified page.
31 * @author someda
32 */
33 public class CacheManager {
34
35 private static CacheManager instance_;
36 private Map cacheMap_;
37 private Map cacheMetaMap_;
38
39 private static Log log_ = LogFactory.getLog(CacheManager.class);
40
41 private CacheManager(){
42 init();
43 }
44
45 private void init(){
46 cacheMap_ = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
47 cacheMetaMap_ = new HashMap();
48 }
49
50 public synchronized static CacheManager getInstance(){
51 if(instance_ == null){
52 instance_ = new CacheManager();
53 }
54 return instance_;
55 }
56
57 public boolean isCachable(Page page, Node node){
58 return page.getResource().isPersistent();
59 }
60
61 /***
62 * Returns cached node.
63 * Before returning, this checks 2 items.
64 * <ol>
65 * <li>The cache contents of the page exists or not.
66 * If exsists, proceeds next step, otherwise returns null.</li>
67 * <li>The last modification time of given page is newer than cache creation date.
68 * If true, invalidating the cache contents and returns null.</li>
69 * </ol>
70 */
71 public Node get(Page page){
72 Node node = null;
73 CacheMetadata metadata = null;
74
75 synchronized(cacheMap_){
76 node = (Node) cacheMap_.get(page);
77
78 if(node == null){
79 cacheMetaMap_.remove(page);
80 }else{
81 metadata = (CacheMetadata) cacheMetaMap_.get(page);
82 if(metadata == null || !metadata.isCacheValid(page.getResource().getModificationDateAsDate())){
83 node = null;
84 cacheMap_.remove(page);
85 }else{
86 metadata.hit();
87 }
88 }
89 }
90 if(node == null){
91 log_.info(page.getResource().getPath() + " cache miss.");
92 }
93 return node;
94 }
95
96 public void cache(Page page, Node node){
97 CacheMetadata cache = new CacheMetadata();
98 synchronized(cacheMap_){
99 cacheMap_.put(page,node);
100 cacheMetaMap_.put(page,cache);
101 }
102 }
103
104 public void clean(){
105 init();
106 }
107
108 private static class CacheMetadata{
109 int hit_;
110 long createdtime_;
111
112 public CacheMetadata(){
113 createdtime_ = System.currentTimeMillis();
114 }
115
116 public synchronized void hit(){
117 hit_++;
118 }
119
120 public int getHit(){
121 return hit_;
122 }
123
124 public boolean isCacheValid(Date date){
125 if(date == null) return false;
126 return (date.getTime() <= createdtime_);
127 }
128 }
129 }