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.Ehcache;
27  import net.sf.ehcache.Element;
28  
29  import org.apache.jetspeed.cache.CacheElement;
30  import org.apache.jetspeed.cache.ContentCacheElement;
31  import org.apache.jetspeed.cache.ContentCacheKey;
32  import org.apache.jetspeed.cache.ContentCacheKeyGenerator;
33  import org.apache.jetspeed.cache.JetspeedCache;
34  import org.apache.jetspeed.cache.JetspeedCacheEventListener;
35  import org.apache.jetspeed.cache.JetspeedContentCache;
36  import org.apache.jetspeed.decoration.Theme;
37  import org.apache.jetspeed.request.RequestContext;
38  
39  /***
40   * Wrapper around actual cache implementation
41   * 
42   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
43   * @version $Id: $
44   */
45  public class EhPortletContentCacheImpl extends EhCacheImpl implements JetspeedContentCache, JetspeedCacheEventListener
46  {
47  
48  	JetspeedCache preferenceCache = null;
49      ContentCacheKeyGenerator keyGenerator = null;    
50  
51      public EhPortletContentCacheImpl(Ehcache ehcache, JetspeedCache preferenceCache, ContentCacheKeyGenerator keyGenerator)
52      {
53          this(ehcache);
54          this.preferenceCache = preferenceCache;
55          this.keyGenerator = keyGenerator;
56          preferenceCache.addEventListener(this,false); //only listen to remote events
57      }
58      
59      public EhPortletContentCacheImpl(Ehcache ehcache, JetspeedCache preferenceCache)
60      {
61          this(ehcache);
62          this.preferenceCache = preferenceCache;
63          preferenceCache.addEventListener(this,false); //only listen to remote events
64      }
65          
66      public EhPortletContentCacheImpl(Ehcache ehcache)
67      {
68          super(ehcache);
69      }
70  
71      public EhPortletContentCacheImpl(Ehcache ehcache, ContentCacheKeyGenerator keyGenerator)
72      {
73          this(ehcache);
74          this.keyGenerator = keyGenerator;
75      }
76      
77  
78  	public void notifyElementAdded(JetspeedCache cache, boolean local, Object key, Object element)
79  	{
80  	}
81  
82  	public void notifyElementChanged(JetspeedCache cache, boolean local, Object key, Object element)
83  	{
84  	}
85  
86  	public void notifyElementEvicted(JetspeedCache cache, boolean local, Object key, Object element)
87  	{
88  	}
89  
90  	public void notifyElementExpired(JetspeedCache cache, boolean local, Object key, Object element)
91  	{
92  		notifyElementRemoved(cache,local,key,element);
93  	}
94  
95  
96      public static final String KEY_ENTITY_KEY = 
97          EhPortletContentCacheElementImpl.KEY_SEPARATOR + "portlet_entity" + EhPortletContentCacheElementImpl.KEY_SEPARATOR ;
98  	public static final int KEY_ENTITY_KEY_LENGTH = KEY_ENTITY_KEY.length();
99      
100 	public void notifyElementRemoved(JetspeedCache cache, boolean local,
101             Object key, Object element)
102     {
103         if (local) 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)) return;
108         String s = (String) key;
109         if (!(s.startsWith(KEY_ENTITY_KEY))) return;
110         StringTokenizer st = new StringTokenizer(s,
111                 EhPortletContentCacheElementImpl.KEY_SEPARATOR);
112         int count = 0;
113         String pe = null;
114         String user = null;
115         while (st.hasMoreTokens())
116         {
117             String temp = st.nextToken();
118             switch (count)
119             {
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) break;
131         }
132         if ((pe != null) && (user != null))
133         {
134             removeUserEntry(user, "portal", pe);     
135             removeUserEntry(user, "desktop", pe);
136         }
137     }
138 
139     void removeUserEntry(String username, String pipeline, String windowId)
140     {        
141         ContentCacheKey key = keyGenerator.createUserCacheKey(username, pipeline, windowId);
142         if (ehcache.remove(key.getKey()))
143         {
144             Element userElement = ehcache.get(username);
145                 
146             if (userElement != null)
147             {
148                 Map map = (Map)userElement.getObjectValue();
149                 if (map != null)
150                 {
151                     map.remove(windowId);
152                 }
153             }
154         }
155     }
156     
157     public CacheElement get(Object key)
158     {
159         ContentCacheKey cckey = (ContentCacheKey)key;
160         Element element = ehcache.get(cckey.getKey());
161         if (element == null)
162             return null;
163         return new EhPortletContentCacheElementImpl(element, cckey);
164     }
165 
166     public int getTimeToIdleSeconds()
167     {
168         return (int)ehcache.getTimeToIdleSeconds();
169     }
170 
171     public int getTimeToLiveSeconds()
172     {
173         return (int)ehcache.getTimeToLiveSeconds();
174     }
175 
176     public boolean isKeyInCache(Object key)
177     {
178         ContentCacheKey cckey = (ContentCacheKey)key;        
179         return ehcache.isKeyInCache(cckey.getKey());
180     }
181 
182     public void put(CacheElement element)
183     {
184         ContentCacheElement ccElement = (ContentCacheElement)element;
185         EhPortletContentCacheElementImpl impl = (EhPortletContentCacheElementImpl)element;
186         Element ehl = impl.getImplElement();        
187         String userKey = ccElement.getContentCacheKey().getSessionId();
188         if (userKey == null)
189         {
190             userKey = ccElement.getContentCacheKey().getUsername();
191         }
192         String windowId = ccElement.getContentCacheKey().getWindowId();
193         try
194         {
195             ehcache.put(ehl);
196         }
197         catch (Exception e)
198         {
199             e.printStackTrace();
200         }
201         Element userElement = ehcache.get(userKey);
202         if (userElement == null)
203         {
204             Map map = Collections.synchronizedMap(new HashMap());
205             map.put(windowId, ccElement.getContentCacheKey());
206             userElement = new Element(userKey, map);
207             ehcache.put(userElement);           
208         }
209         else
210         {
211             Map map = (Map)userElement.getObjectValue();
212             map.put(windowId, ccElement.getContentCacheKey());
213         }        
214     }
215     
216     public CacheElement createElement(Object key, Object content)
217     {
218         ContentCacheKey cckey = (ContentCacheKey)key;
219         Element cachedElement = new Element(cckey.getKey(), content);        
220         return new EhPortletContentCacheElementImpl(cachedElement, cckey);
221     }
222 
223     public boolean remove(Object key)
224     {
225         CacheElement element = this.get(key);
226         boolean removed = false;
227         if (element == null)
228             return false;
229         
230         ContentCacheElement ccElement = (ContentCacheElement)element;
231         EhPortletContentCacheElementImpl impl = (EhPortletContentCacheElementImpl)element;
232         Element ehl = impl.getImplElement();        
233         String userKey = ccElement.getContentCacheKey().getSessionId();
234         if (userKey == null)
235         {
236             userKey = ccElement.getContentCacheKey().getUsername();
237         }        
238         String windowId = ccElement.getContentCacheKey().getWindowId();        
239         removed = ehcache.remove(ccElement.getContentCacheKey().getKey());
240         Element userElement = ehcache.get(userKey);
241         if (userElement != null)
242         {
243             Map map = (Map)userElement.getObjectValue();
244             if (map != null)
245             {
246                 map.remove(windowId);
247             }
248         }
249         return removed;
250     }
251         
252     public void evictContentForUser(String username)
253     {
254         Element userElement = saveGet(username);
255         if (userElement != null)
256         {
257             Map map = (Map)userElement.getObjectValue();
258             if (map != null)
259             {
260                 Iterator entities = map.values().iterator();
261                 while (entities.hasNext())
262                 {
263                     ContentCacheKey ccKey = (ContentCacheKey)entities.next();
264                     ehcache.remove(ccKey.getKey());
265                 }
266             }
267             ehcache.remove(username);
268         }
269     }
270 
271     public void evictContentForSession(String session)
272     {
273         Element userElement = saveGet(session);
274         if (userElement != null)
275         {
276             Map map = (Map)userElement.getObjectValue();
277             if (map != null)
278             {
279                 Iterator entities = map.values().iterator();
280                 while (entities.hasNext())
281                 {
282                     ContentCacheKey ccKey = (ContentCacheKey)entities.next();
283                     ehcache.remove(ccKey.getKey());
284                 }
285             }
286             ehcache.remove(session);
287         }
288     }
289     
290     public void clear()
291     {
292         ehcache.removeAll();
293     }
294         
295     public ContentCacheKey createCacheKey(RequestContext context, String windowId)
296     {
297         return this.keyGenerator.createCacheKey(context, windowId);        
298     }
299     
300     protected Element saveGet(Object key)
301     {
302         try
303         {
304             return ehcache.get(key);
305         }
306         catch (IllegalStateException ise)
307         {
308             // can be thrown during shutdown for instance
309             return null;
310         }
311     }
312     
313     public String createSessionKey(RequestContext context)
314     {
315         boolean isAjaxRequest = (context == null);
316         String mode = isAjaxRequest ? "-d-" : "-p-";
317         String user = context.getRequest().getRemoteUser();
318         if (user == null)
319             user = "guest";        
320         return user + mode + context.getPage().getId();        
321     }
322     
323     public void invalidate(RequestContext context)
324     {
325         String themeCacheKey = createSessionKey(context);
326         Theme theme = (Theme)context.getRequest().getSession().getAttribute(themeCacheKey);        
327         if (theme != null)
328         {
329             theme.setInvalidated(true);
330         }
331     }
332 }