KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > cache > simplecache > SimpleHtmlCache


1 /*
2  * ____.
3  * __/\ ______| |__/\. _______
4  * __ .____| | \ | +----+ \
5  * _______| /--| | | - \ _ | : - \_________
6  * \\______: :---| : : | : | \________>
7  * |__\---\_____________:______: :____|____:_____\
8  * /_____|
9  *
10  * . . . i n j a h i a w e t r u s t . . .
11  *
12  *
13  *
14  * ----- BEGIN LICENSE BLOCK -----
15  * Version: JCSL 1.0
16  *
17  * The contents of this file are subject to the Jahia Community Source License
18  * 1.0 or later (the "License"); you may not use this file except in
19  * compliance with the License. You may obtain a copy of the License at
20  * http://www.jahia.org/license
21  *
22  * Software distributed under the License is distributed on an "AS IS" basis,
23  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24  * for the rights, obligations and limitations governing use of the contents
25  * of the file. The Original and Upgraded Code is the Jahia CMS and Portal
26  * Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
27  * Ltd. owns the copyrights in the portions it created. All Rights Reserved.
28  *
29  * The Shared Modifications are Jahia View Helper.
30  *
31  * The Developer of the Shared Modifications is Jahia Solution Sarl.
32  * Portions created by the Initial Developer are Copyright (C) 2002 by the
33  * Initial Developer. All Rights Reserved.
34  *
35  * Contributor(s):
36  * ??-JUN-2003, Jahia Solutions Sarl, Fulco Houkes : Initial version
37  *
38  * ----- END LICENSE BLOCK -----
39  */

40
41
42 package org.jahia.services.cache.simplecache;
43
44 import org.jahia.exceptions.JahiaInitializationException;
45 import java.io.IOException JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import java.io.File JavaDoc;
48 import org.apache.commons.digester.Digester;
49 import org.apache.commons.digester.Rule;
50 import java.util.Properties JavaDoc;
51 import java.util.ArrayList JavaDoc;
52
53 import org.jahia.services.cache.Cache;
54 import org.jahia.services.cache.HtmlCache;
55 import org.jahia.services.cache.HtmlCacheEntry;
56 import org.jahia.services.cache.JMSHub;
57 import org.jahia.services.htmlcache.UserAgentGroup;
58 import java.util.TreeSet JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.Map JavaDoc;
61 import java.util.HashMap JavaDoc;
62 import org.jahia.settings.SettingsBean;
63
64
65 /** <p>This class implements a cache capable of caching HTML page and associate the pages
66  * to a page identification number and a user name.<p>
67  *
68  * <p>The cached pages can be remove by using either a page identification number or
69  * by specifying a user name. When invalidating pages through the
70  * {@link org.jahia.services.cache.simplecache.SimpleHtmlCache#invalidatePageEntries invalidatePageEntries}
71  * method, all the pages holding the specified page ID will be removed, regardless of
72  * the related user name. The same is achieved by using the
73  * {@link org.jahia.services.cache.simplecache.SimpleHtmlCache#invalidateUserEntries invalidateUserEntries}
74  * method, where all the pages associated to the specified username will be removed,
75  * regardless of the page IDs.</p>
76  *
77  * @author Fulco Houkes, Copyright (c) 2003 by Jahia Ltd.
78  * @author Serge Huber, Copyright (c) 2003 by Jahia Ltd.
79  * @version 1.0
80  * @since Jahia 4.0
81  *
82  * @see org.jahia.services.cache.Cache Cache
83  * @see org.jahia.services.cache.HtmlCacheEntry HtmlCacheEntry
84  */

