File Source: PlanetCache.java
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. The ASF licenses this file to You
4 * under the Apache License, Version 2.0 (the "License"); you may not
5 * 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, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. For additional information regarding
15 * copyright in this work, please see the NOTICE file in the top level
16 * directory of this distribution.
17 */
18
19 package org.apache.roller.weblogger.ui.rendering.util.cache;
20
21 import java.util.Date;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.Map;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.roller.weblogger.WebloggerException;
28 import org.apache.roller.weblogger.config.WebloggerConfig;
29 import org.apache.roller.weblogger.business.WebloggerFactory;
30 import org.apache.roller.planet.business.Planet;
31 import org.apache.roller.planet.business.PlanetFactory;
32 import org.apache.roller.planet.business.PlanetManager;
33 import org.apache.roller.weblogger.ui.rendering.util.PlanetRequest;
34 import org.apache.roller.weblogger.util.cache.Cache;
35 import org.apache.roller.weblogger.util.cache.CacheManager;
36 import org.apache.roller.weblogger.util.cache.ExpiringCacheEntry;
37
38
39 /**
40 * Cache for planet content.
41 */
42 public class PlanetCache {
43
/*
P/P * Method: org.apache.roller.weblogger.ui.rendering.util.cache.PlanetCache__static_init
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@44 != null
*
* Postconditions:
* (soft) log != null
* singletonInstance == &new PlanetCache(PlanetCache__static_init#1)
* new PlanetCache(PlanetCache__static_init#1) num objects == 1
* init'ed(singletonInstance.cacheEnabled)
* init'ed(singletonInstance.contentCache)
* singletonInstance.lastUpdateTime == null
* singletonInstance.timeout in -9_223_372_036_854_775_000..18_446_744_073_709_551_000
*/
44 private static Log log = LogFactory.getLog(PlanetCache.class);
45
46 // a unique identifier for this cache, this is used as the prefix for
47 // roller config properties that apply to this cache
48 public static final String CACHE_ID = "cache.planet";
49
50 // keep cached content
51 private boolean cacheEnabled = true;
52 private Cache contentCache = null;
53
54 // keep a cached version of last expired time
55 private ExpiringCacheEntry lastUpdateTime = null;
56 private long timeout = 15 * 60 * 1000;
57
58 // reference to our singleton instance
59 private static PlanetCache singletonInstance = new PlanetCache();
60
61
/*
P/P * Method: void org.apache.roller.weblogger.ui.rendering.util.cache.PlanetCache()
*
* Preconditions:
* log != null
*
* Presumptions:
* java.lang.Long:parseLong(...)@91 in -9_223_372_036_854_775..18_446_744_073_709_551
* java.lang.String:length(...)@75 <= 232-2
* java.util.Enumeration:nextElement(...)@71 != null
* org.apache.roller.weblogger.config.WebloggerConfig:keys(...)@68 != null
*
* Postconditions:
* init'ed(this.cacheEnabled)
* init'ed(this.contentCache)
* this.lastUpdateTime == null
* this.timeout in -9_223_372_036_854_775_000..18_446_744_073_709_551_000
*
* Test Vectors:
* java.lang.String:startsWith(...)@74: {0}, {1}
* java.util.Enumeration:hasMoreElements(...)@70: {0}, {1}
* org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@64: {0}, {1}
*/
62 private PlanetCache() {
63
64 cacheEnabled = WebloggerConfig.getBooleanProperty(CACHE_ID+".enabled");
65
66 Map cacheProps = new HashMap();
67 cacheProps.put("id", CACHE_ID);
68 Enumeration allProps = WebloggerConfig.keys();
69 String prop = null;
70 while(allProps.hasMoreElements()) {
71 prop = (String) allProps.nextElement();
72
73 // we are only interested in props for this cache
74 if(prop.startsWith(CACHE_ID+".")) {
75 cacheProps.put(prop.substring(CACHE_ID.length()+1),
76 WebloggerConfig.getProperty(prop));
77 }
78 }
79
80 log.info("Planet cache = "+cacheProps);
81
82 if(cacheEnabled) {
83 contentCache = CacheManager.constructCache(null, cacheProps);
84 } else {
85 log.warn("Caching has been DISABLED");
86 }
87
88 // lookup our timeout value
89 String timeoutString = WebloggerConfig.getProperty("cache.planet.timeout");
90 try {
91 long timeoutSecs = Long.parseLong(timeoutString);
92 this.timeout = timeoutSecs * 1000;
93 } catch(Exception e) {
94 // ignored ... illegal value
95 }
96 }
97
98
99 public static PlanetCache getInstance() {
/*
P/P * Method: PlanetCache getInstance()
*
* Preconditions:
* init'ed(singletonInstance)
*
* Postconditions:
* return_value == singletonInstance
* init'ed(return_value)
*/
100 return singletonInstance;
101 }
102
103
104 public Object get(String key) {
105
/*
P/P * Method: Object get(String)
*
* Preconditions:
* init'ed(this.cacheEnabled)
* (soft) log != null
* (soft) this.contentCache != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* this.cacheEnabled: {1}, {0}
* org.apache.roller.weblogger.util.cache.Cache:get(...)@109: Inverse{null}, Addr_Set{null}
*/
106 if(!cacheEnabled)
107 return null;
108
109 Object entry = contentCache.get(key);
110
111 if(entry == null) {
112 log.debug("MISS "+key);
113 } else {
114 log.debug("HIT "+key);
115 }
116
117 return entry;
118 }
119
120
121 public void put(String key, Object value) {
122
/*
P/P * Method: void put(String, Object)
*
* Preconditions:
* init'ed(this.cacheEnabled)
* (soft) log != null
* (soft) this.contentCache != null
*
* Test Vectors:
* this.cacheEnabled: {1}, {0}
*/
123 if(!cacheEnabled)
124 return;
125
126 contentCache.put(key, value);
127 log.debug("PUT "+key);
128 }
129
130
131 public void remove(String key) {
132
/*
P/P * Method: void remove(String)
*
* Preconditions:
* init'ed(this.cacheEnabled)
* (soft) log != null
* (soft) this.contentCache != null
*
* Test Vectors:
* this.cacheEnabled: {1}, {0}
*/
133 if(!cacheEnabled)
134 return;
135
136 contentCache.remove(key);
137 log.debug("REMOVE "+key);
138 }
139
140
141 public void clear() {
142
/*
P/P * Method: void clear()
*
* Preconditions:
* init'ed(this.cacheEnabled)
* (soft) log != null
* (soft) this.contentCache != null
*
* Postconditions:
* this.lastUpdateTime == One-of{old this.lastUpdateTime, null}
*
* Test Vectors:
* this.cacheEnabled: {1}, {0}
*/
143 if(!cacheEnabled)
144 return;
145
146 contentCache.clear();
147 this.lastUpdateTime = null;
148 log.debug("CLEAR");
149 }
150
151
152 public Date getLastModified() {
153
/*
P/P * Method: Date getLastModified()
*
* Preconditions:
* init'ed(this.lastUpdateTime)
* (soft) log != null
* (soft) init'ed(this.timeout)
*
* Postconditions:
* return_value != null
* this.lastUpdateTime == One-of{old this.lastUpdateTime, &new ExpiringCacheEntry(getLastModified#2)}
* this.lastUpdateTime != null
* new Date(getLastModified#1) num objects <= 1
* new ExpiringCacheEntry(getLastModified#2) num objects <= 1
*
* Test Vectors:
* this.lastUpdateTime: Addr_Set{null}, Inverse{null}
*/
154 Date lastModified = null;
155
156 // first try our cached version
157 if(this.lastUpdateTime != null) {
158 lastModified = (Date) this.lastUpdateTime.getValue();
159 }
160
161 // still null, we need to get a fresh value
162 if(lastModified == null) {
163
164 // TODO: ROLLER40 last updated for planet
165 lastModified = null; // PlanetFactory.getPlanet().getPlanetManager().getLastUpdated();
166
+ 167 if (lastModified == null) {
168 lastModified = new Date();
169 log.warn("Can't get lastUpdate time, using current time instead");
170 }
171
172 this.lastUpdateTime = new ExpiringCacheEntry(lastModified, this.timeout);
173 }
174
175 return lastModified;
176 }
177
178
179 /**
180 * Generate a cache key from a parsed planet request.
181 * This generates a key of the form ...
182 *
183 * <context>/<type>/<language>[/user]
184 * or
185 * <context>/<type>[/flavor]/<language>[/excerpts]
186 *
187 *
188 * examples ...
189 *
190 * planet/page/en
191 * planet/feed/rss/en/excerpts
192 *
193 */
194 public String generateKey(PlanetRequest planetRequest) {
195
/*
P/P * Method: String generateKey(PlanetRequest)
*
* Preconditions:
* planetRequest != null
* init'ed(planetRequest.context)
* init'ed(planetRequest.flavor)
* init'ed(planetRequest.group)
* init'ed(planetRequest.language)
* init'ed(planetRequest.type)
* (soft) init'ed(planetRequest.authenticUser)
* (soft) init'ed(planetRequest.excerpts)
*
* Postconditions:
* init'ed(java.lang.StringBuffer:toString(...)._tainted)
* return_value == &java.lang.StringBuffer:toString(...)
*
* Test Vectors:
* planetRequest.authenticUser: Addr_Set{null}, Inverse{null}
* planetRequest.excerpts: {0}, {1}
* planetRequest.flavor: Addr_Set{null}, Inverse{null}
* planetRequest.group: Addr_Set{null}, Inverse{null}
*/
196 StringBuffer key = new StringBuffer();
197
198 key.append(this.CACHE_ID).append(":");
199 key.append(planetRequest.getContext());
200 key.append("/");
201 key.append(planetRequest.getType());
202
203 if(planetRequest.getFlavor() != null) {
204 key.append("/").append(planetRequest.getFlavor());
205 }
206
207 // add language
208 key.append("/").append(planetRequest.getLanguage());
209
210 if(planetRequest.getFlavor() != null) {
211 // add excerpts
212 if(planetRequest.isExcerpts()) {
213 key.append("/excerpts");
214 }
215 } else {
216 // add login state
217 if(planetRequest.getAuthenticUser() != null) {
218 key.append("/user=").append(planetRequest.getAuthenticUser());
219 }
220 }
221
222 // add group
223 if (planetRequest.getGroup() != null) {
224 key.append("/group=").append(planetRequest.getGroup());
225 }
226
227 return key.toString();
228 }
229
230 }
SofCheck Inspector Build Version : 2.18479
| PlanetCache.java |
2009-Jan-02 14:25:06 |
| PlanetCache.class |
2009-Sep-04 03:12:45 |