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  package org.apache.portals.applications.transform.impl;
18  
19  import java.util.Collections;
20  import java.util.Date;
21  import java.util.Iterator;
22  import java.util.LinkedList;
23  import java.util.List;
24  import java.util.Observable;
25  import java.util.TreeMap;
26  
27  import org.apache.portals.applications.transform.Transform;
28  import org.apache.portals.applications.transform.TransformCache;
29  import org.apache.portals.applications.transform.TransformCacheEntry;
30  
31  
32  /***
33   * TransformCacheComponent
34   * 
35   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
36   * @version $Id: MemoryTransformCache.java 517719 2007-03-13 15:05:48Z ate $
37   */
38  public class MemoryTransformCache implements TransformCache
39  {
40      private boolean debug = false;    
41      private int maxSize = 100;    
42      private int evictionPercentage = 10;    
43      private boolean enable = true;
44  
45      private TreeMap cache = null;
46      private Object lock = new Object();
47  
48      /***
49       * Spring constructor injection
50       *  
51       */
52      public MemoryTransformCache(Transform transform, int maxSize, int evictionPercentage, boolean enable, boolean debug)
53      {
54          cache = new TreeMap();
55          this.maxSize = maxSize;
56          this.evictionPercentage = evictionPercentage;
57          
58          transform.getPublisher().addObserver(this);
59      }
60      
61      public int getMaxSize()
62      {
63          return maxSize;
64      }
65  
66      public void setMaxSize(int maxSize)
67      {
68          this.maxSize = maxSize;
69      }
70      
71      public int getEvictionPercentage()
72      {
73          return this.evictionPercentage;
74      }
75      
76      public boolean isEnabled()
77      {
78          return enable;        
79      }
80      
81      public void put(String key, Object document, long timeToLive)
82      {
83          TransformCacheEntry entry = new TransformCacheEntry(key, document, timeToLive);
84          if (cache.size() > getMaxSize())
85          {
86              evict();
87          }
88          synchronized(lock)
89          {
90              cache.put(key, entry);
91          }
92          if (debug)
93          {
94              System.out.println("Transformed content put in cache! Transform: "
95                     + key);
96          }        
97      }
98  
99      /***
100      * The eviction policy will keep n items in the cache, and then start evicting
101      * x items ordered-by least used first. 
102      * n = max size of cache
103      * x = (eviction_percentage/100) * n
104      *
105      */
106     protected void evict()        
107     {
108         if (debug)
109         {
110             System.out.println("Calling evict... cacheSize: "+
111                                cache.size()+" maxSize: "+getMaxSize());
112         }
113         synchronized (lock)
114         {
115             if (this.getMaxSize() >= cache.size())
116             {
117                 return;
118             }
119     
120             List list = new LinkedList( cache.values());
121             Collections.sort(list, this);
122     
123             int count = 0;
124             int limit = (getMaxSize() * getEvictionPercentage())/100 ;
125             if (limit <= 0) limit = 1;
126     
127             for (Iterator it = list.iterator(); it.hasNext(); )
128             {
129                 if (count >= limit)
130                 {
131                     break;
132                 }
133     
134                 TransformCacheEntry entry = (TransformCacheEntry) it.next();
135                 if (debug)
136                 {
137                     System.out.println("Evicting: "+ entry.getKey());
138                 }
139                 cache.remove(entry.getKey());
140                 
141                 count++;
142             }        
143         }
144     }
145     
146     
147     /* (non-Javadoc)
148      * @see org.apache.jetspeed.syndication.services.transform.TransformCacheService#remove(java.lang.String, java.lang.String)
149      */
150     public Object remove(String key)
151     {
152         TransformCacheEntry entry = (TransformCacheEntry)cache.get(key);
153         if (entry == null)
154         {
155             return null;
156         }
157         synchronized(lock)
158         {
159             entry = (TransformCacheEntry)cache.remove(key);
160         }
161         return entry;
162         
163     }
164     
165     /* (non-Javadoc)
166      * @see org.apache.jetspeed.syndication.services.transform.TransformCacheService#get(java.lang.String, java.lang.String)
167      */
168     public TransformCacheEntry get(String key)
169     {
170         TransformCacheEntry entry = (TransformCacheEntry)cache.get(key);
171         if (entry == null)
172         {
173             return null;
174         }
175         long now = new Date().getTime();
176         long lifeTime = entry.getTimeToLive() * 1000;
177         if ((entry.getLastAccessed() + lifeTime) < now)
178         {
179             return null; // expire it
180         }
181         if (debug)
182         {
183             System.out.println("Transformed content found in cache! Transform: "
184                    + key);
185         }
186         return entry;
187     }
188     
189     public Object getDocument(String key)
190     {
191         TransformCacheEntry entry = get(key);
192         if (entry != null)
193         {
194             return entry.getDocument();
195         }
196         return null;
197     }
198     
199     public int compare(Object o1, Object o2)
200     {
201         TransformCacheEntry e1 = (TransformCacheEntry)o1;
202         TransformCacheEntry e2 = (TransformCacheEntry)o2;
203         if (e1.getLastAccessed() < e2.getLastAccessed())
204         {
205             return -1;
206         }
207         else if (e1.getLastAccessed() == e2.getLastAccessed())
208         {
209             return 0;
210         }
211         return 1;
212     }
213     
214     public String constructKey(String url, String stylesheet)
215     {
216         return url + ":" + stylesheet;        
217     }
218 
219     public void clearCache()
220     {
221         cache.clear();
222     }
223     
224     public void update(Observable o, Object arg)
225     {
226         // TODO: write me
227     }
228     
229 }
230