Source Code Cross Referenced for DeferredSessionStorageHandler.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » netui » pageflow » internal » 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 » Library » Apache beehive 1.0.2 src » org.apache.beehive.netui.pageflow.internal 
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:         * $Header:$
018:         */
019:        package org.apache.beehive.netui.pageflow.internal;
020:
021:        import org.apache.beehive.netui.pageflow.handler.StorageHandler;
022:        import org.apache.beehive.netui.pageflow.RequestContext;
023:        import org.apache.beehive.netui.pageflow.ServletContainerAdapter;
024:        import org.apache.beehive.netui.pageflow.PageFlowController;
025:        import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
026:        import org.apache.beehive.netui.util.logging.Logger;
027:        import org.apache.beehive.netui.util.internal.ServletUtils;
028:
029:        import javax.servlet.ServletContext;
030:        import javax.servlet.ServletRequest;
031:        import javax.servlet.http.HttpServletRequest;
032:        import javax.servlet.http.HttpSession;
033:        import javax.servlet.http.HttpSessionBindingListener;
034:        import javax.servlet.http.HttpSessionBindingEvent;
035:        import java.util.HashSet;
036:        import java.util.HashMap;
037:        import java.util.Iterator;
038:        import java.util.Map;
039:        import java.util.Enumeration;
040:        import java.util.ArrayList;
041:        import java.util.Collections;
042:
043:        /**
044:         * This alternate session storage handler does not write any attribute into the session until the very end of a chain
045:         * of forwarded requests (i.e., not even at the end of an inner forwarded request).  This allows it to handle multiple
046:         * concurrent forwarded requests, each of which is modifying the same data, in a more reasonable way.  Basically,
047:         * each request works in its own snapshot of the session, and the last one to commit is the one whose snapshot wins.
048:         * This is a better alternative than allowing them to interfere with each other in the middle of the request chain.
049:         */
050:        public class DeferredSessionStorageHandler extends DefaultHandler
051:                implements  StorageHandler {
052:            private static final Logger _log = Logger
053:                    .getInstance(DeferredSessionStorageHandler.class);
054:
055:            private static final String CHANGELIST_ATTR = InternalConstants.ATTR_PREFIX
056:                    + "changedAttrs";
057:            private static final String FAILOVER_MAP_ATTR = InternalConstants.ATTR_PREFIX
058:                    + "failoverAttrs";
059:
060:            private static ThreadLocal _isCommittingChanges = new ThreadLocal() {
061:                public Object initialValue() {
062:                    return Boolean.FALSE;
063:                }
064:            };
065:
066:            public DeferredSessionStorageHandler(ServletContext servletContext) {
067:                init(null, null, servletContext);
068:            }
069:
070:            private static final class SessionBindingEvent extends
071:                    HttpSessionBindingEvent {
072:                public SessionBindingEvent(HttpSession httpSession,
073:                        String attrName) {
074:                    super (httpSession, attrName);
075:                }
076:
077:                public SessionBindingEvent(HttpSession httpSession,
078:                        String attrName, Object attrVal) {
079:                    super (httpSession, attrName, attrVal);
080:                }
081:            }
082:
083:            public void setAttribute(RequestContext context, String attrName,
084:                    Object value) {
085:                if (_log.isTraceEnabled()) {
086:                    _log.trace("setAttribute: " + attrName + "=" + value);
087:                }
088:
089:                HttpServletRequest request = ScopedServletUtils
090:                        .getOuterRequest((HttpServletRequest) context
091:                                .getRequest());
092:                Object currentValue = request.getAttribute(attrName);
093:
094:                //
095:                // Note that we unconditionally get/create the session.  We want to make sure that the session exists when
096:                // we set an attribute, since we will *not* create it in applyChanges, to prevent recreation of an
097:                // intentionally-invalidated session.
098:                //
099:                HttpSession session = request.getSession();
100:
101:                //
102:                // Emulate a setAttribute on the session: if the value is an HttpSessionBindingListener, invoke its
103:                // valueUnbound().  Note that we don't currently care about calling valueBound().
104:                //
105:                if (currentValue != null && currentValue != value
106:                        && currentValue instanceof  HttpSessionBindingListener) {
107:                    HttpSessionBindingEvent event = new SessionBindingEvent(
108:                            session, attrName, currentValue);
109:                    ((HttpSessionBindingListener) currentValue)
110:                            .valueUnbound(event);
111:                }
112:
113:                request.setAttribute(attrName, value);
114:                getChangedAttributesList(request, true, false).add(attrName);
115:
116:                //
117:                // For attributes that have changed and are now tracked in the changed attribute list, be sure to remove
118:                // them from the list of failover attributes.
119:                //
120:                HashMap failoverAttrs = getFailoverAttributesMap(request,
121:                        false, false);
122:                if (failoverAttrs != null)
123:                    failoverAttrs.remove(attrName);
124:            }
125:
126:            public void removeAttribute(RequestContext context, String attrName) {
127:                if (_log.isTraceEnabled()) {
128:                    _log.trace("removeAttribute: " + attrName);
129:                }
130:
131:                HttpServletRequest request = ScopedServletUtils
132:                        .getOuterRequest((HttpServletRequest) context
133:                                .getRequest());
134:                Object currentValue = request.getAttribute(attrName);
135:
136:                //
137:                // Emulate a removeAttribute on the session: if the value is an HttpSessionBindingListener, invoke its
138:                // valueUnbound().
139:                //
140:                if (currentValue != null
141:                        && currentValue instanceof  HttpSessionBindingListener) {
142:                    HttpSessionBindingEvent event = new SessionBindingEvent(
143:                            request.getSession(), attrName, currentValue);
144:                    ((HttpSessionBindingListener) currentValue)
145:                            .valueUnbound(event);
146:                }
147:
148:                request.removeAttribute(attrName);
149:                getChangedAttributesList(request, true, false).add(attrName);
150:
151:                HashMap failoverAttrs = getFailoverAttributesMap(request,
152:                        false, false);
153:                if (failoverAttrs != null)
154:                    failoverAttrs.remove(attrName);
155:            }
156:
157:            public Object getAttribute(RequestContext context,
158:                    String attributeName) {
159:                if (_log.isTraceEnabled()) {
160:                    _log.trace("getAttribute: " + attributeName);
161:                }
162:
163:                HttpServletRequest request = ScopedServletUtils
164:                        .getOuterRequest((HttpServletRequest) context
165:                                .getRequest());
166:                Object val = request.getAttribute(attributeName);
167:                if (val != null)
168:                    return val;
169:
170:                // If the attribute isn't present in the request and is in the list of changed attrs, then it was removed.
171:                // Don't fall back to the session attribute in that case.
172:                HashSet changedAttrs = getChangedAttributesList(request, false,
173:                        false);
174:                if (changedAttrs != null
175:                        && changedAttrs.contains(attributeName))
176:                    return null;
177:
178:                // Get the attribute out of the session, and put it into the request.  Until applyChanges is called, this is
179:                // the value we'll use.
180:                HttpSession session = request.getSession(false);
181:                if (session != null) {
182:                    val = session.getAttribute(attributeName);
183:                    if (val != null)
184:                        request.setAttribute(attributeName, val);
185:                }
186:
187:                return val;
188:            }
189:
190:            public void applyChanges(RequestContext context) {
191:                HttpServletRequest request = ScopedServletUtils
192:                        .getOuterRequest((HttpServletRequest) context
193:                                .getRequest());
194:                assert request != null;
195:                HttpSession session = request.getSession(false);
196:
197:                //
198:                // If the session doesn't exist, we don't want to recreate it.  It has most likely been intentionally
199:                // invalidated, since we did ensure its existance in getAttribute.
200:                //
201:                if (session == null)
202:                    return;
203:
204:                if (_log.isDebugEnabled())
205:                    _log.debug("Applying changes for request "
206:                            + request.getRequestURI() + ".  Identity: "
207:                            + System.identityHashCode(request));
208:
209:                Object sessionMutex = ServletUtils.getSessionMutex(session,
210:                        ServletUtils.SESSION_MUTEX_ATTRIBUTE);
211:
212:                //
213:                // Synchronize on the session mutex in order to make the operation of applying changes from a request into
214:                // the session atomic.  Atomicity is needed in order to ensure that the attributes set in the session via
215:                // "session.setAttribute(...)" are the same ones present when the "ensureFailover" call is made against the
216:                // ServletContainerAdapter.
217:                //
218:                synchronized (sessionMutex) {
219:
220:                    HashSet changedAttrs = getChangedAttributesList(request,
221:                            false, true);
222:                    if (changedAttrs != null) {
223:                        //
224:                        // Ensure that the Page Flow in the request is run through its destroy lifecycle correctly
225:                        //
226:                        for (Iterator i = changedAttrs.iterator(); i.hasNext();) {
227:                            String attrName = (String) i.next();
228:                            Object val = request.getAttribute(attrName);
229:
230:                            // Write it to the session, but only if the current value isn't already this value.
231:                            Object currSessValue = session
232:                                    .getAttribute(attrName);
233:
234:                            //
235:                            // Here, the value in the session is different than the value about to be persisted to the
236:                            // session.  In some cases, this requires a PageFlowManagedObject lifecycle method to be
237:                            // invoked on that object.
238:                            //
239:                            if (currSessValue != null
240:                                    && val != currSessValue
241:                                    && val instanceof  PageFlowController
242:                                    && val instanceof  HttpSessionBindingListener) {
243:                                //
244:                                // In order to maintain the single-threaded semantics of PFMO destruction, it's necessary
245:                                // to synchronize on PFMO objects here.
246:                                //
247:                                HttpSessionBindingEvent event = new SessionBindingEvent(
248:                                        session, attrName, currSessValue);
249:                                synchronized (currSessValue) {
250:                                    ((HttpSessionBindingListener) currSessValue)
251:                                            .valueUnbound(event);
252:                                }
253:                            }
254:                        }
255:
256:                        //
257:                        // Go through each changed attribute, and either write it to the session or remove it from the session,
258:                        // depending on whether or not it exists in the request.
259:                        //
260:                        for (Iterator i = changedAttrs.iterator(); i.hasNext();) {
261:                            String attrName = (String) i.next();
262:                            Object val = request.getAttribute(attrName);
263:
264:                            if (val != null) {
265:                                // Write it to the session, but only if the current value isn't already this value.
266:                                Object currentValue = session
267:                                        .getAttribute(attrName);
268:
269:                                if (currentValue != val) {
270:                                    if (_log.isTraceEnabled())
271:                                        _log
272:                                                .trace("Committing attribute "
273:                                                        + attrName
274:                                                        + " to the session.");
275:
276:                                    // This ThreadLocal value allows others (e.g., an HttpSessionBindingListener like
277:                                    // PageFlowManagedObject) that we're in the middle of committing changes to the session.
278:                                    _isCommittingChanges.set(Boolean.TRUE);
279:
280:                                    try {
281:                                        session.setAttribute(attrName, val);
282:                                    } finally {
283:                                        _isCommittingChanges.set(Boolean.FALSE);
284:                                    }
285:
286:                                    request.removeAttribute(attrName);
287:                                }
288:                            } else {
289:                                if (_log.isTraceEnabled())
290:                                    _log.trace("Removing attribute " + attrName
291:                                            + " from the session.");
292:
293:                                //
294:                                // This ThreadLocal value allows others (e.g., an HttpSessionBindingListener like
295:                                // PageFlowManagedObject) to query whether the Framework is in the middle of committing
296:                                // changes to the session
297:                                //
298:                                _isCommittingChanges.set(Boolean.TRUE);
299:
300:                                try {
301:                                    session.removeAttribute(attrName);
302:                                } finally {
303:                                    _isCommittingChanges.set(Boolean.FALSE);
304:                                }
305:                            }
306:                        }
307:                    }
308:
309:                    //
310:                    // Now, run the ensureFailover step to make sure that clusterable containers do the right thing
311:                    // with attributes that need to be serialized for failover.
312:                    //
313:                    HashMap failoverAttrs = getFailoverAttributesMap(request,
314:                            false, true);
315:                    if (failoverAttrs != null) {
316:                        ServletContainerAdapter sa = AdapterManager
317:                                .getServletContainerAdapter(getServletContext());
318:
319:                        for (Iterator i = failoverAttrs.entrySet().iterator(); i
320:                                .hasNext();) {
321:                            Map.Entry entry = (Map.Entry) i.next();
322:                            if (_log.isTraceEnabled())
323:                                _log.trace("Ensure failover for attribute "
324:                                        + entry.getKey());
325:
326:                            // This ThreadLocal value allows others (e.g., an HttpSessionBindingListener like
327:                            // PageFlowManagedObject) that we're in the middle of committing changes to the session.
328:                            _isCommittingChanges.set(Boolean.TRUE);
329:                            try {
330:                                sa.ensureFailover((String) entry.getKey(),
331:                                        entry.getValue(), request);
332:                            } finally {
333:                                _isCommittingChanges.set(Boolean.FALSE);
334:                            }
335:                        }
336:                    }
337:                } // release lock on the HttpSession
338:
339:                if (_log.isDebugEnabled())
340:                    _log.debug("Completed applying changes for request "
341:                            + request.getRequestURI() + ".  Identity: "
342:                            + System.identityHashCode(request));
343:            }
344:
345:            public void dropChanges(RequestContext context) {
346:                HttpServletRequest request = ScopedServletUtils
347:                        .getOuterRequest((HttpServletRequest) context
348:                                .getRequest());
349:                if (_log.isDebugEnabled()) {
350:                    _log.debug("Dropping changes for request "
351:                            + request.getRequestURI());
352:                }
353:                getChangedAttributesList(request, false, true);
354:                getFailoverAttributesMap(request, false, true);
355:            }
356:
357:            public Enumeration getAttributeNames(RequestContext context) {
358:                HttpServletRequest request = ScopedServletUtils
359:                        .getOuterRequest((HttpServletRequest) context
360:                                .getRequest());
361:                HttpSession session = request.getSession(false);
362:                ArrayList attrNames = new ArrayList();
363:
364:                // Start with the attribute names that are in the session.
365:                if (session != null) {
366:                    for (Enumeration e = session.getAttributeNames(); e
367:                            .hasMoreElements();) {
368:                        attrNames.add(e.nextElement());
369:                    }
370:                }
371:
372:                // Add or remove as necessary, based on the list of changed attributes.
373:                HashSet changedAttrs = getChangedAttributesList(request, false,
374:                        false);
375:                if (changedAttrs != null) {
376:                    for (Iterator i = changedAttrs.iterator(); i.hasNext();) {
377:                        String attrName = (String) i.next();
378:
379:                        if (request.getAttribute(attrName) != null) {
380:                            attrNames.add(attrName);
381:                        } else {
382:                            // If the attribute isn't present in the request and is in the session, then it's scheduled for
383:                            // removal.
384:                            attrNames.remove(attrName);
385:                        }
386:                    }
387:                }
388:
389:                return Collections.enumeration(attrNames);
390:            }
391:
392:            public void ensureFailover(RequestContext context,
393:                    String attributeName, Object value) {
394:                HttpServletRequest request = ScopedServletUtils
395:                        .getOuterRequest((HttpServletRequest) context
396:                                .getRequest());
397:                getFailoverAttributesMap(request, true, false).put(
398:                        attributeName, value);
399:            }
400:
401:            public boolean allowBindingEvent(Object event) {
402:                return !((Boolean) _isCommittingChanges.get()).booleanValue();
403:            }
404:
405:            private static HashSet getChangedAttributesList(
406:                    ServletRequest request, boolean create, boolean remove) {
407:                HashSet set = (HashSet) request.getAttribute(CHANGELIST_ATTR);
408:
409:                //
410:                // Create a new Set in which to store the changed attributes
411:                //
412:                if (set == null && create) {
413:                    set = new HashSet();
414:                    request.setAttribute(CHANGELIST_ATTR, set);
415:                }
416:
417:                //
418:                // Remove the list of changed attributes from the request
419:                //
420:                if (set != null && remove)
421:                    request.removeAttribute(CHANGELIST_ATTR);
422:
423:                return set;
424:            }
425:
426:            private static HashMap getFailoverAttributesMap(
427:                    ServletRequest request, boolean create, boolean remove) {
428:                HashMap map = (HashMap) request.getAttribute(FAILOVER_MAP_ATTR);
429:
430:                if (map == null && create) {
431:                    map = new HashMap();
432:                    request.setAttribute(FAILOVER_MAP_ATTR, map);
433:                }
434:
435:                if (map != null && remove)
436:                    request.removeAttribute(FAILOVER_MAP_ATTR);
437:
438:                return map;
439:            }
440:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.