001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jetspeed.cache.impl;
019:
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.StringTokenizer;
025:
026: import net.sf.ehcache.Ehcache;
027: import net.sf.ehcache.Element;
028:
029: import org.apache.jetspeed.cache.CacheElement;
030: import org.apache.jetspeed.cache.ContentCacheElement;
031: import org.apache.jetspeed.cache.ContentCacheKey;
032: import org.apache.jetspeed.cache.ContentCacheKeyGenerator;
033: import org.apache.jetspeed.cache.JetspeedCache;
034: import org.apache.jetspeed.cache.JetspeedCacheEventListener;
035: import org.apache.jetspeed.cache.JetspeedContentCache;
036: import org.apache.jetspeed.decoration.Theme;
037: import org.apache.jetspeed.request.RequestContext;
038:
039: /**
040: * Wrapper around actual cache implementation
041: *
042: * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
043: * @version $Id: $
044: */
045: public class EhPortletContentCacheImpl extends EhCacheImpl implements
046: JetspeedContentCache, JetspeedCacheEventListener {
047:
048: JetspeedCache preferenceCache = null;
049: ContentCacheKeyGenerator keyGenerator = null;
050:
051: public EhPortletContentCacheImpl(Ehcache ehcache,
052: JetspeedCache preferenceCache,
053: ContentCacheKeyGenerator keyGenerator) {
054: this (ehcache);
055: this .preferenceCache = preferenceCache;
056: this .keyGenerator = keyGenerator;
057: preferenceCache.addEventListener(this , false); //only listen to remote events
058: }
059:
060: public EhPortletContentCacheImpl(Ehcache ehcache,
061: JetspeedCache preferenceCache) {
062: this (ehcache);
063: this .preferenceCache = preferenceCache;
064: preferenceCache.addEventListener(this , false); //only listen to remote events
065: }
066:
067: public EhPortletContentCacheImpl(Ehcache ehcache) {
068: super (ehcache);
069: }
070:
071: public EhPortletContentCacheImpl(Ehcache ehcache,
072: ContentCacheKeyGenerator keyGenerator) {
073: this (ehcache);
074: this .keyGenerator = keyGenerator;
075: }
076:
077: public void notifyElementAdded(JetspeedCache cache, boolean local,
078: Object key, Object element) {
079: }
080:
081: public void notifyElementChanged(JetspeedCache cache,
082: boolean local, Object key, Object element) {
083: }
084:
085: public void notifyElementEvicted(JetspeedCache cache,
086: boolean local, Object key, Object element) {
087: }
088:
089: public void notifyElementExpired(JetspeedCache cache,
090: boolean local, Object key, Object element) {
091: notifyElementRemoved(cache, local, key, element);
092: }
093:
094: public static final String KEY_ENTITY_KEY = EhPortletContentCacheElementImpl.KEY_SEPARATOR
095: + "portlet_entity"
096: + EhPortletContentCacheElementImpl.KEY_SEPARATOR;
097: public static final int KEY_ENTITY_KEY_LENGTH = KEY_ENTITY_KEY
098: .length();
099:
100: public void notifyElementRemoved(JetspeedCache cache,
101: boolean local, Object key, Object element) {
102: if (local)
103: return; // not interested in local changes
104:
105: // System.out.println("notifying PortletContent that element " +
106: // key.toString() + " has been removed");
107: if (!(key instanceof String))
108: return;
109: String s = (String) key;
110: if (!(s.startsWith(KEY_ENTITY_KEY)))
111: return;
112: StringTokenizer st = new StringTokenizer(s,
113: EhPortletContentCacheElementImpl.KEY_SEPARATOR);
114: int count = 0;
115: String pe = null;
116: String user = null;
117: while (st.hasMoreTokens()) {
118: String temp = st.nextToken();
119: switch (count) {
120: case 0:
121: break;
122: case 1:
123: pe = temp;
124: break;
125: case 2:
126: user = temp;
127: break;
128: }
129: count++;
130: if (count > 2)
131: break;
132: }
133: if ((pe != null) && (user != null)) {
134: removeUserEntry(user, "portal", pe);
135: removeUserEntry(user, "desktop", pe);
136: }
137: }
138:
139: void removeUserEntry(String username, String pipeline,
140: String windowId) {
141: ContentCacheKey key = keyGenerator.createUserCacheKey(username,
142: pipeline, windowId);
143: if (ehcache.remove(key.getKey())) {
144: Element userElement = ehcache.get(username);
145:
146: if (userElement != null) {
147: Map map = (Map) userElement.getObjectValue();
148: if (map != null) {
149: map.remove(windowId);
150: }
151: }
152: }
153: }
154:
155: public CacheElement get(Object key) {
156: ContentCacheKey cckey = (ContentCacheKey) key;
157: Element element = ehcache.get(cckey.getKey());
158: if (element == null)
159: return null;
160: return new EhPortletContentCacheElementImpl(element, cckey);
161: }
162:
163: public int getTimeToIdleSeconds() {
164: return (int) ehcache.getTimeToIdleSeconds();
165: }
166:
167: public int getTimeToLiveSeconds() {
168: return (int) ehcache.getTimeToLiveSeconds();
169: }
170:
171: public boolean isKeyInCache(Object key) {
172: ContentCacheKey cckey = (ContentCacheKey) key;
173: return ehcache.isKeyInCache(cckey.getKey());
174: }
175:
176: public void put(CacheElement element) {
177: ContentCacheElement ccElement = (ContentCacheElement) element;
178: EhPortletContentCacheElementImpl impl = (EhPortletContentCacheElementImpl) element;
179: Element ehl = impl.getImplElement();
180: String userKey = ccElement.getContentCacheKey().getSessionId();
181: if (userKey == null) {
182: userKey = ccElement.getContentCacheKey().getUsername();
183: }
184: String windowId = ccElement.getContentCacheKey().getWindowId();
185: try {
186: ehcache.put(ehl);
187: } catch (Exception e) {
188: e.printStackTrace();
189: }
190: Element userElement = ehcache.get(userKey);
191: if (userElement == null) {
192: Map map = Collections.synchronizedMap(new HashMap());
193: map.put(windowId, ccElement.getContentCacheKey());
194: userElement = new Element(userKey, map);
195: ehcache.put(userElement);
196: } else {
197: Map map = (Map) userElement.getObjectValue();
198: map.put(windowId, ccElement.getContentCacheKey());
199: }
200: }
201:
202: public CacheElement createElement(Object key, Object content) {
203: ContentCacheKey cckey = (ContentCacheKey) key;
204: Element cachedElement = new Element(cckey.getKey(), content);
205: return new EhPortletContentCacheElementImpl(cachedElement,
206: cckey);
207: }
208:
209: public boolean remove(Object key) {
210: CacheElement element = this .get(key);
211: boolean removed = false;
212: if (element == null)
213: return false;
214:
215: ContentCacheElement ccElement = (ContentCacheElement) element;
216: EhPortletContentCacheElementImpl impl = (EhPortletContentCacheElementImpl) element;
217: Element ehl = impl.getImplElement();
218: String userKey = ccElement.getContentCacheKey().getSessionId();
219: if (userKey == null) {
220: userKey = ccElement.getContentCacheKey().getUsername();
221: }
222: String windowId = ccElement.getContentCacheKey().getWindowId();
223: removed = ehcache.remove(ccElement.getContentCacheKey()
224: .getKey());
225: Element userElement = ehcache.get(userKey);
226: if (userElement != null) {
227: Map map = (Map) userElement.getObjectValue();
228: if (map != null) {
229: map.remove(windowId);
230: }
231: }
232: return removed;
233: }
234:
235: public void evictContentForUser(String username) {
236: Element userElement = saveGet(username);
237: if (userElement != null) {
238: Map map = (Map) userElement.getObjectValue();
239: if (map != null) {
240: Iterator entities = map.values().iterator();
241: while (entities.hasNext()) {
242: ContentCacheKey ccKey = (ContentCacheKey) entities
243: .next();
244: ehcache.remove(ccKey.getKey());
245: }
246: }
247: ehcache.remove(username);
248: }
249: }
250:
251: public void evictContentForSession(String session) {
252: Element userElement = saveGet(session);
253: if (userElement != null) {
254: Map map = (Map) userElement.getObjectValue();
255: if (map != null) {
256: Iterator entities = map.values().iterator();
257: while (entities.hasNext()) {
258: ContentCacheKey ccKey = (ContentCacheKey) entities
259: .next();
260: ehcache.remove(ccKey.getKey());
261: }
262: }
263: ehcache.remove(session);
264: }
265: }
266:
267: public void clear() {
268: ehcache.removeAll();
269: }
270:
271: public ContentCacheKey createCacheKey(RequestContext context,
272: String windowId) {
273: return this .keyGenerator.createCacheKey(context, windowId);
274: }
275:
276: protected Element saveGet(Object key) {
277: try {
278: return ehcache.get(key);
279: } catch (IllegalStateException ise) {
280: // can be thrown during shutdown for instance
281: return null;
282: }
283: }
284:
285: public String createSessionKey(RequestContext context) {
286: boolean isAjaxRequest = (context == null);
287: String mode = isAjaxRequest ? "-d-" : "-p-";
288: String user = context.getRequest().getRemoteUser();
289: if (user == null)
290: user = "guest";
291: return user + mode + context.getPage().getId();
292: }
293:
294: public void invalidate(RequestContext context) {
295: String themeCacheKey = createSessionKey(context);
296: Theme theme = (Theme) context.getRequest().getSession()
297: .getAttribute(themeCacheKey);
298: if (theme != null) {
299: theme.setInvalidated(true);
300: }
301: }
302: }
|