Source Code Cross Referenced for ServletCacheAdministrator.java in  » Cache » OSCache » com » opensymphony » oscache » web » 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
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Cache » OSCache » com.opensymphony.oscache.web 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2002-2003 by OpenSymphony
003:         * All rights reserved.
004:         */
005:        package com.opensymphony.oscache.web;
006:
007:        import com.opensymphony.oscache.base.*;
008:        import com.opensymphony.oscache.base.events.CacheEventListener;
009:        import com.opensymphony.oscache.base.events.ScopeEvent;
010:        import com.opensymphony.oscache.base.events.ScopeEventListener;
011:        import com.opensymphony.oscache.base.events.ScopeEventType;
012:
013:        import org.apache.commons.logging.Log;
014:        import org.apache.commons.logging.LogFactory;
015:
016:        import java.io.Serializable;
017:
018:        import java.util.*;
019:
020:        import javax.servlet.ServletContext;
021:        import javax.servlet.http.HttpServletRequest;
022:        import javax.servlet.http.HttpSession;
023:        import javax.servlet.jsp.PageContext;
024:
025:        /**
026:         * A ServletCacheAdministrator creates, flushes and administers the cache.
027:         * <p>
028:         * This is a "servlet Singleton". This means it's not a Singleton in the traditional sense,
029:         * that is stored in a static instance. It's a Singleton _per web app context_.
030:         * <p>
031:         * Once created it manages the cache path on disk through the oscache.properties
032:         * file, and also keeps track of the flush times.
033:         *
034:         * @author <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
035:         * @author <a href="mailto:tgochenour@peregrine.com">Todd Gochenour</a>
036:         * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
037:         * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
038:         * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
039:         * @version        $Revision: 463 $
040:         */
041:        public class ServletCacheAdministrator extends
042:                AbstractCacheAdministrator implements  Serializable {
043:            private static final transient Log log = LogFactory
044:                    .getLog(ServletCacheAdministrator.class);
045:
046:            /**
047:             * Constants for properties read/written from/to file
048:             */
049:            private final static String CACHE_USE_HOST_DOMAIN_KEY = "cache.use.host.domain.in.key";
050:            private final static String CACHE_KEY_KEY = "cache.key";
051:
052:            /**
053:             * The default cache key that is used to store the cache in context.
054:             */
055:            private final static String DEFAULT_CACHE_KEY = "__oscache_cache";
056:
057:            /**
058:             * Constants for scope's name
059:             */
060:            public final static String SESSION_SCOPE_NAME = "session";
061:            public final static String APPLICATION_SCOPE_NAME = "application";
062:
063:            /**
064:             * The suffix added to the cache key used to store a 
065:             * ServletCacheAdministrator will be stored in the ServletContext
066:             */
067:            private final static String CACHE_ADMINISTRATOR_KEY_SUFFIX = "_admin";
068:
069:            /**
070:             * The key under which an array of all ServletCacheAdministrator objects 
071:             * will be stored in the ServletContext
072:             */
073:            private final static String CACHE_ADMINISTRATORS_KEY = "__oscache_admins";
074:
075:            /**
076:             * Key used to store the current scope in the configuration. This is a hack
077:             * to let the scope information get passed through to the DiskPersistenceListener,
078:             * and will be removed in a future release.
079:             */
080:            public final static String HASH_KEY_SCOPE = "scope";
081:
082:            /**
083:             * Key used to store the current session ID in the configuration. This is a hack
084:             * to let the scope information get passed through to the DiskPersistenceListener,
085:             * and will be removed in a future release.
086:             */
087:            public final static String HASH_KEY_SESSION_ID = "sessionId";
088:
089:            /**
090:             * Key used to store the servlet container temporary directory in the configuration.
091:             * This is a hack to let the scope information get passed through to the
092:             * DiskPersistenceListener, and will be removed in a future release.
093:             */
094:            public final static String HASH_KEY_CONTEXT_TMPDIR = "context.tempdir";
095:
096:            /**
097:             * The string to use as a file separator.
098:             */
099:            private final static String FILE_SEPARATOR = "/";
100:
101:            /**
102:             * The character to use as a file separator.
103:             */
104:            private final static char FILE_SEPARATOR_CHAR = FILE_SEPARATOR
105:                    .charAt(0);
106:
107:            /**
108:             * Constant for Key generation.
109:             */
110:            private final static short AVERAGE_KEY_LENGTH = 30;
111:
112:            /**
113:             * Usable caracters for key generation
114:             */
115:            private static final String m_strBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
116:
117:            /**
118:             * Map containing the flush times of different scopes
119:             */
120:            private Map flushTimes;
121:
122:            /**
123:             * Required so we can look up the app scope cache without forcing a session creation.
124:             */
125:            private transient ServletContext context;
126:
127:            /**
128:             * Key to use for storing and retrieving Object in contexts (Servlet, session).
129:             */
130:            private String cacheKey;
131:
132:            /**
133:             *  Set property cache.use.host.domain.in.key=true to add domain information to key
134:             *  generation for hosting multiple sites.
135:             */
136:            private boolean useHostDomainInKey = false;
137:
138:            /**
139:             *        Create the cache administrator.
140:             *
141:             *        This will reset all the flush times and load the properties file.
142:             */
143:            private ServletCacheAdministrator(ServletContext context,
144:                    Properties p) {
145:                super (p);
146:                config.set(HASH_KEY_CONTEXT_TMPDIR, context
147:                        .getAttribute("javax.servlet.context.tempdir"));
148:
149:                flushTimes = new HashMap();
150:                initHostDomainInKey();
151:                this .context = context;
152:            }
153:
154:            /**
155:             * Obtain an instance of the CacheAdministrator
156:             *
157:             * @param context The ServletContext that this CacheAdministrator is a Singleton under
158:             * @return Returns the CacheAdministrator instance for this context
159:             */
160:            public static ServletCacheAdministrator getInstance(
161:                    ServletContext context) {
162:                return getInstance(context, null);
163:            }
164:
165:            /**
166:             * Obtain an instance of the CacheAdministrator for the specified key
167:             *
168:             * @param context The ServletContext that this CacheAdministrator is a Singleton under
169:             * @param key the cachekey or admincachekey for the CacheAdministrator wanted
170:             * @return Returns the CacheAdministrator instance for this context, or null if no
171:             * CacheAdministrator exists with the key supplied
172:             */
173:            public static ServletCacheAdministrator getInstanceFromKey(
174:                    ServletContext context, String key) {
175:                // Note we do not bother to check if the key is null because it mustn't.
176:                if (!key.endsWith(CACHE_ADMINISTRATOR_KEY_SUFFIX)) {
177:                    key = key + CACHE_ADMINISTRATOR_KEY_SUFFIX;
178:                }
179:                return (ServletCacheAdministrator) context.getAttribute(key);
180:            }
181:
182:            /**
183:             * Obtain an instance of the CacheAdministrator
184:             *
185:             * @param context The ServletContext that this CacheAdministrator is a Singleton under
186:             * @param p the properties to use for the cache if the cache administrator has not been
187:             * created yet. Once the administrator has been created, the properties parameter is
188:             * ignored for all future invocations. If a null value is passed in, then the properties
189:             * are loaded from the oscache.properties file in the classpath.
190:             * @return Returns the CacheAdministrator instance for this context
191:             */
192:            public synchronized static ServletCacheAdministrator getInstance(
193:                    ServletContext context, Properties p) {
194:                String adminKey = null;
195:                if (p != null) {
196:                    adminKey = p.getProperty(CACHE_KEY_KEY);
197:                }
198:                if (adminKey == null) {
199:                    adminKey = DEFAULT_CACHE_KEY;
200:                }
201:                adminKey += CACHE_ADMINISTRATOR_KEY_SUFFIX;
202:
203:                ServletCacheAdministrator admin = (ServletCacheAdministrator) context
204:                        .getAttribute(adminKey);
205:
206:                // First time we need to create the administrator and store it in the
207:                // servlet context
208:                if (admin == null) {
209:                    admin = new ServletCacheAdministrator(context, p);
210:                    Map admins = (Map) context
211:                            .getAttribute(CACHE_ADMINISTRATORS_KEY);
212:                    if (admins == null) {
213:                        admins = new HashMap();
214:                    }
215:                    admins.put(adminKey, admin);
216:                    context.setAttribute(CACHE_ADMINISTRATORS_KEY, admins);
217:                    context.setAttribute(adminKey, admin);
218:
219:                    if (log.isInfoEnabled()) {
220:                        log
221:                                .info("Created new instance of ServletCacheAdministrator with key "
222:                                        + adminKey);
223:                    }
224:
225:                    admin.getAppScopeCache(context);
226:                }
227:
228:                if (admin.context == null) {
229:                    admin.context = context;
230:                }
231:
232:                return admin;
233:            }
234:
235:            /**
236:             * Shuts down all servlet cache administrators. This should usually only 
237:             * be called when the controlling application shuts down.
238:             */
239:            public static void destroyInstance(ServletContext context) {
240:                ServletCacheAdministrator admin;
241:                Map admins = (Map) context
242:                        .getAttribute(CACHE_ADMINISTRATORS_KEY);
243:                if (admins != null) {
244:                    Set keys = admins.keySet();
245:                    Iterator it = keys.iterator();
246:                    while (it.hasNext()) {
247:                        String adminKey = (String) it.next();
248:                        admin = (ServletCacheAdministrator) admins
249:                                .get(adminKey);
250:                        if (admin != null) {
251:                            // Finalize the application scope cache
252:                            Cache cache = (Cache) context.getAttribute(admin
253:                                    .getCacheKey());
254:                            if (cache != null) {
255:                                admin.finalizeListeners(cache);
256:                                context.removeAttribute(admin.getCacheKey());
257:                                context.removeAttribute(adminKey);
258:                                cache = null;
259:                                if (log.isInfoEnabled()) {
260:                                    log
261:                                            .info("Shut down the ServletCacheAdministrator "
262:                                                    + adminKey);
263:                                }
264:                            }
265:                            admin = null;
266:                        }
267:                    }
268:                    context.removeAttribute(CACHE_ADMINISTRATORS_KEY);
269:                }
270:            }
271:
272:            /**
273:             * Grabs the cache for the specified scope
274:             *
275:             * @param request The current request
276:             * @param scope The scope of this cache (<code>PageContext.APPLICATION_SCOPE</code>
277:             * or <code>PageContext.SESSION_SCOPE</code>)
278:             * @return The cache
279:             */
280:            public Cache getCache(HttpServletRequest request, int scope) {
281:                if (scope == PageContext.APPLICATION_SCOPE) {
282:                    return getAppScopeCache(context);
283:                }
284:
285:                if (scope == PageContext.SESSION_SCOPE) {
286:                    return getSessionScopeCache(request.getSession(true));
287:                }
288:
289:                throw new RuntimeException(
290:                        "The supplied scope value of "
291:                                + scope
292:                                + " is invalid. Acceptable values are PageContext.APPLICATION_SCOPE and PageContext.SESSION_SCOPE");
293:            }
294:
295:            /**
296:             * A convenience method to retrieve the application scope cache
297:
298:             * @param context the current <code>ServletContext</code>
299:             * @return the application scope cache. If none is present, one will
300:             * be created.
301:             */
302:            public Cache getAppScopeCache(ServletContext context) {
303:                Cache cache;
304:                Object obj = context.getAttribute(getCacheKey());
305:
306:                if ((obj == null) || !(obj instanceof  Cache)) {
307:                    if (log.isInfoEnabled()) {
308:                        log
309:                                .info("Created new application-scoped cache at key: "
310:                                        + getCacheKey());
311:                    }
312:
313:                    cache = createCache(PageContext.APPLICATION_SCOPE, null);
314:                    context.setAttribute(getCacheKey(), cache);
315:                } else {
316:                    cache = (Cache) obj;
317:                }
318:
319:                return cache;
320:            }
321:
322:            /**
323:             * A convenience method to retrieve the session scope cache
324:             *
325:             * @param session the current <code>HttpSession</code>
326:             * @return the session scope cache for this session. If none is present,
327:             * one will be created.
328:             */
329:            public Cache getSessionScopeCache(HttpSession session) {
330:                Cache cache;
331:                Object obj = session.getAttribute(getCacheKey());
332:
333:                if ((obj == null) || !(obj instanceof  Cache)) {
334:                    if (log.isInfoEnabled()) {
335:                        log
336:                                .info("Created new session-scoped cache in session "
337:                                        + session.getId()
338:                                        + " at key: "
339:                                        + getCacheKey());
340:                    }
341:
342:                    cache = createCache(PageContext.SESSION_SCOPE, session
343:                            .getId());
344:                    session.setAttribute(getCacheKey(), cache);
345:                } else {
346:                    cache = (Cache) obj;
347:                }
348:
349:                return cache;
350:            }
351:
352:            /**
353:             * Get the cache key from the properties. Set it to a default value if it
354:             * is not present in the properties
355:             *
356:             * @return The cache.key property or the DEFAULT_CACHE_KEY
357:             */
358:            public String getCacheKey() {
359:                if (cacheKey == null) {
360:                    cacheKey = getProperty(CACHE_KEY_KEY);
361:
362:                    if (cacheKey == null) {
363:                        cacheKey = DEFAULT_CACHE_KEY;
364:                    }
365:                }
366:
367:                return cacheKey;
368:            }
369:
370:            /**
371:             * Set the flush time for a specific scope to a specific time
372:             *
373:             * @param date  The time to flush the scope
374:             * @param scope The scope to be flushed
375:             */
376:            public void setFlushTime(Date date, int scope) {
377:                if (log.isInfoEnabled()) {
378:                    log.info("Flushing scope " + scope + " at " + date);
379:                }
380:
381:                synchronized (flushTimes) {
382:                    if (date != null) {
383:                        // Trigger a SCOPE_FLUSHED event
384:                        dispatchScopeEvent(ScopeEventType.SCOPE_FLUSHED, scope,
385:                                date, null);
386:                        flushTimes.put(new Integer(scope), date);
387:                    } else {
388:                        logError("setFlushTime called with a null date.");
389:                        throw new IllegalArgumentException(
390:                                "setFlushTime called with a null date.");
391:                    }
392:                }
393:            }
394:
395:            /**
396:             * Set the flush time for a specific scope to the current time.
397:             *
398:             * @param scope The scope to be flushed
399:             */
400:            public void setFlushTime(int scope) {
401:                setFlushTime(new Date(), scope);
402:            }
403:
404:            /**
405:             *        Get the flush time for a particular scope.
406:             *
407:             *        @param        scope        The scope to get the flush time for.
408:             *        @return A date representing the time this scope was last flushed.
409:             *        Returns null if it has never been flushed.
410:             */
411:            public Date getFlushTime(int scope) {
412:                synchronized (flushTimes) {
413:                    return (Date) flushTimes.get(new Integer(scope));
414:                }
415:            }
416:
417:            /**
418:             * Retrieve an item from the cache
419:             *
420:             * @param scope The cache scope
421:             * @param request The servlet request
422:             * @param key The key of the object to retrieve
423:             * @param refreshPeriod The time interval specifying if an entry needs refresh
424:             * @return The requested object
425:             * @throws NeedsRefreshException
426:             */
427:            public Object getFromCache(int scope, HttpServletRequest request,
428:                    String key, int refreshPeriod) throws NeedsRefreshException {
429:                Cache cache = getCache(request, scope);
430:                key = this .generateEntryKey(key, request, scope);
431:                return cache.getFromCache(key, refreshPeriod);
432:            }
433:
434:            /**
435:             * Checks if the given scope was flushed more recently than the CacheEntry provided.
436:             * Used to determine whether to refresh the particular CacheEntry.
437:             *
438:             * @param cacheEntry The cache entry which we're seeing whether to refresh
439:             * @param scope The scope we're checking
440:             *
441:             * @return Whether or not the scope has been flushed more recently than this cache entry was updated.
442:             */
443:            public boolean isScopeFlushed(CacheEntry cacheEntry, int scope) {
444:                Date flushDateTime = getFlushTime(scope);
445:
446:                if (flushDateTime != null) {
447:                    long lastUpdate = cacheEntry.getLastUpdate();
448:                    return (flushDateTime.getTime() >= lastUpdate);
449:                } else {
450:                    return false;
451:                }
452:            }
453:
454:            /**
455:             * Register a listener for Cache Map events.
456:             *
457:             * @param listener  The object that listens to events.
458:             */
459:            public void addScopeEventListener(ScopeEventListener listener) {
460:                listenerList.add(ScopeEventListener.class, listener);
461:            }
462:
463:            /**
464:             * Cancels a pending cache update. This should only be called by a thread
465:             * that received a {@link NeedsRefreshException} and was unable to generate
466:             * some new cache content.
467:             *
468:             * @param scope The cache scope
469:             * @param request The servlet request
470:             * @param key The cache entry key to cancel the update of.
471:             */
472:            public void cancelUpdate(int scope, HttpServletRequest request,
473:                    String key) {
474:                Cache cache = getCache(request, scope);
475:                key = this .generateEntryKey(key, request, scope);
476:                cache.cancelUpdate(key);
477:            }
478:
479:            /**
480:             * Flush all scopes at a particular time
481:             *
482:             * @param date The time to flush the scope
483:             */
484:            public void flushAll(Date date) {
485:                synchronized (flushTimes) {
486:                    setFlushTime(date, PageContext.APPLICATION_SCOPE);
487:                    setFlushTime(date, PageContext.SESSION_SCOPE);
488:                    setFlushTime(date, PageContext.REQUEST_SCOPE);
489:                    setFlushTime(date, PageContext.PAGE_SCOPE);
490:                }
491:
492:                // Trigger a flushAll event
493:                dispatchScopeEvent(ScopeEventType.ALL_SCOPES_FLUSHED, -1, date,
494:                        null);
495:            }
496:
497:            /**
498:             * Flush all scopes instantly.
499:             */
500:            public void flushAll() {
501:                flushAll(new Date());
502:            }
503:
504:            /**
505:             * Generates a cache entry key.
506:             *
507:             * If the string key is not specified, the HTTP request URI and QueryString is used.
508:             * Operating systems that have a filename limitation less than 255 or have
509:             * filenames that are case insensitive may have issues with key generation where
510:             * two distinct pages map to the same key.
511:             * <p>
512:             * POST Requests (which have no distinguishing
513:             * query string) may also generate identical keys for what is actually different pages.
514:             * In these cases, specify an explicit key attribute for the CacheTag.
515:             *
516:             * @param key The key entered by the user
517:             * @param request The current request
518:             * @param scope The scope this cache entry is under
519:             * @return The generated cache key
520:             */
521:            public String generateEntryKey(String key,
522:                    HttpServletRequest request, int scope) {
523:                return generateEntryKey(key, request, scope, null, null);
524:            }
525:
526:            /**
527:             * Generates a cache entry key.
528:             *
529:             * If the string key is not specified, the HTTP request URI and QueryString is used.
530:             * Operating systems that have a filename limitation less than 255 or have
531:             * filenames that are case insensitive may have issues with key generation where
532:             * two distinct pages map to the same key.
533:             * <p>
534:             * POST Requests (which have no distinguishing
535:             * query string) may also generate identical keys for what is actually different pages.
536:             * In these cases, specify an explicit key attribute for the CacheTag.
537:             *
538:             * @param key The key entered by the user
539:             * @param request The current request
540:             * @param scope The scope this cache entry is under
541:             * @param language The ISO-639 language code to distinguish different pages in application scope
542:             * @return The generated cache key
543:             */
544:            public String generateEntryKey(String key,
545:                    HttpServletRequest request, int scope, String language) {
546:                return generateEntryKey(key, request, scope, language, null);
547:            }
548:
549:            /**
550:             * Generates a cache entry key.
551:             * <p>
552:             * If the string key is not specified, the HTTP request URI and QueryString is used.
553:             * Operating systems that have a filename limitation less than 255 or have
554:             * filenames that are case insensitive may have issues with key generation where
555:             * two distinct pages map to the same key.
556:             * <p>
557:             * POST Requests (which have no distinguishing
558:             * query string) may also generate identical keys for what is actually different pages.
559:             * In these cases, specify an explicit key attribute for the CacheTag.
560:             *
561:             * @param key The key entered by the user
562:             * @param request The current request
563:             * @param scope The scope this cache entry is under
564:             * @param language The ISO-639 language code to distinguish different pages in application scope
565:             * @param suffix The ability to put a suffix at the end of the key
566:             * @return The generated cache key
567:             */
568:            public String generateEntryKey(String key,
569:                    HttpServletRequest request, int scope, String language,
570:                    String suffix) {
571:                /**
572:                 * Used for generating cache entry keys.
573:                 */
574:                StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH);
575:
576:                // Append the language if available
577:                if (language != null) {
578:                    cBuffer.append(FILE_SEPARATOR).append(language);
579:                }
580:
581:                // Servers for multiple host domains need this distinction in the key
582:                if (useHostDomainInKey) {
583:                    cBuffer.append(FILE_SEPARATOR).append(
584:                            request.getServerName());
585:                }
586:
587:                if (key != null) {
588:                    cBuffer.append(FILE_SEPARATOR).append(key);
589:                } else {
590:                    String generatedKey = request.getRequestURI();
591:
592:                    if (generatedKey.charAt(0) != FILE_SEPARATOR_CHAR) {
593:                        cBuffer.append(FILE_SEPARATOR_CHAR);
594:                    }
595:
596:                    cBuffer.append(generatedKey);
597:                    cBuffer.append("_").append(request.getMethod()).append("_");
598:
599:                    generatedKey = getSortedQueryString(request);
600:
601:                    if (generatedKey != null) {
602:                        try {
603:                            java.security.MessageDigest digest = java.security.MessageDigest
604:                                    .getInstance("MD5");
605:                            byte[] b = digest.digest(generatedKey.getBytes());
606:                            cBuffer.append('_');
607:
608:                            // Base64 encoding allows for unwanted slash characters.
609:                            cBuffer.append(toBase64(b).replace('/', '_'));
610:                        } catch (Exception e) {
611:                            // Ignore query string
612:                        }
613:                    }
614:                }
615:
616:                // Do we want a suffix
617:                if ((suffix != null) && (suffix.length() > 0)) {
618:                    cBuffer.append(suffix);
619:                }
620:
621:                return cBuffer.toString();
622:            }
623:
624:            /**
625:             * Creates a string that contains all of the request parameters and their
626:             * values in a single string. This is very similar to
627:             * <code>HttpServletRequest.getQueryString()</code> except the parameters are
628:             * sorted by name, and if there is a <code>jsessionid</code> parameter it is
629:             * filtered out.<p>
630:             * If the request has no parameters, this method returns <code>null</code>.
631:             */
632:            protected String getSortedQueryString(HttpServletRequest request) {
633:                Map paramMap = request.getParameterMap();
634:
635:                if (paramMap.isEmpty()) {
636:                    return null;
637:                }
638:
639:                Set paramSet = new TreeMap(paramMap).entrySet();
640:
641:                StringBuffer buf = new StringBuffer();
642:
643:                boolean first = true;
644:
645:                for (Iterator it = paramSet.iterator(); it.hasNext();) {
646:                    Map.Entry entry = (Map.Entry) it.next();
647:                    String[] values = (String[]) entry.getValue();
648:
649:                    for (int i = 0; i < values.length; i++) {
650:                        String key = (String) entry.getKey();
651:
652:                        if ((key.length() != 10) || !"jsessionid".equals(key)) {
653:                            if (first) {
654:                                first = false;
655:                            } else {
656:                                buf.append('&');
657:                            }
658:
659:                            buf.append(key).append('=').append(values[i]);
660:                        }
661:                    }
662:                }
663:
664:                // We get a 0 length buffer if the only parameter was a jsessionid
665:                if (buf.length() == 0) {
666:                    return null;
667:                } else {
668:                    return buf.toString();
669:                }
670:            }
671:
672:            /**
673:             * Log error messages to commons logging.
674:             *
675:             * @param message   Message to log.
676:             */
677:            public void logError(String message) {
678:                log.error("[oscache]: " + message);
679:            }
680:
681:            /**
682:             * Put an object in the cache. This should only be called by a thread
683:             * that received a {@link NeedsRefreshException}. Using session scope
684:             * the thread has to insure that the session wasn't invalidated in
685:             * the meantime. CacheTag and CacheFilter guarantee that the same
686:             * cache is used in cancelUpdate and getFromCache.
687:             *
688:             * @param scope The cache scope
689:             * @param request The servlet request
690:             * @param key The object key
691:             * @param content The object to add
692:             */
693:            public void putInCache(int scope, HttpServletRequest request,
694:                    String key, Object content) {
695:                putInCache(scope, request, key, content, null);
696:            }
697:
698:            /**
699:             * Put an object in the cache. This should only be called by a thread
700:             * that received a {@link NeedsRefreshException}. Using session scope
701:             * the thread has to insure that the session wasn't invalidated in
702:             * the meantime. CacheTag and CacheFilter guarantee that the same
703:             * cache is used in cancelUpdate and getFromCache.
704:             *
705:             * @param scope The cache scope
706:             * @param request The servlet request
707:             * @param key The object key
708:             * @param content The object to add
709:             * @param policy The refresh policy
710:             */
711:            public void putInCache(int scope, HttpServletRequest request,
712:                    String key, Object content, EntryRefreshPolicy policy) {
713:                Cache cache = getCache(request, scope);
714:                key = this .generateEntryKey(key, request, scope);
715:                cache.putInCache(key, content, policy);
716:            }
717:
718:            /**
719:             * Sets the cache capacity (number of items). If the cache contains
720:             * more than <code>capacity</code> items then items will be removed
721:             * to bring the cache back down to the new size.
722:             *
723:             * @param scope The cache scope
724:             * @param request The servlet request
725:             * @param capacity The new capacity
726:             */
727:            public void setCacheCapacity(int scope, HttpServletRequest request,
728:                    int capacity) {
729:                setCacheCapacity(capacity);
730:                getCache(request, scope).setCapacity(capacity);
731:            }
732:
733:            /**
734:             * Unregister a listener for Cache Map events.
735:             *
736:             * @param listener  The object that currently listens to events.
737:             */
738:            public void removeScopeEventListener(ScopeEventListener listener) {
739:                listenerList.remove(ScopeEventListener.class, listener);
740:            }
741:
742:            /**
743:             * Finalizes all the listeners that are associated with the given cache object
744:             */
745:            protected void finalizeListeners(Cache cache) {
746:                super .finalizeListeners(cache);
747:            }
748:
749:            /**
750:             * Convert a byte array into a Base64 string (as used in mime formats)
751:             */
752:            private static String toBase64(byte[] aValue) {
753:                int byte1;
754:                int byte2;
755:                int byte3;
756:                int iByteLen = aValue.length;
757:                StringBuffer tt = new StringBuffer();
758:
759:                for (int i = 0; i < iByteLen; i += 3) {
760:                    boolean bByte2 = (i + 1) < iByteLen;
761:                    boolean bByte3 = (i + 2) < iByteLen;
762:                    byte1 = aValue[i] & 0xFF;
763:                    byte2 = (bByte2) ? (aValue[i + 1] & 0xFF) : 0;
764:                    byte3 = (bByte3) ? (aValue[i + 2] & 0xFF) : 0;
765:
766:                    tt.append(m_strBase64Chars.charAt(byte1 / 4));
767:                    tt.append(m_strBase64Chars.charAt((byte2 / 16)
768:                            + ((byte1 & 0x3) * 16)));
769:                    tt.append(((bByte2) ? m_strBase64Chars.charAt((byte3 / 64)
770:                            + ((byte2 & 0xF) * 4)) : '='));
771:                    tt.append(((bByte3) ? m_strBase64Chars.charAt(byte3 & 0x3F)
772:                            : '='));
773:                }
774:
775:                return tt.toString();
776:            }
777:
778:            /**
779:             * Create a cache
780:             *
781:             * @param scope The cache scope
782:             * @param sessionId The sessionId for with the cache will be created
783:             * @return A new cache
784:             */
785:            private ServletCache createCache(int scope, String sessionId) {
786:                ServletCache newCache = new ServletCache(this , algorithmClass,
787:                        cacheCapacity, scope);
788:
789:                // TODO - Fix me please!
790:                // Hack! This is nasty - if two sessions are created within a short
791:                // space of time it is possible they will end up with duplicate
792:                // session IDs being passed to the DiskPersistenceListener!...
793:                config.set(HASH_KEY_SCOPE, "" + scope);
794:                config.set(HASH_KEY_SESSION_ID, sessionId);
795:
796:                newCache = (ServletCache) configureStandardListeners(newCache);
797:
798:                if (config.getProperty(CACHE_ENTRY_EVENT_LISTENERS_KEY) != null) {
799:                    // Add any event listeners that have been specified in the configuration
800:                    CacheEventListener[] listeners = getCacheEventListeners();
801:
802:                    for (int i = 0; i < listeners.length; i++) {
803:                        if (listeners[i] instanceof  ScopeEventListener) {
804:                            newCache.addCacheEventListener(listeners[i]);
805:                        }
806:                    }
807:                }
808:
809:                return newCache;
810:            }
811:
812:            /**
813:             * Dispatch a scope event to all registered listeners.
814:             *
815:             * @param eventType   The type of event
816:             * @param scope       Scope that was flushed (Does not apply for FLUSH_ALL event)
817:             * @param date        Date of flushing
818:             * @param origin      The origin of the event
819:             */
820:            private void dispatchScopeEvent(ScopeEventType eventType,
821:                    int scope, Date date, String origin) {
822:                // Create the event
823:                ScopeEvent event = new ScopeEvent(eventType, scope, date,
824:                        origin);
825:
826:                // Guaranteed to return a non-null array
827:                Object[] listeners = listenerList.getListenerList();
828:
829:                // Process the listeners last to first, notifying
830:                // those that are interested in this event
831:                for (int i = listeners.length - 2; i >= 0; i -= 2) {
832:                    if (listeners[i + 1] instanceof  ScopeEventListener) {
833:                        ((ScopeEventListener) listeners[i + 1])
834:                                .scopeFlushed(event);
835:                    }
836:                }
837:            }
838:
839:            /**
840:             *        Set property cache.use.host.domain.in.key=true to add domain information to key
841:             *  generation for hosting multiple sites
842:             */
843:            private void initHostDomainInKey() {
844:                String propStr = getProperty(CACHE_USE_HOST_DOMAIN_KEY);
845:
846:                useHostDomainInKey = "true".equalsIgnoreCase(propStr);
847:            }
848:        }
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.