Source Code Cross Referenced for ContinuationsManagerImpl.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » components » flow » 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 » Content Management System » apache lenya 2.0 » org.apache.cocoon.components.flow 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.components.flow;
018:
019:        import org.apache.avalon.framework.component.Component;
020:        import org.apache.avalon.framework.configuration.Configurable;
021:        import org.apache.avalon.framework.configuration.Configuration;
022:        import org.apache.avalon.framework.context.Context;
023:        import org.apache.avalon.framework.context.ContextException;
024:        import org.apache.avalon.framework.context.Contextualizable;
025:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
026:        import org.apache.avalon.framework.service.ServiceException;
027:        import org.apache.avalon.framework.service.ServiceManager;
028:        import org.apache.avalon.framework.service.Serviceable;
029:        import org.apache.avalon.framework.thread.ThreadSafe;
030:        import org.apache.cocoon.components.ContextHelper;
031:        import org.apache.cocoon.components.thread.RunnableManager;
032:        import org.apache.cocoon.environment.ObjectModelHelper;
033:        import org.apache.cocoon.environment.Request;
034:        import org.apache.cocoon.environment.Session;
035:
036:        import org.apache.excalibur.instrument.CounterInstrument;
037:        import org.apache.excalibur.instrument.Instrument;
038:        import org.apache.excalibur.instrument.Instrumentable;
039:        import org.apache.excalibur.instrument.ValueInstrument;
040:
041:        import java.security.SecureRandom;
042:        import java.util.ArrayList;
043:        import java.util.Collections;
044:        import java.util.HashMap;
045:        import java.util.HashSet;
046:        import java.util.Iterator;
047:        import java.util.List;
048:        import java.util.Map;
049:        import java.util.Set;
050:        import java.util.SortedSet;
051:        import java.util.TreeSet;
052:
053:        import javax.servlet.http.HttpSessionBindingEvent;
054:        import javax.servlet.http.HttpSessionBindingListener;
055:
056:        /**
057:         * The default implementation of {@link ContinuationsManager}. <br/>There are
058:         * two modes of work: <br/>
059:         * <ul>
060:         * <li><b>standard mode </b>- continuations are stored in single holder. No
061:         * security is applied to continuation lookup. Anyone can invoke a continuation
062:         * only knowing the ID. Set "session-bound-continuations" configuration option
063:         * to false to activate this mode.</li>
064:         * <li><b>secure mode </b>- each session has it's own continuations holder. A
065:         * continuation is only valid for the same session it was created for. Session
066:         * invalidation causes all bound continuations to be invalidated as well. Use
067:         * this setting for web applications. Set "session-bound-continuations"
068:         * configuration option to true to activate this mode.</li>
069:         * </ul>
070:         * 
071:         * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu </a>
072:         * @author <a href="mailto:Michael.Melhem@managesoft.com">Michael Melhem </a>
073:         * @since March 19, 2002
074:         * @see ContinuationsManager
075:         * @version CVS $Id: ContinuationsManagerImpl.java 433543 2006-08-22 06:22:54Z crossley $
076:         */
077:        public class ContinuationsManagerImpl extends AbstractLogEnabled
078:                implements  ContinuationsManager, Component, Configurable,
079:                ThreadSafe, Instrumentable, Serviceable, Contextualizable {
080:
081:            static final int CONTINUATION_ID_LENGTH = 20;
082:            static final String EXPIRE_CONTINUATIONS = "expire-continuations";
083:
084:            /**
085:             * Random number generator used to create continuation ID
086:             */
087:            protected SecureRandom random;
088:            protected byte[] bytes;
089:
090:            /**
091:             * How long does a continuation exist in memory since the last
092:             * access? The time is in miliseconds, and the default is 1 hour.
093:             */
094:            protected int defaultTimeToLive;
095:
096:            /**
097:             * Maintains the forest of <code>WebContinuation</code> trees.
098:             * This set is used only for debugging puroses by
099:             * {@link #displayAllContinuations()} method.
100:             */
101:            protected Set forest = Collections.synchronizedSet(new HashSet());
102:
103:            /**
104:             * Main continuations holder. Used unless continuations are stored in user
105:             * session.
106:             */
107:            protected WebContinuationsHolder continuationsHolder;
108:
109:            /**
110:             * Sorted set of <code>WebContinuation</code> instances, based on
111:             * their expiration time. This is used by the background thread to
112:             * invalidate continuations.
113:             */
114:            protected SortedSet expirations = Collections
115:                    .synchronizedSortedSet(new TreeSet());
116:
117:            protected String instrumentableName;
118:            protected ValueInstrument continuationsCount;
119:            protected int continuationsCounter;
120:            protected ValueInstrument forestSize;
121:            protected ValueInstrument expirationsSize;
122:            protected CounterInstrument continuationsCreated;
123:            protected CounterInstrument continuationsInvalidated;
124:            protected boolean isContinuationSharingBugCompatible;
125:            protected boolean bindContinuationsToSession;
126:
127:            protected ServiceManager serviceManager;
128:            protected Context context;
129:
130:            public ContinuationsManagerImpl() throws Exception {
131:
132:                try {
133:                    random = SecureRandom.getInstance("SHA1PRNG");
134:                } catch (java.security.NoSuchAlgorithmException nsae) {
135:                    // Maybe we are on IBM's SDK
136:                    random = SecureRandom.getInstance("IBMSecureRandom");
137:                }
138:                random.setSeed(System.currentTimeMillis());
139:                bytes = new byte[CONTINUATION_ID_LENGTH];
140:
141:                continuationsCount = new ValueInstrument("count");
142:                continuationsCounter = 0;
143:                forestSize = new ValueInstrument("forest-size");
144:                expirationsSize = new ValueInstrument("expirations-size");
145:                continuationsCreated = new CounterInstrument("creates");
146:                continuationsInvalidated = new CounterInstrument("invalidates");
147:            }
148:
149:            /**
150:             * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
151:             */
152:            public void service(final ServiceManager manager)
153:                    throws ServiceException {
154:                this .serviceManager = manager;
155:            }
156:
157:            /**
158:             * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
159:             */
160:            public void configure(Configuration config) {
161:                this .defaultTimeToLive = config.getAttributeAsInteger(
162:                        "time-to-live", (3600 * 1000));
163:                this .isContinuationSharingBugCompatible = config
164:                        .getAttributeAsBoolean(
165:                                "continuation-sharing-bug-compatible", false);
166:                this .bindContinuationsToSession = config.getAttributeAsBoolean(
167:                        "session-bound-continuations", false);
168:
169:                // create a global ContinuationsHolder if this the "session-bound-continuations" parameter is set to false
170:                if (!this .bindContinuationsToSession) {
171:                    this .continuationsHolder = new WebContinuationsHolder();
172:                }
173:
174:                // create a thread that invalidates the continuations
175:                final Configuration expireConf = config
176:                        .getChild("expirations-check");
177:                final long initialDelay = expireConf.getChild("offset", true)
178:                        .getValueAsLong(180000);
179:                final long interval = expireConf.getChild("period", true)
180:                        .getValueAsLong(180000);
181:                try {
182:                    final RunnableManager runnableManager = (RunnableManager) serviceManager
183:                            .lookup(RunnableManager.ROLE);
184:                    runnableManager.execute(new Runnable() {
185:                        public void run() {
186:                            expireContinuations();
187:                        }
188:                    }, initialDelay, interval);
189:                    serviceManager.release(runnableManager);
190:                } catch (Exception e) {
191:                    getLogger()
192:                            .warn(
193:                                    "Could not enqueue continuations expiration task. "
194:                                            + "Continuations will not automatically expire.",
195:                                    e);
196:                }
197:            }
198:
199:            /**
200:             * @see org.apache.excalibur.instrument.Instrumentable#setInstrumentableName(java.lang.String)
201:             */
202:            public void setInstrumentableName(String instrumentableName) {
203:                this .instrumentableName = instrumentableName;
204:            }
205:
206:            /**
207:             * @see org.apache.excalibur.instrument.Instrumentable#getInstrumentableName()
208:             */
209:            public String getInstrumentableName() {
210:                return instrumentableName;
211:            }
212:
213:            /**
214:             * @see org.apache.excalibur.instrument.Instrumentable#getInstruments()
215:             */
216:            public Instrument[] getInstruments() {
217:                return new Instrument[] { continuationsCount,
218:                        continuationsCreated, continuationsInvalidated,
219:                        forestSize };
220:            }
221:
222:            /**
223:             * @see org.apache.excalibur.instrument.Instrumentable#getChildInstrumentables()
224:             */
225:            public Instrumentable[] getChildInstrumentables() {
226:                return Instrumentable.EMPTY_INSTRUMENTABLE_ARRAY;
227:            }
228:
229:            /**
230:             * @see org.apache.cocoon.components.flow.ContinuationsManager#createWebContinuation(java.lang.Object, org.apache.cocoon.components.flow.WebContinuation, int, java.lang.String, org.apache.cocoon.components.flow.ContinuationsDisposer)
231:             */
232:            public WebContinuation createWebContinuation(Object kont,
233:                    WebContinuation parent, int timeToLive,
234:                    String interpreterId, ContinuationsDisposer disposer) {
235:                int ttl = (timeToLive == 0 ? defaultTimeToLive : timeToLive);
236:
237:                WebContinuation wk = generateContinuation(kont, parent, ttl,
238:                        interpreterId, disposer);
239:                wk.enableLogging(getLogger());
240:
241:                if (parent == null) {
242:                    forest.add(wk);
243:                    forestSize.setValue(forest.size());
244:                } else {
245:                    handleParentContinuationExpiration(parent);
246:                }
247:
248:                handleLeafContinuationExpiration(wk);
249:
250:                if (getLogger().isDebugEnabled()) {
251:                    getLogger().debug("WK: Created continuation " + wk.getId());
252:                }
253:
254:                return wk;
255:            }
256:
257:            /**
258:             * When a new continuation is created in @link #createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer),
259:             * it is registered in the expiration set in order to be evaluated by the invalidation mechanism.
260:             */
261:            protected void handleLeafContinuationExpiration(WebContinuation wk) {
262:                expirations.add(wk);
263:                expirationsSize.setValue(expirations.size());
264:            }
265:
266:            /**
267:             * When a new continuation is created in @link #createWebContinuation(Object, WebContinuation, int, String, ContinuationsDisposer),
268:             * its parent continuation is removed from the expiration set. This way only leaf continuations are part of
269:             * the expiration set.
270:             */
271:            protected void handleParentContinuationExpiration(
272:                    WebContinuation parent) {
273:                if (parent.getChildren().size() < 2) {
274:                    expirations.remove(parent);
275:                }
276:            }
277:
278:            /**
279:             * @see org.apache.cocoon.components.flow.ContinuationsManager#lookupWebContinuation(java.lang.String, java.lang.String)
280:             */
281:            public WebContinuation lookupWebContinuation(String id,
282:                    String interpreterId) {
283:                // REVISIT: Is the following check needed to avoid threading issues:
284:                // return wk only if !(wk.hasExpired) ?
285:                WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(false);
286:                if (continuationsHolder == null) {
287:                    return null;
288:                }
289:
290:                WebContinuation kont = continuationsHolder.get(id);
291:                if (kont != null) {
292:                    boolean interpreterMatches = kont
293:                            .interpreterMatches(interpreterId);
294:                    if (!interpreterMatches && getLogger().isWarnEnabled()) {
295:                        getLogger()
296:                                .warn(
297:                                        "WK: Continuation ("
298:                                                + kont.getId()
299:                                                + ") lookup for wrong interpreter. Bound to: "
300:                                                + kont.getInterpreterId()
301:                                                + ", looked up for: "
302:                                                + interpreterId);
303:                    }
304:                    return interpreterMatches
305:                            || isContinuationSharingBugCompatible ? kont : null;
306:                }
307:                return null;
308:            }
309:
310:            /**
311:             * Create <code>WebContinuation</code> and generate unique identifier
312:             * for it. The identifier is generated using a cryptographically strong
313:             * algorithm to prevent people to generate their own identifiers.
314:             *
315:             * @param kont an <code>Object</code> value representing continuation
316:             * @param parent value representing parent <code>WebContinuation</code>
317:             * @param ttl <code>WebContinuation</code> time to live
318:             * @param interpreterId id of interpreter invoking continuation creation
319:             * @param disposer <code>ContinuationsDisposer</code> instance to use for
320:             * cleanup of the continuation.
321:             * @return the generated <code>WebContinuation</code> with unique identifier
322:             */
323:            protected WebContinuation generateContinuation(Object kont,
324:                    WebContinuation parent, int ttl, String interpreterId,
325:                    ContinuationsDisposer disposer) {
326:
327:                char[] result = new char[bytes.length * 2];
328:                WebContinuation wk = null;
329:                WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(true);
330:                while (true) {
331:                    random.nextBytes(bytes);
332:
333:                    for (int i = 0; i < CONTINUATION_ID_LENGTH; i++) {
334:                        byte ch = bytes[i];
335:                        result[2 * i] = Character.forDigit(Math.abs(ch >> 4),
336:                                16);
337:                        result[2 * i + 1] = Character.forDigit(Math
338:                                .abs(ch & 0x0f), 16);
339:                    }
340:
341:                    final String id = new String(result);
342:                    synchronized (continuationsHolder) {
343:                        if (!continuationsHolder.contains(id)) {
344:                            if (this .bindContinuationsToSession) {
345:                                wk = new HolderAwareWebContinuation(id, kont,
346:                                        parent, ttl, interpreterId, disposer,
347:                                        continuationsHolder);
348:                            } else {
349:                                wk = new WebContinuation(id, kont, parent, ttl,
350:                                        interpreterId, disposer);
351:                            }
352:                            continuationsHolder.addContinuation(wk);
353:                            synchronized (continuationsCount) {
354:                                continuationsCounter++;
355:                                continuationsCount
356:                                        .setValue(continuationsCounter);
357:                            }
358:                            break;
359:                        }
360:                    }
361:                }
362:
363:                continuationsCreated.increment();
364:                return wk;
365:            }
366:
367:            /**
368:             * @see org.apache.cocoon.components.flow.ContinuationsManager#invalidateWebContinuation(org.apache.cocoon.components.flow.WebContinuation)
369:             */
370:            public void invalidateWebContinuation(WebContinuation wk) {
371:                WebContinuationsHolder continuationsHolder = lookupWebContinuationsHolder(false);
372:                if (!continuationsHolder.contains(wk)) {
373:                    //TODO this looks like a security breach - should we throw?
374:                    return;
375:                }
376:                _detach(wk);
377:                _invalidate(continuationsHolder, wk);
378:            }
379:
380:            protected void _invalidate(
381:                    WebContinuationsHolder continuationsHolder,
382:                    WebContinuation wk) {
383:                if (getLogger().isDebugEnabled()) {
384:                    getLogger().debug(
385:                            "WK: Manual expire of continuation " + wk.getId());
386:                }
387:                disposeContinuation(continuationsHolder, wk);
388:                expirations.remove(wk);
389:                expirationsSize.setValue(expirations.size());
390:
391:                // Invalidate all the children continuations as well
392:                List children = wk.getChildren();
393:                int size = children.size();
394:                for (int i = 0; i < size; i++) {
395:                    _invalidate(continuationsHolder, (WebContinuation) children
396:                            .get(i));
397:                }
398:            }
399:
400:            /**
401:             * Detach this continuation from parent. This method removes
402:             * continuation from {@link #forest} set, or, if it has parent,
403:             * from parent's children collection.
404:             * @param wk Continuation to detach from parent.
405:             */
406:            private void _detach(WebContinuation wk) {
407:                WebContinuation parent = wk.getParentContinuation();
408:                if (parent == null) {
409:                    forest.remove(wk);
410:                    forestSize.setValue(forest.size());
411:                } else
412:                    wk.detachFromParent();
413:            }
414:
415:            /**
416:             * Makes the continuation inaccessible for lookup, and triggers possible needed
417:             * cleanup code through the ContinuationsDisposer interface.
418:             * @param continuationsHolder
419:             *
420:             * @param wk the continuation to dispose.
421:             */
422:            protected void disposeContinuation(
423:                    WebContinuationsHolder continuationsHolder,
424:                    WebContinuation wk) {
425:                continuationsHolder.removeContinuation(wk);
426:                synchronized (continuationsCount) {
427:                    continuationsCounter--;
428:                    continuationsCount.setValue(continuationsCounter);
429:                }
430:                wk.dispose();
431:                continuationsInvalidated.increment();
432:            }
433:
434:            /**
435:             * Removes an expired leaf <code>WebContinuation</code> node
436:             * from its continuation tree, and recursively removes its
437:             * parent(s) if it they have expired and have no (other) children.
438:             * @param continuationsHolder
439:             *
440:             * @param wk <code>WebContinuation</code> node
441:             */
442:            protected void removeContinuation(
443:                    WebContinuationsHolder continuationsHolder,
444:                    WebContinuation wk) {
445:                if (wk.getChildren().size() != 0) {
446:                    return;
447:                }
448:
449:                // remove access to this contination
450:                disposeContinuation(continuationsHolder, wk);
451:                _detach(wk);
452:
453:                if (getLogger().isDebugEnabled()) {
454:                    getLogger()
455:                            .debug("WK: Deleted continuation: " + wk.getId());
456:                }
457:
458:                // now check if parent needs to be removed.
459:                WebContinuation parent = wk.getParentContinuation();
460:                if (null != parent && parent.hasExpired()) {
461:                    //parent must have the same continuations holder, lookup not needed
462:                    removeContinuation(continuationsHolder, parent);
463:                }
464:            }
465:
466:            /**
467:             * Dump to Log file the current contents of
468:             * the expirations <code>SortedSet</code>
469:             */
470:            protected void displayExpireSet() {
471:                StringBuffer wkSet = new StringBuffer("\nWK; Expire set size: "
472:                        + expirations.size());
473:                Iterator i = expirations.iterator();
474:                while (i.hasNext()) {
475:                    final WebContinuation wk = (WebContinuation) i.next();
476:                    final long lat = wk.getLastAccessTime()
477:                            + wk.getTimeToLive();
478:                    wkSet.append("\nWK: ").append(wk.getId()).append(
479:                            " ExpireTime [");
480:
481:                    if (lat < System.currentTimeMillis()) {
482:                        wkSet.append("Expired");
483:                    } else {
484:                        wkSet.append(lat);
485:                    }
486:                    wkSet.append("]");
487:                }
488:
489:                getLogger().debug(wkSet.toString());
490:            }
491:
492:            /**
493:             * Dump to Log file all <code>WebContinuation</code>s
494:             * in the system
495:             */
496:            public void displayAllContinuations() {
497:                final Iterator i = forest.iterator();
498:                while (i.hasNext()) {
499:                    ((WebContinuation) i.next()).display();
500:                }
501:            }
502:
503:            /**
504:             * Remove all continuations which have already expired.
505:             */
506:            protected void expireContinuations() {
507:                long now = 0;
508:                if (getLogger().isDebugEnabled()) {
509:                    now = System.currentTimeMillis();
510:
511:                    /* Continuations before clean up: */
512:                    getLogger().debug(
513:                            "WK: Forest before cleanup: " + forest.size());
514:                    displayAllContinuations();
515:                    displayExpireSet();
516:
517:                }
518:
519:                // Clean up expired continuations
520:                int count = 0;
521:                WebContinuation wk;
522:                Iterator i = expirations.iterator();
523:                while (i.hasNext()
524:                        && ((wk = (WebContinuation) i.next()).hasExpired())) {
525:                    i.remove();
526:                    WebContinuationsHolder continuationsHolder = null;
527:                    if (wk instanceof  HolderAwareWebContinuation) {
528:                        continuationsHolder = ((HolderAwareWebContinuation) wk)
529:                                .getContinuationsHolder();
530:                    } else {
531:                        continuationsHolder = this .continuationsHolder;
532:                    }
533:                    removeContinuation(continuationsHolder, wk);
534:                    count++;
535:                }
536:                expirationsSize.setValue(expirations.size());
537:
538:                if (getLogger().isDebugEnabled()) {
539:                    getLogger().debug(
540:                            "WK Cleaned up " + count + " continuations in "
541:                                    + (System.currentTimeMillis() - now)
542:                                    + " ms");
543:
544:                    /* Continuations after clean up: */
545:                    //            getLogger().debug("WK: Forest after cleanup: " + forest.size());
546:                    //            displayAllContinuations();
547:                    //            displayExpireSet();
548:                }
549:            }
550:
551:            /**
552:             * Method used by WebContinuationsHolder to notify the continuations manager
553:             * about session invalidation. Invalidates all continuations held by passed
554:             * continuationsHolder.
555:             */
556:            protected void invalidateContinuations(
557:                    WebContinuationsHolder continuationsHolder) {
558:                // TODO: this avoids ConcurrentModificationException, still this is not
559:                // the best solution and should be changed
560:                Object[] continuationIds = continuationsHolder
561:                        .getContinuationIds().toArray();
562:
563:                for (int i = 0; i < continuationIds.length; i++) {
564:                    WebContinuation wk = continuationsHolder
565:                            .get(continuationIds[i]);
566:                    if (wk != null) {
567:                        _detach(wk);
568:                        _invalidate(continuationsHolder, wk);
569:                    }
570:                }
571:            }
572:
573:            /**
574:             * Lookup a proper web continuations holder. 
575:             * @param createNew
576:             *            should the manager create a continuations holder in session
577:             *            when none found?
578:             */
579:            public WebContinuationsHolder lookupWebContinuationsHolder(
580:                    boolean createNew) {
581:                //there is only one holder if continuations are not bound to session
582:                if (!this .bindContinuationsToSession)
583:                    return this .continuationsHolder;
584:
585:                //if continuations bound to session lookup a proper holder in the session
586:                Map objectModel = ContextHelper.getObjectModel(this .context);
587:                Request request = ObjectModelHelper.getRequest(objectModel);
588:
589:                if (!createNew && request.getSession(false) == null)
590:                    return null;
591:
592:                Session session = request.getSession(true);
593:                WebContinuationsHolder holder = (WebContinuationsHolder) session
594:                        .getAttribute(WebContinuationsHolder.CONTINUATIONS_HOLDER);
595:                if (!createNew)
596:                    return holder;
597:
598:                if (holder != null)
599:                    return holder;
600:
601:                holder = new WebContinuationsHolder();
602:                session.setAttribute(
603:                        WebContinuationsHolder.CONTINUATIONS_HOLDER, holder);
604:                return holder;
605:            }
606:
607:            /**
608:             * A holder for WebContinuations. When bound to session notifies the
609:             * continuations manager of session invalidation.
610:             */
611:            protected class WebContinuationsHolder implements 
612:                    HttpSessionBindingListener {
613:                private final static String CONTINUATIONS_HOLDER = "o.a.c.c.f.SCMI.WebContinuationsHolder";
614:
615:                private Map holder = Collections.synchronizedMap(new HashMap());
616:
617:                public WebContinuation get(Object id) {
618:                    return (WebContinuation) this .holder.get(id);
619:                }
620:
621:                public void addContinuation(WebContinuation wk) {
622:                    this .holder.put(wk.getId(), wk);
623:                }
624:
625:                public void removeContinuation(WebContinuation wk) {
626:                    this .holder.remove(wk.getId());
627:                }
628:
629:                public Set getContinuationIds() {
630:                    return holder.keySet();
631:                }
632:
633:                public boolean contains(String continuationId) {
634:                    return this .holder.containsKey(continuationId);
635:                }
636:
637:                public boolean contains(WebContinuation wk) {
638:                    return contains(wk.getId());
639:                }
640:
641:                public void valueBound(HttpSessionBindingEvent event) {
642:                }
643:
644:                public void valueUnbound(HttpSessionBindingEvent event) {
645:                    invalidateContinuations(this );
646:                }
647:            }
648:
649:            /**
650:             * WebContinuation extension that holds also the information about the
651:             * holder. This information is needed to cleanup a proper holder after
652:             * continuation's expiration time.
653:             */
654:            protected static class HolderAwareWebContinuation extends
655:                    WebContinuation {
656:                private WebContinuationsHolder continuationsHolder;
657:
658:                public HolderAwareWebContinuation(String id,
659:                        Object continuation,
660:                        WebContinuation parentContinuation, int timeToLive,
661:                        String interpreterId, ContinuationsDisposer disposer,
662:                        WebContinuationsHolder continuationsHolder) {
663:                    super (id, continuation, parentContinuation, timeToLive,
664:                            interpreterId, disposer);
665:                    this .continuationsHolder = continuationsHolder;
666:                }
667:
668:                public WebContinuationsHolder getContinuationsHolder() {
669:                    return continuationsHolder;
670:                }
671:
672:                //retain comparation logic from parent
673:                public int compareTo(Object other) {
674:                    return super .compareTo(other);
675:                }
676:            }
677:
678:            /**
679:             * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
680:             */
681:            public void contextualize(Context context) throws ContextException {
682:                this .context = context;
683:            }
684:
685:            /**
686:             * Get a list of all web continuations (data only)
687:             */
688:            public List getWebContinuationsDataBeanList() {
689:                List beanList = new ArrayList();
690:                for (Iterator it = this .forest.iterator(); it.hasNext();) {
691:                    beanList.add(new WebContinuationDataBean(
692:                            (WebContinuation) it.next()));
693:                }
694:                return beanList;
695:            }
696:
697:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.