View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.jetspeed.cache.impl;
19  
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.Map;
24  import java.util.StringTokenizer;
25  
26  import net.sf.ehcache.Cache;
27  import net.sf.ehcache.Ehcache;
28  import net.sf.ehcache.Element;
29  
30  import org.apache.jetspeed.cache.CacheElement;
31  import org.apache.jetspeed.cache.ContentCacheElement;
32  import org.apache.jetspeed.cache.ContentCacheKey;
33  import org.apache.jetspeed.cache.ContentCacheKeyGenerator;
34  import org.apache.jetspeed.cache.JetspeedCache;
35  import org.apache.jetspeed.cache.JetspeedCacheEventListener;
36  import org.apache.jetspeed.cache.JetspeedContentCache;
37  import org.apache.jetspeed.decoration.Theme;
38  import org.apache.jetspeed.om.page.ContentPage;
39  import org.apache.jetspeed.request.RequestContext;
40  
41  /***
42   * Wrapper around actual cache implementation
43   * 
44   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
45   * @version $Id: $
46   */
47  public class EhDecorationContentCacheImpl extends EhCacheImpl implements JetspeedContentCache, JetspeedCacheEventListener
48  {
49  
50  	JetspeedCache preferenceCache = null;
51      ContentCacheKeyGenerator keyGenerator = null;    
52  
53      public EhDecorationContentCacheImpl(Ehcache ehcache, JetspeedCache preferenceCache, ContentCacheKeyGenerator keyGenerator)
54      {
55          this(ehcache);
56          this.preferenceCache = preferenceCache;
57          this.keyGenerator = keyGenerator;
58          preferenceCache.addEventListener(this,false); //only listen to remote events
59      }
60      
61      public EhDecorationContentCacheImpl(Ehcache ehcache, JetspeedCache preferenceCache)
62      {
63          this(ehcache);
64          this.preferenceCache = preferenceCache;
65          preferenceCache.addEventListener(this,false); //only listen to remote events
66      }
67          
68      public EhDecorationContentCacheImpl(Ehcache ehcache)
69      {
70          super(ehcache);
71      }
72  
73      public EhDecorationContentCacheImpl(Cache ehcache, ContentCacheKeyGenerator keyGenerator)
74      {
75          this(ehcache);
76          this.keyGenerator = keyGenerator;
77      }
78      
79  
80  	public void notifyElementAdded(JetspeedCache cache, boolean local, Object key, Object element)
81  	{
82  	}
83  
84  	public void notifyElementChanged(JetspeedCache cache, boolean local, Object key, Object element)
85  	{
86  	}
87  
88  	public void notifyElementEvicted(JetspeedCache cache, boolean local, Object key, Object element)
89  	{
90  	}
91  
92  	public void notifyElementExpired(JetspeedCache cache, boolean local, Object key, Object element)
93  	{
94  		notifyElementRemoved(cache,local,key,element);
95  	}
96  
97  
98      public static final String KEY_THEME_KEY = 
99          EhDecorationContentCacheElementImpl.KEY_SEPARATOR + "theme" + EhDecorationContentCacheElementImpl.KEY_SEPARATOR ;
100 	public static final int KEY_THEME_KEY_LENGTH = KEY_THEME_KEY.length();
101     
102 	public void notifyElementRemoved(JetspeedCache cache, boolean local,
103             Object key, Object element)
104     {
105         if (local) return; // not interested in local changes
106 
107         // System.out.println("notifying DecorationContent that element " +
108         // key.toString() + " has been removed");
109         if (!(key instanceof String)) return;
110         String s = (String) key;
111         if (!(s.startsWith(KEY_THEME_KEY))) return;
112         StringTokenizer st = new StringTokenizer(s,
113                 EhDecorationContentCacheElementImpl.KEY_SEPARATOR);
114         int count = 0;
115         String te = null;
116         String user = null;
117         while (st.hasMoreTokens())
118         {
119             String temp = st.nextToken();
120             switch (count)
121             {
122             case 0:
123                 break;
124             case 1:
125                 te = temp; 
126                 break;
127             case 2:
128                 user = temp;
129                 break;
130             }
131             count++;
132             if (count > 2) break;
133         }
134         if (te != null)
135         {
136             removeUserEntry(user, "theme", te);     
137         }
138     }
139 
140     void removeUserEntry(String username, String pipeline, String windowId)
141     {        
142         ContentCacheKey key = keyGenerator.createUserCacheKey(username, pipeline, windowId);
143         if (ehcache.remove(key.getKey()))
144         {
145             Element userElement = ehcache.get(username);
146                 
147             if (userElement != null)
148             {
149                 Map map = (Map)userElement.getObjectValue();
150                 if (map != null)
151                 {
152                     map.remove(windowId);
153                 }
154             }
155         }
156     }
157     
158     public CacheElement get(Object key)
159     {
160         ContentCacheKey cckey = (ContentCacheKey)key;
161         Element element = ehcache.get(cckey.getKey());
162         if (element == null)
163             return null;
164         return new EhDecorationContentCacheElementImpl(element, cckey);
165     }
166 
167     public int getTimeToIdleSeconds()
168     {
169         return (int)ehcache.getTimeToIdleSeconds();
170     }
171 
172     public int getTimeToLiveSeconds()
173     {
174         return (int)ehcache.getTimeToLiveSeconds();
175     }
176 
177     public boolean isKeyInCache(Object key)
178     {
179         ContentCacheKey cckey = (ContentCacheKey)key;        
180         return ehcache.isKeyInCache(cckey.getKey());
181     }
182 
183     public void put(CacheElement element)
184     {
185         ContentCacheElement ccElement = (ContentCacheElement)element;
186         EhDecorationContentCacheElementImpl impl = (EhDecorationContentCacheElementImpl)element;
187         Element ehl = impl.getImplElement();        
188         String userKey = ccElement.getContentCacheKey().getSessionId();
189         if (userKey == null)
190         {
191             userKey = ccElement.getContentCacheKey().getUsername();
192         }
193         String windowId = ccElement.getContentCacheKey().getWindowId();
194         try
195         {
196             ehcache.put(ehl);
197         }
198         catch (Exception e)
199         {
200             e.printStackTrace();
201         }
202         Element userElement = ehcache.get(userKey);
203         if (userElement == null)
204         {
205             Map map = Collections.synchronizedMap(new HashMap());
206             map.put(windowId, ccElement.getContentCacheKey());
207             userElement = new Element(userKey, map);
208             ehcache.put(userElement);           
209         }
210         else
211         {
212             Map map = (Map)userElement.getObjectValue();
213             map.put(windowId, ccElement.getContentCacheKey());
214         }        
215     }
216     
217     public CacheElement createElement(Object key, Object content)
218     {
219         ContentCacheKey cckey = (ContentCacheKey)key;
220         Element cachedElement = new Element(cckey.getKey(), content);        
221         return new EhDecorationContentCacheElementImpl(cachedElement, cckey);
222     }
223 
224     public boolean remove(Object key)
225     {
226         CacheElement element = this.get(key);
227         boolean removed = false;
228         if (element == null)
229             return false;
230         
231         ContentCacheElement ccElement = (ContentCacheElement)element;
232         EhDecorationContentCacheElementImpl impl = (EhDecorationContentCacheElementImpl)element;
233         Element ehl = impl.getImplElement();        
234         String userKey = ccElement.getContentCacheKey().getSessionId();
235         if (userKey == null)
236         {
237             userKey = ccElement.getContentCacheKey().getUsername();
238         }        
239         String windowId = ccElement.getContentCacheKey().getWindowId();        
240         removed = ehcache.remove(ccElement.getContentCacheKey().getKey());
241         Element userElement = ehcache.get(userKey);
242         if (userElement != null)
243         {
244             Map map = (Map)userElement.getObjectValue();
245             if (map != null)
246             {
247                 map.remove(windowId);
248             }
249         }
250         return removed;
251     }
252         
253     public void evictContentForUser(String username)
254     {
255         Element userElement = saveGet(username);
256         if (userElement != null)
257         {
258             Map map = (Map)userElement.getObjectValue();
259             if (map != null)
260             {
261                 Iterator entities = map.values().iterator();
262                 while (entities.hasNext())
263                 {
264                     ContentCacheKey ccKey = (ContentCacheKey)entities.next();
265                     ehcache.remove(ccKey.getKey());
266                 }
267             }
268             ehcache.remove(username);
269         }
270     }
271 
272     public void evictContentForSession(String session)
273     {
274         Element userElement = saveGet(session);
275         if (userElement != null)
276         {
277             Map map = (Map)userElement.getObjectValue();
278             if (map != null)
279             {
280                 Iterator entities = map.values().iterator();
281                 while (entities.hasNext())
282                 {
283                     ContentCacheKey ccKey = (ContentCacheKey)entities.next();
284                     ehcache.remove(ccKey.getKey());
285                 }
286             }
287             ehcache.remove(session);
288         }
289     }
290     
291     public void clear()
292     {
293         ehcache.removeAll();
294     }
295         
296     public ContentCacheKey createCacheKey(RequestContext context, String windowId)
297     {
298         return this.keyGenerator.createCacheKey(context, windowId);        
299     }
300     
301     protected Element saveGet(Object key)
302     {
303         try
304         {
305             return ehcache.get(key);
306         }
307         catch (IllegalStateException ise)
308         {
309             // can be thrown during shutdown for instance
310             return null;
311         }
312     }
313     
314     public String createSessionKey(RequestContext context)
315     {
316         boolean isAjaxRequest = (context == null);
317         String mode = isAjaxRequest ? "-d-" : "-p-";
318         String user = context.getRequest().getRemoteUser();
319         if (user == null)
320             user = "guest";        
321         return user + mode + context.getPage().getId();        
322     }
323     
324     public void invalidate(RequestContext context)
325     {
326         ContentPage page = context.getPage();
327         ContentCacheKey themeContentCacheKey = createCacheKey(context, page.getId());
328         CacheElement themeCacheElem = get(themeContentCacheKey);
329         
330         if (themeCacheElem != null)
331         {
332             Theme theme = (Theme) themeCacheElem.getContent();
333             theme.setInvalidated(true);
334         }
335     }
336 }