85 public class SimpleHtmlCache extends SimpleCache implements HtmlCache {
86
87     /** the cache entry key separator. */
88     private static final String JavaDoc KEY_SEPARATOR = "###";
89
90     /** the page prefix. */
91     private static final String JavaDoc PAGE_PREFIX = "PAGE-";
92
93     /** the hierarchical separator. */
94     private static final String JavaDoc HIERARCHY_SEPARATOR = ":";
95
96     /** logging. */
97     private static final org.apache.log4j.Logger logger =
98             org.apache.log4j.Logger.getLogger (SimpleHtmlCache.class);
99
100     private static final String JavaDoc CONFIG_FILE_NAME = "cacheconfig.xml";
101     private Digester digester = null;
102     protected ArrayList JavaDoc userAgentGroupList = new ArrayList JavaDoc();
103     private Map JavaDoc userAgentMap = new HashMap JavaDoc();
104     private static final String JavaDoc DEFAULT_GROUP_NAME = "defaultgroup";
105     protected UserAgentGroup defaultUserAgentGroup = null;
106
107     /** Default constructor, creates a new <code>Cache</code> instance.
108      *
109      * @param hub The JMS hub reference to use for cache synchronization.
110      *
111      * @throws JahiaInitializationException
112      * when the HTML Cache initialization failed
113      */

114     public SimpleHtmlCache (JMSHub hub)
115             throws JahiaInitializationException
116     {
117         super (HtmlCache.HTML_CACHE, hub);
118
119         // log the instanciation
120
logger.debug ("***** HTML Cache successfully instanciated. *****");
121     }
122
123
124     /** <p>Invalidates all the cache entries related to the specified page <code>pageID</code>,
125      * by removing the cache entries.</p>
126      *
127      * <p><b>Caution</b>: depending of the HTML cache size, this operation can be
128      * time consumming!</p>
129      *
130      * @param pageID the page identification
131      */

132     public synchronized void invalidatePageEntries (String JavaDoc pageID) {
133         if (pageID == null) {
134             logger.debug ("Cannot remove a null page ID fromt the cache!");
135             return;
136         }
137
138         logger.debug ("Removing cache entries for page ["+ pageID +"]");
139
140         String JavaDoc pageKey = PAGE_PREFIX + pageID + HIERARCHY_SEPARATOR;
141         Object JavaDoc[] keys = keys();
142         for (int i=0; i<keys.length; i++) {
143             if (keys[i] instanceof String JavaDoc) {
144                 String JavaDoc key = (String JavaDoc)keys[i];
145
146                 // if the key starts with the pageID, remove the element from the cache
147
if (key.startsWith (pageKey)) {
148                     remove(keys[i]);
149                 }
150             }
151         }
152     }
153
154     /** <p>Invalidates all the cache entries related to the specified page <code>pageID</code>,
155      * by removing the cache entries.</p>
156      *
157      * <p><b>Caution</b>: depending of the HTML cache size, this operation can be
158      * time consumming!</p>
159      *
160      * @param pageID the page identification
161      */

162     public synchronized void invalidatePageEntries (String JavaDoc pageID, int workflowState) {
163         if (pageID == null) {
164             logger.debug ("Cannot remove a null page ID fromt the cache!");
165             return;
166         }
167
168         logger.debug ("Removing cache entries for page ["+ pageID +"]");
169
170         String JavaDoc pageKey = PAGE_PREFIX + pageID + HIERARCHY_SEPARATOR+"(.*)"+KEY_SEPARATOR+workflowState;
171         Object JavaDoc[] keys = keys();
172         for (int i=0; i<keys.length; i++) {
173             if (keys[i] instanceof String JavaDoc) {
174                 String JavaDoc key = (String JavaDoc)keys[i];
175
176                 // if the key starts with the pageID, remove the element from the cache
177
if (key.matches(pageKey)) {
178                     remove(keys[i]);
179                 }
180             }
181         }
182     }
183
184     /** <p>Invalidates all the cache entries related to the specified user
185      * <code>username</code>, by removing the cache entries.</p>
186      *
187      * <p><b>Caution</b>: depending of the HTML cache size, this operation can be
188      * time consumming!</p>
189      *
190      * @param username the page identification
191      */

192     public synchronized void invalidateUserEntries (String JavaDoc username) {
193         if (username == null) {
194             logger.debug ("Cannot remove a null username fromt the cache!");
195             return;
196         }
197
198         logger.debug ("Removing cache entries for user ["+ username +"]");
199
200         String JavaDoc userKey = HIERARCHY_SEPARATOR + username + HIERARCHY_SEPARATOR;
201         Object JavaDoc[] keys = keys();
202         for (int i=0; i<keys.length; i++) {
203             if (keys[i] instanceof String JavaDoc) {
204                 String JavaDoc key = (String JavaDoc)keys[i];
205
206                 // if the key starts with the pageID, remove the element from the cache
207
if (key.indexOf (userKey) != -1) {
208                     remove(keys[i]);
209                 }
210             }
211         }
212     }
213
214
215     /**
216      * <p>Builds the cache key that is used to reference the cache entries in the
217      * lookup table.</p>
218      *
219      * <p>This method actually does much more in the case of user
220      * agent to group mappings. If the mapping doesn't exist yet, it creates it
221      * and if the automatic serialization mode is active, it saves the new user
222      * agent in the default group in the configuration file.</p>
223      *
224      * @param pageID the page identification number
225      * @param userName the user name
226      * @param languageCode the language code
227      * @param workflowState the workflow state
228      * @param userAgent the userAgent
229      * @param scheme the request scheme (http/https)
230      *
231      * @return the generated cache key
232      */

233     public Object JavaDoc computeEntryKey (String JavaDoc pageID, String JavaDoc userName, String JavaDoc languageCode,
234                                           int workflowState, String JavaDoc userAgent, String JavaDoc scheme)
235     {
236         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
237         buffer.append (PAGE_PREFIX);
238         buffer.append (pageID);
239         buffer.append (HIERARCHY_SEPARATOR);
240
241         buffer.append (userName);
242         buffer.append (HIERARCHY_SEPARATOR);
243         buffer.append (languageCode);
244         buffer.append (KEY_SEPARATOR);
245         buffer.append (Integer.toString(workflowState));
246         if (userAgentGroupList.size() > 0) {
247             String JavaDoc groupName = DEFAULT_GROUP_NAME;
248             if (userAgentMap.containsKey(userAgent)) {
249                 groupName = (String JavaDoc) userAgentMap.get(userAgent);
250             } else {
251                 Iterator JavaDoc userAgentEnum = userAgentGroupList.iterator();
252                 boolean hasBeenMatched = false;
253                 while (userAgentEnum.hasNext()) {
254                     UserAgentGroup curGroup = (UserAgentGroup) userAgentEnum.next();
255                     if (curGroup.matchesInsertCriterias(userAgent)) {
256                         // this user agent matches one or more of the regular
257
// expressions, let's add it to this group.
258
curGroup.setUserAgent(userAgent);
259                         groupName = curGroup.getName();
260                         userAgentMap.put(userAgent, groupName);
261                         hasBeenMatched = true;
262                         break;
263                     }
264                 }
265                 if (!hasBeenMatched) {
266                     userAgentMap.put(userAgent, DEFAULT_GROUP_NAME);
267                     groupName = DEFAULT_GROUP_NAME;
268                     if (defaultUserAgentGroup != null) {
269                         defaultUserAgentGroup.setUserAgent(userAgent);
270                     }
271                 }
272                 logger.debug("Inserting user agent " + userAgent +
273                              " into group " + groupName + "... ");
274             }
275
276             buffer.append(KEY_SEPARATOR);
277             buffer.append(groupName);
278             if (!"http".equals(scheme)) {
279                 buffer.append(KEY_SEPARATOR);
280                 buffer.append(scheme);
281               }
282         }
283
284         return buffer.toString();
285     }
286
287     public void init(SettingsBean jSettings)
288         throws JahiaInitializationException {
289         try {
290             String JavaDoc configPath = jSettings.getJahiaOutputCacheConfigDiskPath();
291
292             File JavaDoc configFile = new File JavaDoc(configPath + File.separator +
293                                        CONFIG_FILE_NAME);
294             if (configFile.exists()) {
295
296                 String JavaDoc configFileName = configPath + File.separator +
297                                         CONFIG_FILE_NAME;
298
299                 loadAgentGroupConfig(configFileName);
300
301                 defaultUserAgentGroup = new UserAgentGroup(DEFAULT_GROUP_NAME, new ArrayList JavaDoc(), new TreeSet JavaDoc());
302
303             } else {
304                 logger.error("Config file not found in " + configPath +
305                              File.separator + CONFIG_FILE_NAME);
306             }
307             logger.debug("Initialized");
308         } catch (Throwable JavaDoc t) {
309             throw new JahiaInitializationException("Error while loading output cache configuration file", t);
310         }
311     }
312
313     private void loadAgentGroupConfig (String JavaDoc agentGroupConfigFileName)
314         throws IOException JavaDoc, SAXException JavaDoc {
315         initDigester();
316         File JavaDoc agentGroupConfigFile = new File JavaDoc(agentGroupConfigFileName);
317         this.digester.parse(agentGroupConfigFile);
318     }
319
320     private void initDigester () {
321         this.digester = new Digester();
322
323         AddGroupRule addGroupRule =
324             new AddGroupRule();
325         digester.addRule(
326             "cacheconfig/agentgroups/group", addGroupRule);
327         digester.addRule(
328             "cacheconfig/agentgroups/group/name",
329             addGroupRule.groupNameRule);
330         digester.addRule(
331             "cacheconfig/agentgroups/group/regexps/regexp",
332             addGroupRule.groupRegexpRule);
333     }
334
335     final class AddGroupRule extends Rule {
336
337         private Properties JavaDoc properties = new Properties JavaDoc();
338         private String JavaDoc groupName;
339         protected ArrayList JavaDoc regexpList = new ArrayList JavaDoc();
340
341         protected AddGroupNameRule groupNameRule = new AddGroupNameRule();
342         protected AddGroupRegexpRule groupRegexpRule = new
343             AddGroupRegexpRule();
344
345         public void begin (
346             String JavaDoc namespace,
347             String JavaDoc name,
348             org.xml.sax.Attributes JavaDoc attributes)
349             throws Exception JavaDoc {
350             for (int i = 0; i < attributes.getLength(); i++) {
351                 properties.setProperty(
352                     attributes.getQName(i),
353                     attributes.getValue(i));
354             }
355         }
356
357         public void end (String JavaDoc namespace, String JavaDoc name)
358             throws Exception JavaDoc {
359             groupName = groupNameRule.tagText;
360             // we can now also build a user agent group, notably used to
361
// re-serialize the data to the XML file as well as insert new
362
// unknown user agents based on the evaluation of regular
363
// expressions
364

365             UserAgentGroup curGroup = new UserAgentGroup(groupName,
366                                                          regexpList,
367                                                          new TreeSet JavaDoc());
368
369             if (DEFAULT_GROUP_NAME.equals(groupName)) {
370                 // for speed of access we use this internal reference to
371
// the default group.
372
defaultUserAgentGroup = curGroup;
373             }
374
375             userAgentGroupList.add(curGroup);
376             groupName = null;
377             regexpList = new ArrayList JavaDoc();
378             properties = new Properties JavaDoc();
379         }
380
381         final class AddGroupNameRule extends Rule {
382
383             protected String JavaDoc tagText = null;
384
385             public AddGroupNameRule () {
386             }
387
388             public void body (String JavaDoc namespace, String JavaDoc name, String JavaDoc text)
389                 throws Exception JavaDoc {
390                 this.tagText = text;
391             }
392
393         }
394
395         final class AddGroupRegexpRule extends Rule {
396
397             Properties JavaDoc regExpProperties = new Properties JavaDoc();
398
399             public AddGroupRegexpRule () {
400             }
401
402             public void begin (
403                 String JavaDoc namespace,
404                 String JavaDoc name,
405                 org.xml.sax.Attributes JavaDoc attributes)
406                 throws Exception JavaDoc {
407                 for (int i = 0; i < attributes.getLength(); i++) {
408                     regExpProperties.setProperty(
409                         attributes.getQName(i),
410                         attributes.getValue(i));
411                 }
412             }
413
414             public void end (String JavaDoc namespace, String JavaDoc name)
415                 throws Exception JavaDoc {
416                 String JavaDoc curRegexp = regExpProperties.getProperty("value");
417                 if (curRegexp != null) {
418                     regexpList.add(curRegexp);
419                 }
420                 regExpProperties = new Properties JavaDoc();
421             }
422
423         }
424
425     }
426
427 }
428
Popular Tags