KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > ui > rendering > util > SiteWideCache


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.ui.rendering.util;
20
21 import java.io.UnsupportedEncodingException JavaDoc;
22 import java.net.URLEncoder JavaDoc;
23 import java.util.Date JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.roller.config.RollerConfig;
31 import org.apache.roller.config.RollerRuntimeConfig;
32 import org.apache.roller.pojos.BookmarkData;
33 import org.apache.roller.pojos.CommentData;
34 import org.apache.roller.pojos.FolderData;
35 import org.apache.roller.pojos.RefererData;
36 import org.apache.roller.pojos.UserData;
37 import org.apache.roller.pojos.WeblogCategoryData;
38 import org.apache.roller.pojos.WeblogEntryData;
39 import org.apache.roller.pojos.WeblogTemplate;
40 import org.apache.roller.pojos.WebsiteData;
41 import org.apache.roller.util.Utilities;
42 import org.apache.roller.util.cache.Cache;
43 import org.apache.roller.util.cache.CacheHandler;
44 import org.apache.roller.util.cache.CacheManager;
45 import org.apache.roller.util.cache.ExpiringCacheEntry;
46
47
48 /**
49  * Cache for site-wide weblog content.
50  */

51 public class SiteWideCache implements CacheHandler {
52     
53     private static Log log = LogFactory.getLog(SiteWideCache.class);
54     
55     // a unique identifier for this cache, this is used as the prefix for
56
// roller config properties that apply to this cache
57
public static final String JavaDoc CACHE_ID = "cache.sitewide";
58     
59     // keep cached content
60
private boolean cacheEnabled = true;
61     private Cache contentCache = null;
62     
63     // keep a cached version of last expired time
64
private ExpiringCacheEntry lastUpdateTime = null;
65     private long timeout = 15 * 60 * 1000;
66     
67     // reference to our singleton instance
68
private static SiteWideCache singletonInstance = new SiteWideCache();
69     
70     
71     private SiteWideCache() {
72         
73         cacheEnabled = RollerConfig.getBooleanProperty(CACHE_ID+".enabled");
74         
75         Map JavaDoc cacheProps = new HashMap JavaDoc();
76         cacheProps.put("id", CACHE_ID);
77         Enumeration JavaDoc allProps = RollerConfig.keys();
78         String JavaDoc prop = null;
79         while(allProps.hasMoreElements()) {
80             prop = (String JavaDoc) allProps.nextElement();
81             
82             // we are only interested in props for this cache
83
if(prop.startsWith(CACHE_ID+".")) {
84                 cacheProps.put(prop.substring(CACHE_ID.length()+1),
85                         RollerConfig.getProperty(prop));
86             }
87         }
88         
89         log.info(cacheProps);
90         
91         if(cacheEnabled) {
92             contentCache = CacheManager.constructCache(this, cacheProps);
93         } else {
94             log.warn("Caching has been DISABLED");
95         }
96     }
97     
98     
99     public static SiteWideCache getInstance() {
100         return singletonInstance;
101     }
102     
103     
104     public Object JavaDoc get(String JavaDoc key) {
105         
106         if(!cacheEnabled)
107             return null;
108         
109         Object JavaDoc 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 JavaDoc key, Object JavaDoc value) {
122         
123         if(!cacheEnabled)
124             return;
125         
126         contentCache.put(key, value);
127         log.debug("PUT "+key);
128     }
129
130     
131     public void remove(String JavaDoc key) {
132         
133         if(!cacheEnabled)
134             return;
135         
136         contentCache.remove(key);
137         log.debug("REMOVE "+key);
138     }
139     
140     
141     public void clear() {
142         
143         if(!cacheEnabled)
144             return;
145         
146         contentCache.clear();
147         this.lastUpdateTime = null;
148         log.debug("CLEAR");
149     }
150     
151     
152     public Date JavaDoc getLastModified() {
153         
154         Date JavaDoc lastModified = null;
155         
156         // first try our cached version
157
if(this.lastUpdateTime != null) {
158             lastModified = (Date JavaDoc) this.lastUpdateTime.getValue();
159         }
160         
161         // still null, we need to get a fresh value
162
if(lastModified == null) {
163             lastModified = new Date JavaDoc();
164             this.lastUpdateTime = new ExpiringCacheEntry(lastModified, this.timeout);
165         }
166         
167         return lastModified;
168     }
169     
170     
171     /**
172      * Generate a cache key from a parsed weblog page request.
173      * This generates a key of the form ...
174      *
175      * <handle>/<ctx>[/anchor][/language][/user]
176      * or
177      * <handle>/<ctx>[/weblogPage][/date][/category][/language][/user]
178      *
179      *
180      * examples ...
181      *
182      * foo/en
183      * foo/entry_anchor
184      * foo/20051110/en
185      * foo/MyCategory/en/user=myname
186      *
187      */

188     public String JavaDoc generateKey(WeblogPageRequest pageRequest) {
189         
190         StringBuffer JavaDoc key = new StringBuffer JavaDoc();
191         
192         key.append(this.CACHE_ID).append(":");
193         key.append("page/");
194         key.append(pageRequest.getWeblogHandle());
195         
196         if(pageRequest.getWeblogAnchor() != null) {
197             String JavaDoc anchor = null;
198             try {
199                 // may contain spaces or other bad chars
200
anchor = URLEncoder.encode(pageRequest.getWeblogAnchor(), "UTF-8");
201             } catch(UnsupportedEncodingException JavaDoc ex) {
202                 // ignored
203
}
204             
205             key.append("/entry/").append(anchor);
206         } else {
207             
208             if(pageRequest.getWeblogPageName() != null) {
209                 key.append("/page/").append(pageRequest.getWeblogPageName());
210             }
211             
212             if(pageRequest.getWeblogDate() != null) {
213                 key.append("/").append(pageRequest.getWeblogDate());
214             }
215             
216             if(pageRequest.getWeblogCategoryName() != null) {
217                 String JavaDoc cat = null;
218                 try {
219                     // may contain spaces or other bad chars
220
cat = URLEncoder.encode(pageRequest.getWeblogCategoryName(), "UTF-8");
221                 } catch(UnsupportedEncodingException JavaDoc ex) {
222                     // ignored
223
}
224                 
225                 key.append("/").append(cat);
226             }
227         }
228         
229         if(pageRequest.getLocale() != null) {
230             key.append("/").append(pageRequest.getLocale());
231         }
232         
233         // add page number when applicable
234
if(pageRequest.getWeblogAnchor() == null) {
235             key.append("/page=").append(pageRequest.getPageNum());
236         }
237         
238         // add login state
239
if(pageRequest.getAuthenticUser() != null) {
240             key.append("/user=").append(pageRequest.getAuthenticUser());
241         }
242         
243         // we allow for arbitrary query params for custom pages
244
if(pageRequest.getCustomParams().size() > 0) {
245             String JavaDoc queryString = paramsToString(pageRequest.getCustomParams());
246             
247             key.append("/qp=").append(queryString);
248         }
249
250         return key.toString();
251     }
252     
253     
254     /**
255      * Generate a cache key from a parsed weblog feed request.
256      * This generates a key of the form ...
257      *
258      * <handle>/<type>/<format>/[/category][/language][/excerpts]
259      *
260      * examples ...
261      *
262      * foo/entries/rss/en
263      * foo/comments/rss/MyCategory/en
264      * foo/entries/atom/en/excerpts
265      *
266      */

267     public String JavaDoc generateKey(WeblogFeedRequest feedRequest) {
268         
269         StringBuffer JavaDoc key = new StringBuffer JavaDoc();
270         
271         key.append(this.CACHE_ID).append(":");
272         key.append("feed/");
273         key.append(feedRequest.getWeblogHandle());
274         
275         key.append("/").append(feedRequest.getType());
276         key.append("/").append(feedRequest.getFormat());
277         
278         if(feedRequest.getWeblogCategoryName() != null) {
279             String JavaDoc cat = feedRequest.getWeblogCategoryName();
280             try {
281                 cat = URLEncoder.encode(cat, "UTF-8");
282             } catch (UnsupportedEncodingException JavaDoc ex) {
283                 // should never happen, utf-8 is always supported
284
}
285             
286             key.append("/").append(cat);
287         }
288         
289         if(feedRequest.getLocale() != null) {
290             key.append("/").append(feedRequest.getLocale());
291         }
292         
293         if(feedRequest.isExcerpts()) {
294             key.append("/excerpts");
295         }
296         
297         return key.toString();
298     }
299     
300     
301     /**
302      * A weblog entry has changed.
303      */

304     public void invalidate(WeblogEntryData entry) {
305         
306         if(!cacheEnabled)
307             return;
308         
309         this.contentCache.clear();
310         this.lastUpdateTime = null;
311     }
312     
313     
314     /**
315      * A weblog has changed.
316      */

317     public void invalidate(WebsiteData website) {
318         
319         if(!cacheEnabled)
320             return;
321         
322         this.contentCache.clear();
323         this.lastUpdateTime = null;
324     }
325     
326     
327     /**
328      * A bookmark has changed.
329      */

330     public void invalidate(BookmarkData bookmark) {
331         if(RollerRuntimeConfig.isSiteWideWeblog(bookmark.getWebsite().getHandle())) {
332             invalidate(bookmark.getWebsite());
333         }
334     }
335     
336     
337     /**
338      * A folder has changed.
339      */

340     public void invalidate(FolderData folder) {
341         if(RollerRuntimeConfig.isSiteWideWeblog(folder.getWebsite().getHandle())) {
342             invalidate(folder.getWebsite());
343         }
344     }
345     
346     
347     /**
348      * A comment has changed.
349      */

350     public void invalidate(CommentData comment) {
351         if(RollerRuntimeConfig.isSiteWideWeblog(comment.getWeblogEntry().getWebsite().getHandle())) {
352             invalidate(comment.getWeblogEntry().getWebsite());
353         }
354     }
355     
356     
357     /**
358      * A referer has changed.
359      */

360     public void invalidate(RefererData referer) {
361         // ignored
362
}
363     
364     
365     /**
366      * A user profile has changed.
367      */

368     public void invalidate(UserData user) {
369         // ignored
370
}
371     
372     
373     /**
374      * A category has changed.
375      */

376     public void invalidate(WeblogCategoryData category) {
377         if(RollerRuntimeConfig.isSiteWideWeblog(category.getWebsite().getHandle())) {
378             invalidate(category.getWebsite());
379         }
380     }
381     
382     
383     /**
384      * A weblog template has changed.
385      */

386     public void invalidate(WeblogTemplate template) {
387         if(RollerRuntimeConfig.isSiteWideWeblog(template.getWebsite().getHandle())) {
388             invalidate(template.getWebsite());
389         }
390     }
391     
392     
393     private String JavaDoc paramsToString(Map JavaDoc map) {
394         
395         if(map == null) {
396             return null;
397         }
398         
399         StringBuffer JavaDoc string = new StringBuffer JavaDoc();
400         
401         String JavaDoc key = null;
402         String JavaDoc[] value = null;
403         Iterator JavaDoc keys = map.keySet().iterator();
404         while(keys.hasNext()) {
405             key = (String JavaDoc) keys.next();
406             value = (String JavaDoc[]) map.get(key);
407             
408             if(value != null) {
409                 string.append(",").append(key).append("=").append(value[0]);
410             }
411         }
412         
413         return Utilities.toBase64(string.toString().substring(1).getBytes());
414     }
415     
416 }
417
Popular Tags