Source Code Cross Referenced for CachingProvider.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » providers » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.providers 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:            JSPWiki - a JSP-based WikiWiki clone.
003:
004:            Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006:            This program is free software; you can redistribute it and/or modify
007:            it under the terms of the GNU Lesser General Public License as published by
008:            the Free Software Foundation; either version 2.1 of the License, or
009:            (at your option) any later version.
010:
011:            This program is distributed in the hope that it will be useful,
012:            but WITHOUT ANY WARRANTY; without even the implied warranty of
013:            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:            GNU Lesser General Public License for more details.
015:
016:            You should have received a copy of the GNU Lesser General Public License
017:            along with this program; if not, write to the Free Software
018:            Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package com.ecyrd.jspwiki.providers;
021:
022:        import java.io.IOException;
023:        import java.util.*;
024:
025:        import org.apache.log4j.Logger;
026:
027:        import com.ecyrd.jspwiki.*;
028:        import com.ecyrd.jspwiki.parser.MarkupParser;
029:        import com.ecyrd.jspwiki.render.RenderingManager;
030:        import com.ecyrd.jspwiki.util.ClassUtil;
031:        import com.opensymphony.oscache.base.Cache;
032:        import com.opensymphony.oscache.base.NeedsRefreshException;
033:        import com.opensymphony.oscache.base.events.*;
034:
035:        /**
036:         *  Provides a caching page provider.  This class rests on top of a
037:         *  real provider class and provides a cache to speed things up.  Only
038:         *  if the cache copy of the page text has expired, we fetch it from
039:         *  the provider.
040:         *  <p>
041:         *  This class also detects if someone has modified the page
042:         *  externally, not through JSPWiki routines, and throws the proper
043:         *  RepositoryModifiedException.
044:         *  <p>
045:         *  Heavily based on ideas by Chris Brooking.
046:         *  <p>
047:         *  Since 2.1.52 uses the OSCache library from OpenSymphony.
048:         *
049:         *  @author Janne Jalkanen
050:         *  @since 1.6.4
051:         *  @see RepositoryModifiedException
052:         */
053:        // FIXME: Synchronization is a bit inconsistent in places.
054:        // FIXME: A part of the stuff is now redundant, since we could easily use the text cache
055:        //        for a lot of things.  RefactorMe.
056:        public class CachingProvider implements  WikiPageProvider,
057:                VersioningProvider {
058:            private static final Logger log = Logger
059:                    .getLogger(CachingProvider.class);
060:
061:            private WikiPageProvider m_provider;
062:            // FIXME: Find another way to the search engine to use instead of from WikiEngine?
063:            private WikiEngine m_engine;
064:
065:            private Cache m_cache;
066:            private Cache m_negCache; // Cache for holding non-existing pages
067:
068:            private Cache m_textCache;
069:            private Cache m_historyCache;
070:
071:            private long m_cacheMisses = 0;
072:            private long m_cacheHits = 0;
073:
074:            private long m_historyCacheMisses = 0;
075:            private long m_historyCacheHits = 0;
076:
077:            private int m_expiryPeriod = 30;
078:
079:            /**
080:             *  This can be very long, as normally all modifications are noticed in an earlier
081:             *  stage.
082:             */
083:            private int m_pageContentExpiryPeriod = 24 * 60 * 60;
084:
085:            // FIXME: This MUST be cached somehow.
086:
087:            private boolean m_gotall = false;
088:
089:            private CacheItemCollector m_allCollector = new CacheItemCollector();
090:
091:            /**
092:             *  Defines, in seconds, the amount of time a text will live in the cache
093:             *  at most before requiring a refresh.
094:             */
095:
096:            public static final String PROP_CACHECHECKINTERVAL = "jspwiki.cachingProvider.cacheCheckInterval";
097:            public static final String PROP_CACHECAPACITY = "jspwiki.cachingProvider.capacity";
098:
099:            private static final int DEFAULT_CACHECAPACITY = 1000; // Good most wikis
100:
101:            private static final String OSCACHE_ALGORITHM = "com.opensymphony.oscache.base.algorithm.LRUCache";
102:
103:            public void initialize(WikiEngine engine, Properties properties)
104:                    throws NoRequiredPropertyException, IOException {
105:                log.debug("Initing CachingProvider");
106:
107:                // engine is used for getting the search engine
108:                m_engine = engine;
109:
110:                //
111:                //  Cache consistency checks
112:                //
113:                m_expiryPeriod = TextUtil.getIntegerProperty(properties,
114:                        PROP_CACHECHECKINTERVAL, m_expiryPeriod);
115:
116:                log.debug("Cache expiry period is " + m_expiryPeriod + " s");
117:
118:                //
119:                //  Text cache capacity
120:                //
121:                int capacity = TextUtil.getIntegerProperty(properties,
122:                        PROP_CACHECAPACITY, DEFAULT_CACHECAPACITY);
123:
124:                log.debug("Cache capacity " + capacity + " pages.");
125:
126:                m_cache = new Cache(true, false, false);
127:
128:                //
129:                //  OSCache documentation sucks big time.  The clazz-parameter is completely
130:                //  undefined; I had to read the source code to figure out that you need
131:                //  to declare what type of a listener you are adding by sending the type
132:                //  of the interface.
133:                //
134:                m_cache.addCacheEventListener(m_allCollector,
135:                        CacheEntryEventListener.class);
136:
137:                //
138:                //  FIXME: There's an interesting issue here... It would probably be
139:                //  possible to DOS a JSPWiki instance by bombarding it with names that
140:                //  do not exist, as they would fill the negcache.  Will need to
141:                //  think about this some more...
142:                //
143:                m_negCache = new Cache(true, false, false);
144:
145:                m_textCache = new Cache(true, false, false, false,
146:                        OSCACHE_ALGORITHM, capacity);
147:
148:                m_historyCache = new Cache(true, false, false, false,
149:                        OSCACHE_ALGORITHM, capacity);
150:
151:                //
152:                //  Find and initialize real provider.
153:                //
154:                String classname = WikiEngine.getRequiredProperty(properties,
155:                        PageManager.PROP_PAGEPROVIDER);
156:
157:                try {
158:                    Class providerclass = ClassUtil.findClass(
159:                            "com.ecyrd.jspwiki.providers", classname);
160:
161:                    m_provider = (WikiPageProvider) providerclass.newInstance();
162:
163:                    log.debug("Initializing real provider class " + m_provider);
164:                    m_provider.initialize(engine, properties);
165:                } catch (ClassNotFoundException e) {
166:                    log
167:                            .error("Unable to locate provider class "
168:                                    + classname, e);
169:                    throw new IllegalArgumentException("no provider class");
170:                } catch (InstantiationException e) {
171:                    log
172:                            .error("Unable to create provider class "
173:                                    + classname, e);
174:                    throw new IllegalArgumentException("faulty provider class");
175:                } catch (IllegalAccessException e) {
176:                    log.error("Illegal access to provider class " + classname,
177:                            e);
178:                    throw new IllegalArgumentException("illegal provider class");
179:                }
180:            }
181:
182:            private WikiPage getPageInfoFromCache(String name)
183:                    throws ProviderException, RepositoryModifiedException {
184:                boolean wasUpdated = false;
185:                // Sanity check; seems to occur sometimes
186:                if (name == null)
187:                    return null;
188:
189:                try {
190:                    WikiPage item = (WikiPage) m_cache.getFromCache(name,
191:                            m_expiryPeriod);
192:
193:                    wasUpdated = true;
194:
195:                    if (item != null)
196:                        return item;
197:
198:                    return null;
199:                } catch (NeedsRefreshException e) {
200:                    WikiPage cached = (WikiPage) e.getCacheContent();
201:
202:                    // int version = (cached != null) ? cached.getVersion() : WikiPageProvider.LATEST_VERSION;
203:
204:                    WikiPage refreshed;
205:
206:                    //
207:                    //  Just be careful that we don't accidentally leave the cache in a
208:                    //  hung state
209:                    //
210:
211:                    refreshed = m_provider.getPageInfo(name,
212:                            WikiPageProvider.LATEST_VERSION);
213:
214:                    if (refreshed == null && cached != null) {
215:                        //  Page has been removed evilly by a goon from outer space
216:
217:                        log.debug("Page " + name
218:                                + " has been removed externally.");
219:
220:                        m_cache.putInCache(name, null);
221:                        m_textCache.putInCache(name, null);
222:                        m_historyCache.putInCache(name, null);
223:                        // We cache a page miss
224:                        m_negCache.putInCache(name, name);
225:                        wasUpdated = true;
226:
227:                        throw new RepositoryModifiedException("Removed: "
228:                                + name, name);
229:                    } else if (cached == null) {
230:                        // The page did not exist in the first place
231:
232:                        if (refreshed != null) {
233:                            // We must now add it
234:                            m_cache.putInCache(name, refreshed);
235:                            // Requests for this page are now no longer denied
236:                            m_negCache.putInCache(name, null);
237:                            wasUpdated = true;
238:
239:                            throw new RepositoryModifiedException("Added: "
240:                                    + name, name);
241:                        }
242:
243:                        // Cache page miss
244:                        m_negCache.putInCache(name, name);
245:                    } else if (refreshed != null
246:                            && cached.getVersion() != refreshed.getVersion()) {
247:                        //  The newest version has been deleted, but older versions still remain
248:                        log.debug("Page " + cached.getName()
249:                                + " newest version deleted, reloading...");
250:
251:                        m_cache.putInCache(name, refreshed);
252:                        // Requests for this page are now no longer denied
253:                        m_negCache.putInCache(name, null);
254:
255:                        m_textCache.flushEntry(name);
256:                        m_historyCache.flushEntry(name);
257:                        wasUpdated = true;
258:
259:                        return refreshed;
260:                    } else if (refreshed != null
261:                            && Math.abs(refreshed.getLastModified().getTime()
262:                                    - cached.getLastModified().getTime()) > 1000L) {
263:                        //  Yes, the page has been modified externally and nobody told us
264:
265:                        log.info("Page " + cached.getName()
266:                                + " changed, reloading...");
267:
268:                        m_cache.putInCache(name, refreshed);
269:                        // Requests for this page are now no longer denied
270:                        m_negCache.putInCache(name, null);
271:                        m_textCache.flushEntry(name);
272:                        m_historyCache.flushEntry(name);
273:                        wasUpdated = true;
274:
275:                        throw new RepositoryModifiedException("Modified: "
276:                                + name, name);
277:                    } else {
278:                        // Refresh the cache by putting the same object back
279:                        m_cache.putInCache(name, cached);
280:                        // Requests for this page are now no longer denied
281:                        m_negCache.putInCache(name, null);
282:                        wasUpdated = true;
283:                    }
284:
285:                    return cached;
286:                } finally {
287:                    if (!wasUpdated)
288:                        m_cache.cancelUpdate(name);
289:                }
290:            }
291:
292:            public boolean pageExists(String pageName, int version) {
293:                if (pageName == null)
294:                    return false;
295:
296:                //
297:                //  First, check the negative cache if we've seen it before
298:                //
299:                try {
300:                    String isNonExistant = (String) m_negCache.getFromCache(
301:                            pageName, m_expiryPeriod);
302:
303:                    if (isNonExistant != null)
304:                        return false; // No such page
305:                } catch (NeedsRefreshException e) {
306:                    m_negCache.cancelUpdate(pageName);
307:                }
308:
309:                WikiPage p = null;
310:
311:                try {
312:                    p = getPageInfoFromCache(pageName);
313:                } catch (RepositoryModifiedException e) {
314:                    // The repository was modified, we need to check now if the page was removed or
315:                    // added.
316:                    // TODO: This information would be available in the exception, but we would
317:                    //       need to subclass.
318:
319:                    try {
320:                        p = getPageInfoFromCache(pageName);
321:                    } catch (Exception ex) {
322:                        // This should not happen
323:                        return false;
324:                    }
325:                } catch (ProviderException e) {
326:                    log
327:                            .info("Provider failed while trying to check if page exists: "
328:                                    + pageName);
329:                    return false;
330:                }
331:
332:                if (p != null) {
333:                    int latestVersion = p.getVersion();
334:
335:                    if (version == latestVersion || version == LATEST_VERSION) {
336:                        return true;
337:                    }
338:
339:                    if (m_provider instanceof  VersioningProvider)
340:                        return ((VersioningProvider) m_provider).pageExists(
341:                                pageName, version);
342:                }
343:
344:                try {
345:                    return getPageInfo(pageName, version) != null;
346:                } catch (ProviderException e) {
347:                }
348:
349:                return false;
350:            }
351:
352:            public boolean pageExists(String pageName) {
353:                if (pageName == null)
354:                    return false;
355:
356:                //
357:                //  First, check the negative cache if we've seen it before
358:                //
359:                try {
360:                    String isNonExistant = (String) m_negCache.getFromCache(
361:                            pageName, m_expiryPeriod);
362:
363:                    if (isNonExistant != null)
364:                        return false; // No such page
365:                } catch (NeedsRefreshException e) {
366:                    m_negCache.cancelUpdate(pageName);
367:                }
368:
369:                WikiPage p = null;
370:
371:                try {
372:                    p = getPageInfoFromCache(pageName);
373:                } catch (RepositoryModifiedException e) {
374:                    // The repository was modified, we need to check now if the page was removed or
375:                    // added.
376:                    // TODO: This information would be available in the exception, but we would
377:                    //       need to subclass.
378:
379:                    try {
380:                        p = getPageInfoFromCache(pageName);
381:                    } catch (Exception ex) {
382:                        return false; // This should not happen
383:                    }
384:                } catch (ProviderException e) {
385:                    log
386:                            .info("Provider failed while trying to check if page exists: "
387:                                    + pageName);
388:                    return false;
389:                }
390:
391:                //
392:                //  A null item means that the page either does not
393:                //  exist, or has not yet been cached; a non-null
394:                //  means that the page does exist.
395:                //
396:                if (p != null) {
397:                    return true;
398:                }
399:
400:                //
401:                //  If we have a list of all pages in memory, then any page
402:                //  not in the cache must be non-existent.
403:                //
404:                //  FIXME: There's a problem here; if someone modifies the
405:                //         repository by adding a page outside JSPWiki,
406:                //         we won't notice it.
407:
408:                if (m_gotall) {
409:                    return false;
410:                }
411:
412:                //
413:                //  We could add the page to the cache here as well,
414:                //  but in order to understand whether that is a
415:                //  good thing or not we would need to analyze
416:                //  the JSPWiki calling patterns extensively.  Presumably
417:                //  it would be a good thing if pageExists() is called
418:                //  many times before the first getPageText() is called,
419:                //  and the whole page is cached.
420:                //
421:                return m_provider.pageExists(pageName);
422:            }
423:
424:            /**
425:             *  @throws RepositoryModifiedException If the page has been externally modified.
426:             */
427:            public String getPageText(String pageName, int version)
428:                    throws ProviderException, RepositoryModifiedException {
429:                String result = null;
430:
431:                if (pageName == null)
432:                    return null;
433:
434:                if (version == WikiPageProvider.LATEST_VERSION) {
435:                    result = getTextFromCache(pageName);
436:                } else {
437:                    WikiPage p = getPageInfoFromCache(pageName);
438:
439:                    //
440:                    //  Or is this the latest version fetched by version number?
441:                    //
442:                    if (p != null && p.getVersion() == version) {
443:                        result = getTextFromCache(pageName);
444:                    } else {
445:                        result = m_provider.getPageText(pageName, version);
446:                    }
447:                }
448:
449:                return result;
450:            }
451:
452:            /**
453:             *  @throws RepositoryModifiedException If the page has been externally modified.
454:             */
455:            private String getTextFromCache(String pageName)
456:                    throws ProviderException, RepositoryModifiedException {
457:                String text;
458:                boolean wasUpdated = false;
459:
460:                if (pageName == null)
461:                    return null;
462:
463:                WikiPage page = getPageInfoFromCache(pageName);
464:
465:                try {
466:                    text = (String) m_textCache.getFromCache(pageName,
467:                            m_pageContentExpiryPeriod);
468:                    wasUpdated = true;
469:
470:                    if (text == null) {
471:                        if (page != null) {
472:                            text = m_provider.getPageText(pageName,
473:                                    WikiPageProvider.LATEST_VERSION);
474:
475:                            m_textCache.putInCache(pageName, text);
476:
477:                            m_cacheMisses++;
478:                        } else {
479:                            return null;
480:                        }
481:                    } else {
482:                        m_cacheHits++;
483:                    }
484:                } catch (NeedsRefreshException e) {
485:                    if (pageExists(pageName)) {
486:                        text = m_provider.getPageText(pageName,
487:                                WikiPageProvider.LATEST_VERSION);
488:
489:                        m_textCache.putInCache(pageName, text);
490:                        wasUpdated = true;
491:
492:                        m_cacheMisses++;
493:                    } else {
494:                        m_textCache.putInCache(pageName, null);
495:                        wasUpdated = true;
496:                        return null; // No page exists
497:                    }
498:                } finally {
499:                    if (!wasUpdated)
500:                        m_textCache.cancelUpdate(pageName);
501:                }
502:
503:                return text;
504:            }
505:
506:            public void putPageText(WikiPage page, String text)
507:                    throws ProviderException {
508:                synchronized (this ) {
509:                    m_provider.putPageText(page, text);
510:
511:                    page.setLastModified(new Date());
512:
513:                    // Refresh caches properly
514:
515:                    m_cache.flushEntry(page.getName());
516:                    m_textCache.flushEntry(page.getName());
517:                    m_historyCache.flushEntry(page.getName());
518:                    m_negCache.flushEntry(page.getName());
519:
520:                    // Refresh caches
521:                    try {
522:                        getPageInfoFromCache(page.getName());
523:                    } catch (RepositoryModifiedException e) {
524:                    } // Expected
525:                }
526:            }
527:
528:            public Collection getAllPages() throws ProviderException {
529:                Collection all;
530:
531:                if (m_gotall == false) {
532:                    all = m_provider.getAllPages();
533:
534:                    // Make sure that all pages are in the cache.
535:
536:                    synchronized (this ) {
537:                        for (Iterator i = all.iterator(); i.hasNext();) {
538:                            WikiPage p = (WikiPage) i.next();
539:
540:                            m_cache.putInCache(p.getName(), p);
541:                            // Requests for this page are now no longer denied
542:                            m_negCache.putInCache(p.getName(), null);
543:                        }
544:
545:                        m_gotall = true;
546:                    }
547:                } else {
548:                    all = m_allCollector.getAllItems();
549:                }
550:
551:                return all;
552:            }
553:
554:            public Collection getAllChangedSince(Date date) {
555:                return m_provider.getAllChangedSince(date);
556:            }
557:
558:            public int getPageCount() throws ProviderException {
559:                return m_provider.getPageCount();
560:            }
561:
562:            public Collection findPages(QueryItem[] query) {
563:                //
564:                //  If the provider is a fast searcher, then
565:                //  just pass this request through.
566:                //
567:                return m_provider.findPages(query);
568:
569:                // FIXME: Does not implement fast searching
570:            }
571:
572:            //
573:            //  FIXME: Kludge: make sure that the page is also parsed and it gets all the
574:            //         necessary variables.
575:            //
576:
577:            private void refreshMetadata(WikiPage page) {
578:                if (page != null && !page.hasMetadata()) {
579:                    RenderingManager mgr = m_engine.getRenderingManager();
580:
581:                    try {
582:                        String data = m_provider.getPageText(page.getName(),
583:                                page.getVersion());
584:
585:                        WikiContext ctx = new WikiContext(m_engine, page);
586:                        MarkupParser parser = mgr.getParser(ctx, data);
587:
588:                        parser.parse();
589:                    } catch (Exception ex) {
590:                        log.debug("Failed to retrieve variables for wikipage "
591:                                + page);
592:                    }
593:                }
594:            }
595:
596:            public WikiPage getPageInfo(String pageName, int version)
597:                    throws ProviderException, RepositoryModifiedException {
598:                WikiPage page = null;
599:                WikiPage cached = getPageInfoFromCache(pageName);
600:
601:                int latestcached = (cached != null) ? cached.getVersion()
602:                        : Integer.MIN_VALUE;
603:
604:                if (version == WikiPageProvider.LATEST_VERSION
605:                        || version == latestcached) {
606:                    if (cached == null) {
607:                        WikiPage data = m_provider.getPageInfo(pageName,
608:                                version);
609:
610:                        if (data != null) {
611:                            m_cache.putInCache(pageName, data);
612:                            // Requests for this page are now no longer denied
613:                            m_negCache.putInCache(pageName, null);
614:                        }
615:                        page = data;
616:                    } else {
617:                        page = cached;
618:                    }
619:                } else {
620:                    // We do not cache old versions.
621:                    page = m_provider.getPageInfo(pageName, version);
622:                    //refreshMetadata( page );
623:                }
624:
625:                refreshMetadata(page);
626:
627:                return page;
628:            }
629:
630:            public List getVersionHistory(String pageName)
631:                    throws ProviderException {
632:                List history = null;
633:                boolean wasUpdated = false;
634:
635:                if (pageName == null)
636:                    return null;
637:                try {
638:                    history = (List) m_historyCache.getFromCache(pageName,
639:                            m_expiryPeriod);
640:
641:                    log.debug("History cache hit for page " + pageName);
642:                    m_historyCacheHits++;
643:                    wasUpdated = true;
644:                } catch (NeedsRefreshException e) {
645:                    history = m_provider.getVersionHistory(pageName);
646:
647:                    m_historyCache.putInCache(pageName, history);
648:
649:                    log.debug("History cache miss for page " + pageName);
650:                    m_historyCacheMisses++;
651:                    wasUpdated = true;
652:                } finally {
653:                    if (!wasUpdated)
654:                        m_historyCache.cancelUpdate(pageName);
655:                }
656:
657:                return history;
658:            }
659:
660:            public synchronized String getProviderInfo() {
661:                return "Real provider: " + m_provider.getClass().getName()
662:                        + ". Cache misses: " + m_cacheMisses + ". Cache hits: "
663:                        + m_cacheHits + ". History cache hits: "
664:                        + m_historyCacheHits + ". History cache misses: "
665:                        + m_historyCacheMisses + ". Cache consistency checks: "
666:                        + m_expiryPeriod + "s";
667:            }
668:
669:            public void deleteVersion(String pageName, int version)
670:                    throws ProviderException {
671:                //
672:                //  Luckily, this is such a rare operation it is okay
673:                //  to synchronize against the whole thing.
674:                //
675:                synchronized (this ) {
676:                    WikiPage cached = getPageInfoFromCache(pageName);
677:
678:                    int latestcached = (cached != null) ? cached.getVersion()
679:                            : Integer.MIN_VALUE;
680:
681:                    //
682:                    //  If we have this version cached, remove from cache.
683:                    //
684:                    if (version == WikiPageProvider.LATEST_VERSION
685:                            || version == latestcached) {
686:                        m_cache.flushEntry(pageName);
687:                        m_textCache.putInCache(pageName, null);
688:                        m_historyCache.putInCache(pageName, null);
689:                    }
690:
691:                    m_provider.deleteVersion(pageName, version);
692:                }
693:            }
694:
695:            public void deletePage(String pageName) throws ProviderException {
696:                //
697:                //  See note in deleteVersion().
698:                //
699:                synchronized (this ) {
700:                    m_cache.putInCache(pageName, null);
701:                    m_textCache.putInCache(pageName, null);
702:                    m_historyCache.putInCache(pageName, null);
703:                    m_negCache.putInCache(pageName, pageName);
704:                    m_provider.deletePage(pageName);
705:                }
706:            }
707:
708:            public void movePage(String from, String to)
709:                    throws ProviderException {
710:                m_provider.movePage(from, to);
711:
712:                synchronized (this ) {
713:                    // Clear any cached version of the old page
714:                    log.debug("Removing page " + from + " from cache");
715:                    m_cache.flushEntry(from);
716:
717:                    // Clear the cache for the to page, if that page already exists
718:                    //if ( m_cache.get( to ) != null )
719:                    //{
720:                    log.debug("Removing page " + to + " from cache");
721:                    m_cache.flushEntry(to);
722:                    //}
723:                }
724:            }
725:
726:            /**
727:             *  Returns the actual used provider.
728:             *  @since 2.0
729:             */
730:            public WikiPageProvider getRealProvider() {
731:                return m_provider;
732:            }
733:
734:            /**
735:             *  This is a simple class that keeps a list of all WikiPages that
736:             *  we have in memory.  Because the OSCache cannot give us a list
737:             *  of all pages currently in cache, we'll have to check this
738:             *  ourselves.
739:             *
740:             *  @author jalkanen
741:             *
742:             *  @since 2.4
743:             */
744:            private static class CacheItemCollector implements 
745:                    CacheEntryEventListener {
746:                private Map m_allItems = new HashMap();
747:
748:                /**
749:                 * Returns a clone of the set - you cannot manipulate this.
750:                 *
751:                 * @return
752:                 */
753:                public Set getAllItems() {
754:                    Set ret = new TreeSet();
755:                    ret.addAll(m_allItems.values());
756:
757:                    return ret;
758:                }
759:
760:                public void cacheEntryAdded(CacheEntryEvent arg0) {
761:                    cacheEntryUpdated(arg0);
762:                }
763:
764:                public void cachePatternFlushed(CachePatternEvent ev) {
765:                }
766:
767:                public void cacheGroupFlushed(CacheGroupEvent ev) {
768:                }
769:
770:                public void cacheFlushed(CachewideEvent ev) {
771:                }
772:
773:                public void cacheEntryFlushed(CacheEntryEvent arg0) {
774:                    cacheEntryRemoved(arg0);
775:                }
776:
777:                public void cacheEntryRemoved(CacheEntryEvent arg0) {
778:                    WikiPage item = (WikiPage) arg0.getEntry().getContent();
779:
780:                    if (item != null) {
781:                        m_allItems.remove(item);
782:                    }
783:                }
784:
785:                public void cacheEntryUpdated(CacheEntryEvent arg0) {
786:                    WikiPage item = (WikiPage) arg0.getEntry().getContent();
787:
788:                    if (item != null) {
789:                        // Item added or replaced.
790:                        m_allItems.put(item.getName(), item);
791:                    } else {
792:                        // Removed item
793:                        // FIXME: If the page system is changed during this time, we'll just fail gracefully
794:
795:                        m_allItems.remove(arg0.getKey());
796:                    }
797:                }
798:            }
799:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.