View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
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 }