KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > cache > treecache > JahiaTreeHtmlCache


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

90 public class JahiaTreeHtmlCache extends JahiaTreeCache implements HtmlCache {
91
92     // the HTML cache name.
93
public static final String JavaDoc HTML_CACHE = "HTMLCache";
94
95     /** the cache entry key separator. */
96     private static final String JavaDoc KEY_SEPARATOR = "###";
97
98     /** logging. */
99     private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger
100             .getLogger(HtmlCache.class);
101
102     private static final String JavaDoc CONFIG_FILE_NAME = "cacheconfig.xml";
103
104     private Digester digester = null;
105
106     protected ArrayList JavaDoc userAgentGroupList = new ArrayList JavaDoc();
107
108     private Map JavaDoc userAgentMap = new HashMap JavaDoc();
109
110     private static final String JavaDoc DEFAULT_GROUP_NAME = "defaultgroup";
111
112     protected UserAgentGroup defaultUserAgentGroup = null;
113
114     /**
115      * Default constructor, creates a new <code>Cache</code> instance.
116      *
117      * @param propagated
118      * The JMS hub reference to use for cache synchronization.
119      *
120      * @throws JahiaInitializationException
121      * when the HTML Cache initialization failed
122      */

123     protected JahiaTreeHtmlCache(boolean propagated)
124             throws JahiaInitializationException {
125         super(HTML_CACHE, propagated);
126
127         // log the instanciation
128
logger.debug("***** HTML Cache successfully instanciated. *****");
129     }
130
131     /**
132      * <p>
133      * Invalidates all the cache entries related to the specified page
134      * <code>pageID</code>, by removing the cache entries.
135      * </p>
136      *
137      * <p>
138      * <b>Caution</b>: depending of the HTML cache size, this operation can be
139      * time consumming!
140      * </p>
141      *
142      * @param pageID
143      * the page identification
144      */

145     public synchronized void invalidatePageEntries(String JavaDoc pageID) {
146         if (pageID == null) {
147             logger.debug("Cannot remove a null page ID fromt the cache!");
148             return;
149         }
150
151         logger.debug("Removing cache entries for page [" + pageID + "]");
152
153         remove(pageID);
154     }
155
156     /**
157      * <p>
158      * Invalidates all the cache entries related to the specified page
159      * <code>pageID</code>, by removing the cache entries.
160      * </p>
161      *
162      * <p>
163      * <b>Caution</b>: depending of the HTML cache size, this operation can be
164      * time consumming!
165      * </p>
166      *
167      * @param pageID
168      * the page identification
169      */

170     public synchronized void invalidatePageEntries(String JavaDoc pageID,
171             int workflowState) {
172         if (pageID == null) {
173             logger.debug("Cannot remove a null page ID fromt the cache!");
174             return;
175         }
176
177         logger.debug("Removing cache entries for page [" + pageID + "]");
178
179         List JavaDoc key = new ArrayList JavaDoc(2);
180         key.add(pageID);
181         key.add(Integer.toString(workflowState));
182         remove(key);
183     }
184
185     /**
186      * <p>
187      * Invalidates all the cache entries related to the specified user
188      * <code>username</code>, by removing the cache entries.
189      * </p>
190      *
191      * <p>
192      * <b>Caution</b>: depending of the HTML cache size, this operation can be
193      * time consumming!
194      * </p>
195      *
196      * @param username
197      * the page identification
198      */

199     public synchronized void invalidateUserEntries(String JavaDoc username) {
200         if (username == null) {
201             logger.debug("Cannot remove a null username fromt the cache!");
202             return;
203         }
204
205         logger.debug("Removing cache entries for user [" + username + "]");
206         TreeCache htmlCache = getTreeCache();
207         try {
208             Set JavaDoc pageKeys = htmlCache.getChildrenNames(getFqn());
209             if (pageKeys != null) {
210                 for (Iterator JavaDoc it = pageKeys.iterator(); it.hasNext();) {
211                     Object JavaDoc pageKey = it.next();
212                     Set JavaDoc workflowKeys = htmlCache.getChildrenNames(new Fqn(
213                             getFqn(), pageKey));
214                     if (workflowKeys != null) {
215                         for (Iterator JavaDoc it2 = workflowKeys.iterator(); it2
216                                 .hasNext();) {
217                             Object JavaDoc workflowKey = it2.next();
218                             Fqn fqn = new Fqn(getFqn(), pageKey, workflowKey,
219                                     username);
220                             if (htmlCache.exists(fqn)) {
221                                 htmlCache.remove(fqn);
222                             }
223                         }
224                     }
225                 }
226             }
227         } catch (CacheException e) {
228             logger.warn(getName() + username, e);
229         }
230     }
231
232     /**
233      * <p>
234      * Builds the cache key that is used to reference the cache entries in the
235      * lookup table.
236      * </p>
237      *
238      * <p>
239      * This method actually does much more in the case of user agent to group
240      * mappings. If the mapping doesn't exist yet, it creates it and if the
241      * automatic serialization mode is active, it saves the new user agent in
242      * the default group in the configuration file.
243      * </p>
244      *
245      * @param pageID
246      * the page identification number
247      * @param userName
248      * the user name
249      * @param languageCode
250      * the language code
251      * @param workflowState
252      * the workflow state
253      * @param userAgent
254      * the userAgent
255      *
256      * @return the generated cache key
257      */

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

385             UserAgentGroup curGroup = new UserAgentGroup(groupName, regexpList,
386                     new TreeSet JavaDoc());
387
388             if (DEFAULT_GROUP_NAME.equals(groupName)) {
389                 // for speed of access we use this internal reference to
390
// the default group.
391
defaultUserAgentGroup = curGroup;
392             }
393
394             userAgentGroupList.add(curGroup);
395             groupName = null;
396             regexpList = new ArrayList JavaDoc();
397             properties = new Properties JavaDoc();
398         }
399
400         final class AddGroupNameRule extends Rule {
401
402             private String JavaDoc tagName = null;
403
404             protected String JavaDoc tagText = null;
405
406             public AddGroupNameRule() {
407             }
408
409             public void body(String JavaDoc namespace, String JavaDoc name, String JavaDoc text)
410                     throws Exception JavaDoc {
411                 this.tagName = name;
412                 this.tagText = text;
413             }
414
415         }
416
417         final class AddGroupRegexpRule extends Rule {
418
419             Properties JavaDoc properties = new Properties JavaDoc();
420
421             public AddGroupRegexpRule() {
422             }
423
424             public void begin(String JavaDoc namespace, String JavaDoc name,
425                     org.xml.sax.Attributes JavaDoc attributes) throws Exception JavaDoc {
426                 for (int i = 0; i < attributes.getLength(); i++) {
427                     properties.setProperty(attributes.getQName(i), attributes
428                             .getValue(i));
429                 }
430             }
431
432             public void end(String JavaDoc namespace, String JavaDoc name) throws Exception JavaDoc {
433                 String JavaDoc curRegexp = properties.getProperty("value");
434                 if (curRegexp != null) {
435                     regexpList.add(curRegexp);
436                 }
437                 properties = new Properties JavaDoc();
438             }
439
440         }
441
442     }
443
444 }
445
Popular Tags