001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.ui.rendering.util.cache;
020:
021: import java.io.UnsupportedEncodingException;
022: import java.net.URLEncoder;
023: import java.util.Enumeration;
024: import java.util.HashMap;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.TreeSet;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.roller.config.RollerConfig;
031: import org.apache.roller.ui.rendering.util.WeblogFeedRequest;
032: import org.apache.roller.util.Utilities;
033: import org.apache.roller.util.cache.Cache;
034: import org.apache.roller.util.cache.CacheManager;
035: import org.apache.roller.util.cache.LazyExpiringCacheEntry;
036:
037: /**
038: * Cache for weblog feed content.
039: */
040: public class WeblogFeedCache {
041:
042: private static Log log = LogFactory.getLog(WeblogFeedCache.class);
043:
044: // a unique identifier for this cache, this is used as the prefix for
045: // roller config properties that apply to this cache
046: public static final String CACHE_ID = "cache.weblogfeed";
047:
048: // keep cached content
049: private boolean cacheEnabled = true;
050: private Cache contentCache = null;
051:
052: // reference to our singleton instance
053: private static WeblogFeedCache singletonInstance = new WeblogFeedCache();
054:
055: private WeblogFeedCache() {
056:
057: cacheEnabled = RollerConfig.getBooleanProperty(CACHE_ID
058: + ".enabled");
059:
060: Map cacheProps = new HashMap();
061: cacheProps.put("id", CACHE_ID);
062: Enumeration allProps = RollerConfig.keys();
063: String prop = null;
064: while (allProps.hasMoreElements()) {
065: prop = (String) allProps.nextElement();
066:
067: // we are only interested in props for this cache
068: if (prop.startsWith(CACHE_ID + ".")) {
069: cacheProps.put(prop.substring(CACHE_ID.length() + 1),
070: RollerConfig.getProperty(prop));
071: }
072: }
073:
074: log.info(cacheProps);
075:
076: if (cacheEnabled) {
077: contentCache = CacheManager
078: .constructCache(null, cacheProps);
079: } else {
080: log.warn("Caching has been DISABLED");
081: }
082: }
083:
084: public static WeblogFeedCache getInstance() {
085: return singletonInstance;
086: }
087:
088: public Object get(String key, long lastModified) {
089:
090: if (!cacheEnabled)
091: return null;
092:
093: Object entry = null;
094:
095: LazyExpiringCacheEntry lazyEntry = (LazyExpiringCacheEntry) this .contentCache
096: .get(key);
097: if (lazyEntry != null) {
098: entry = lazyEntry.getValue(lastModified);
099:
100: if (entry != null) {
101: log.debug("HIT " + key);
102: } else {
103: log.debug("HIT-EXPIRED " + key);
104: }
105:
106: } else {
107: log.debug("MISS " + key);
108: }
109:
110: return entry;
111: }
112:
113: public void put(String key, Object value) {
114:
115: if (!cacheEnabled)
116: return;
117:
118: contentCache.put(key, new LazyExpiringCacheEntry(value));
119: log.debug("PUT " + key);
120: }
121:
122: public void remove(String key) {
123:
124: if (!cacheEnabled)
125: return;
126:
127: contentCache.remove(key);
128: log.debug("REMOVE " + key);
129: }
130:
131: public void clear() {
132:
133: if (!cacheEnabled)
134: return;
135:
136: contentCache.clear();
137: log.debug("CLEAR");
138: }
139:
140: /**
141: * Generate a cache key from a parsed weblog feed request.
142: * This generates a key of the form ...
143: *
144: * <handle>/<type>/<format>/[/category][/language][/excerpts]
145: *
146: * examples ...
147: *
148: * foo/entries/rss/en
149: * foo/comments/rss/MyCategory/en
150: * foo/entries/atom/en/excerpts
151: *
152: */
153: public String generateKey(WeblogFeedRequest feedRequest) {
154:
155: StringBuffer key = new StringBuffer();
156:
157: key.append(this .CACHE_ID).append(":");
158: key.append(feedRequest.getWeblogHandle());
159:
160: key.append("/").append(feedRequest.getType());
161: key.append("/").append(feedRequest.getFormat());
162:
163: if (feedRequest.getWeblogCategoryName() != null) {
164: String cat = feedRequest.getWeblogCategoryName();
165: try {
166: cat = URLEncoder.encode(cat, "UTF-8");
167: } catch (UnsupportedEncodingException ex) {
168: // should never happen, utf-8 is always supported
169: }
170:
171: key.append("/").append(cat);
172: }
173:
174: if (feedRequest.getTags() != null
175: && feedRequest.getTags().size() > 0) {
176: Set ordered = new TreeSet(feedRequest.getTags());
177: String[] tags = (String[]) ordered
178: .toArray(new String[ordered.size()]);
179: key.append("/tags/").append(
180: Utilities.stringArrayToString(tags, "+"));
181: }
182:
183: if (feedRequest.getLocale() != null) {
184: key.append("/").append(feedRequest.getLocale());
185: }
186:
187: if (feedRequest.isExcerpts()) {
188: key.append("/excerpts");
189: }
190:
191: return key.toString();
192: }
193:
194: }
|