Source Code Cross Referenced for JvmRouteBinderValve.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » catalina » ha » session » 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 » Sevlet Container » apache tomcat 6.0.14 » org.apache.catalina.ha.session 
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.catalina.ha.session;
018:
019:        import java.io.IOException;
020:
021:        import javax.servlet.ServletException;
022:        import javax.servlet.http.Cookie;
023:
024:        import org.apache.catalina.Container;
025:        import org.apache.catalina.Context;
026:        import org.apache.catalina.Engine;
027:        import org.apache.catalina.Globals;
028:        import org.apache.catalina.Host;
029:        import org.apache.catalina.Lifecycle;
030:        import org.apache.catalina.LifecycleException;
031:        import org.apache.catalina.LifecycleListener;
032:        import org.apache.catalina.Manager;
033:        import org.apache.catalina.Session;
034:        import org.apache.catalina.ha.CatalinaCluster;
035:        import org.apache.catalina.ha.ClusterManager;
036:        import org.apache.catalina.ha.ClusterMessage;
037:        import org.apache.catalina.ha.ClusterValve;
038:        import org.apache.catalina.connector.Request;
039:        import org.apache.catalina.connector.Response;
040:        import org.apache.catalina.session.ManagerBase;
041:        import org.apache.catalina.util.LifecycleSupport;
042:        import org.apache.catalina.util.StringManager;
043:        import org.apache.catalina.valves.ValveBase;
044:
045:        /**
046:         * Valve to handle Tomcat jvmRoute takeover using mod_jk module after node
047:         * failure. After a node crashed the next request going to other cluster node.
048:         * Now the answering from apache is slower ( make some error handshaking. Very
049:         * bad with apache at my windows.). We rewrite now the cookie jsessionid
050:         * information to the backup cluster node. After the next response all client
051:         * request goes direct to the backup node. The change sessionid send also to all
052:         * other cluster nodes. Well, now the session stickyness work directly to the
053:         * backup node and traffic don't go back too restarted cluster nodes!
054:         * 
055:         * At all cluster node you must configure the as ClusterListener since 5.5.10
056:         * {@link org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener JvmRouteSessionIDBinderListener}
057:         * or before with
058:         * org.apache.catalina.ha.session.JvmRouteSessionIDBinderListenerLifecycle.
059:         * 
060:         * Add this Valve to your host definition at conf/server.xml .
061:         * 
062:         * Since 5.5.10 as direct cluster valve:<br/>
063:         * <pre>
064:         *  &lt;Cluster&gt;
065:         *  &lt;Valve className=&quot;org.apache.catalina.ha.session.JvmRouteBinderValve&quot; /&gt;  
066:         *  &lt;/Cluster&gt;
067:         * </pre>
068:         * <br />
069:         * Before 5.5.10 as Host element:<br/>
070:         * <pre>
071:         *  &lt;Hostr&gt;
072:         *  &lt;Valve className=&quot;org.apache.catalina.ha.session.JvmRouteBinderValve&quot; /&gt;  
073:         *  &lt;/Hostr&gt;
074:         * </pre>
075:         * 
076:         * Trick:<br/>
077:         * You can enable this mod_jk turnover mode via JMX before you drop a node to all backup nodes!
078:         * Set enable true on all JvmRouteBinderValve backups, disable worker at mod_jk 
079:         * and then drop node and restart it! Then enable mod_jk Worker and disable JvmRouteBinderValves again. 
080:         * This use case means that only requested session are migrated.
081:         * 
082:         * @author Peter Rossbach
083:         * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
084:         */
085:        public class JvmRouteBinderValve extends ValveBase implements 
086:                ClusterValve, Lifecycle {
087:
088:            /*--Static Variables----------------------------------------*/
089:            public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
090:                    .getLog(JvmRouteBinderValve.class);
091:
092:            /**
093:             * The descriptive information about this implementation.
094:             */
095:            protected static final String info = "org.apache.catalina.ha.session.JvmRouteBinderValve/1.2";
096:
097:            /*--Instance Variables--------------------------------------*/
098:
099:            /**
100:             * the cluster
101:             */
102:            protected CatalinaCluster cluster;
103:
104:            /**
105:             * The string manager for this package.
106:             */
107:            protected StringManager sm = StringManager
108:                    .getManager(Constants.Package);
109:
110:            /**
111:             * Has this component been started yet?
112:             */
113:            protected boolean started = false;
114:
115:            /**
116:             * enabled this component
117:             */
118:            protected boolean enabled = true;
119:
120:            /**
121:             * number of session that no at this tomcat instanz hosted
122:             */
123:            protected long numberOfSessions = 0;
124:
125:            protected String sessionIdAttribute = "org.apache.catalina.ha.session.JvmRouteOrignalSessionID";
126:
127:            /**
128:             * The lifecycle event support for this component.
129:             */
130:            protected LifecycleSupport lifecycle = new LifecycleSupport(this );
131:
132:            /*--Logic---------------------------------------------------*/
133:
134:            /**
135:             * Return descriptive information about this implementation.
136:             */
137:            public String getInfo() {
138:
139:                return (info);
140:
141:            }
142:
143:            /**
144:             * set session id attribute to failed node for request.
145:             * 
146:             * @return Returns the sessionIdAttribute.
147:             */
148:            public String getSessionIdAttribute() {
149:                return sessionIdAttribute;
150:            }
151:
152:            /**
153:             * get name of failed reqeust session attribute
154:             * 
155:             * @param sessionIdAttribute
156:             *            The sessionIdAttribute to set.
157:             */
158:            public void setSessionIdAttribute(String sessionIdAttribute) {
159:                this .sessionIdAttribute = sessionIdAttribute;
160:            }
161:
162:            /**
163:             * @return Returns the number of migrated sessions.
164:             */
165:            public long getNumberOfSessions() {
166:                return numberOfSessions;
167:            }
168:
169:            /**
170:             * @return Returns the enabled.
171:             */
172:            public boolean getEnabled() {
173:                return enabled;
174:            }
175:
176:            /**
177:             * @param enabled
178:             *            The enabled to set.
179:             */
180:            public void setEnabled(boolean enabled) {
181:                this .enabled = enabled;
182:            }
183:
184:            /**
185:             * Detect possible the JVMRoute change at cluster backup node..
186:             * 
187:             * @param request
188:             *            tomcat request being processed
189:             * @param response
190:             *            tomcat response being processed
191:             * @exception IOException
192:             *                if an input/output error has occurred
193:             * @exception ServletException
194:             *                if a servlet error has occurred
195:             */
196:            public void invoke(Request request, Response response)
197:                    throws IOException, ServletException {
198:
199:                if (getEnabled() && getCluster() != null
200:                        && request.getContext() != null
201:                        && request.getContext().getDistributable()) {
202:                    // valve cluster can access manager - other cluster handle turnover 
203:                    // at host level - hopefully!
204:                    Manager manager = request.getContext().getManager();
205:                    if (manager != null
206:                            && manager instanceof  ClusterManager
207:                            && getCluster().getManager(
208:                                    ((ClusterManager) manager).getName()) != null)
209:                        handlePossibleTurnover(request, response);
210:                }
211:                // Pass this request on to the next valve in our pipeline
212:                getNext().invoke(request, response);
213:            }
214:
215:            /**
216:             * handle possible session turn over.
217:             * 
218:             * @see JvmRouteBinderValve#handleJvmRoute(Request, Response, String, String)
219:             * @param request current request
220:             * @param response current response
221:             */
222:            protected void handlePossibleTurnover(Request request,
223:                    Response response) {
224:                Session session = request.getSessionInternal(false);
225:                if (session != null) {
226:                    long t1 = System.currentTimeMillis();
227:                    String jvmRoute = getLocalJvmRoute(request);
228:                    if (jvmRoute == null) {
229:                        if (log.isDebugEnabled())
230:                            log
231:                                    .debug(sm
232:                                            .getString("jvmRoute.missingJvmRouteAttribute"));
233:                        return;
234:                    }
235:                    handleJvmRoute(request, response, session.getIdInternal(),
236:                            jvmRoute);
237:                    if (log.isDebugEnabled()) {
238:                        long t2 = System.currentTimeMillis();
239:                        long time = t2 - t1;
240:                        log.debug(sm.getString("jvmRoute.turnoverInfo",
241:                                new Long(time)));
242:                    }
243:                }
244:            }
245:
246:            /**
247:             * get jvmroute from engine
248:             * 
249:             * @param request current request
250:             * @return return jvmRoute from ManagerBase or null
251:             */
252:            protected String getLocalJvmRoute(Request request) {
253:                Manager manager = getManager(request);
254:                if (manager instanceof  ManagerBase)
255:                    return ((ManagerBase) manager).getJvmRoute();
256:                return null;
257:            }
258:
259:            /**
260:             * get Cluster DeltaManager
261:             * 
262:             * @param request current request
263:             * @return manager or null
264:             */
265:            protected Manager getManager(Request request) {
266:                Manager manager = request.getContext().getManager();
267:                if (log.isDebugEnabled()) {
268:                    if (manager != null)
269:                        log.debug(sm.getString("jvmRoute.foundManager",
270:                                manager, request.getContext().getName()));
271:                    else
272:                        log.debug(sm.getString("jvmRoute.notFoundManager",
273:                                manager, request.getContext().getName()));
274:                }
275:                return manager;
276:            }
277:
278:            /**
279:             * @return Returns the cluster.
280:             */
281:            public CatalinaCluster getCluster() {
282:                return cluster;
283:            }
284:
285:            /**
286:             * @param cluster The cluster to set.
287:             */
288:            public void setCluster(CatalinaCluster cluster) {
289:                this .cluster = cluster;
290:            }
291:
292:            /**
293:             * Handle jvmRoute stickyness after tomcat instance failed. After this
294:             * correction a new Cookie send to client with new jvmRoute and the
295:             * SessionID change propage to the other cluster nodes.
296:             * 
297:             * @param request current request
298:             * @param response
299:             *            Tomcat Response
300:             * @param sessionId
301:             *            request SessionID from Cookie
302:             * @param localJvmRoute
303:             *            local jvmRoute
304:             */
305:            protected void handleJvmRoute(Request request, Response response,
306:                    String sessionId, String localJvmRoute) {
307:                // get requested jvmRoute.
308:                String requestJvmRoute = null;
309:                int index = sessionId.indexOf(".");
310:                if (index > 0) {
311:                    requestJvmRoute = sessionId.substring(index + 1, sessionId
312:                            .length());
313:                }
314:                if (requestJvmRoute != null
315:                        && !requestJvmRoute.equals(localJvmRoute)) {
316:                    if (log.isDebugEnabled()) {
317:                        log.debug(sm.getString("jvmRoute.failover",
318:                                requestJvmRoute, localJvmRoute, sessionId));
319:                    }
320:                    // OK - turnover the session ?
321:                    String newSessionID = sessionId.substring(0, index) + "."
322:                            + localJvmRoute;
323:                    Session catalinaSession = null;
324:                    try {
325:                        catalinaSession = getManager(request).findSession(
326:                                sessionId);
327:                    } catch (IOException e) {
328:                        // Hups!
329:                    }
330:                    if (catalinaSession != null) {
331:                        changeSessionID(request, response, sessionId,
332:                                newSessionID, catalinaSession);
333:                        numberOfSessions++;
334:                    } else {
335:                        if (log.isDebugEnabled()) {
336:                            log.debug(sm.getString(
337:                                    "jvmRoute.cannotFindSession", sessionId));
338:                        }
339:                    }
340:                }
341:            }
342:
343:            /**
344:             * change session id and send to all cluster nodes
345:             * 
346:             * @param request current request
347:             * @param response current response
348:             * @param sessionId
349:             *            original session id
350:             * @param newSessionID
351:             *            new session id for node migration
352:             * @param catalinaSession
353:             *            current session with original session id
354:             */
355:            protected void changeSessionID(Request request, Response response,
356:                    String sessionId, String newSessionID,
357:                    Session catalinaSession) {
358:                lifecycle.fireLifecycleEvent("Before session migration",
359:                        catalinaSession);
360:                request.setRequestedSessionId(newSessionID);
361:                catalinaSession.setId(newSessionID);
362:                if (catalinaSession instanceof  DeltaSession)
363:                    ((DeltaSession) catalinaSession).resetDeltaRequest();
364:                if (request.isRequestedSessionIdFromCookie())
365:                    setNewSessionCookie(request, response, newSessionID);
366:                // set orginal sessionid at request, to allow application detect the
367:                // change
368:                if (sessionIdAttribute != null
369:                        && !"".equals(sessionIdAttribute)) {
370:                    if (log.isDebugEnabled()) {
371:                        log.debug(sm.getString("jvmRoute.set.orignalsessionid",
372:                                sessionIdAttribute, sessionId));
373:                    }
374:                    request.setAttribute(sessionIdAttribute, sessionId);
375:                }
376:                // now sending the change to all other clusternode!
377:                ClusterManager manager = (ClusterManager) catalinaSession
378:                        .getManager();
379:                sendSessionIDClusterBackup(manager, request, sessionId,
380:                        newSessionID);
381:                lifecycle.fireLifecycleEvent("After session migration",
382:                        catalinaSession);
383:                if (log.isDebugEnabled()) {
384:                    log.debug(sm.getString("jvmRoute.changeSession", sessionId,
385:                            newSessionID));
386:                }
387:            }
388:
389:            /**
390:             * Send the changed Sessionid to all clusternodes.
391:             * 
392:             * @see JvmRouteSessionIDBinderListener#messageReceived(ClusterMessage)
393:             * @param manager
394:             *            ClusterManager
395:             * @param sessionId
396:             *            current failed sessionid
397:             * @param newSessionID
398:             *            new session id, bind to the new cluster node
399:             */
400:            protected void sendSessionIDClusterBackup(ClusterManager manager,
401:                    Request request, String sessionId, String newSessionID) {
402:                SessionIDMessage msg = new SessionIDMessage();
403:                msg.setOrignalSessionID(sessionId);
404:                msg.setBackupSessionID(newSessionID);
405:                Context context = request.getContext();
406:                msg.setContextPath(context.getPath());
407:                msg.setHost(context.getParent().getName());
408:                if (manager.doDomainReplication())
409:                    cluster.sendClusterDomain(msg);
410:                else
411:                    cluster.send(msg);
412:            }
413:
414:            /**
415:             * Sets a new cookie for the given session id and response and see
416:             * {@link org.apache.catalina.connector.Request#configureSessionCookie(javax.servlet.http.Cookie)}
417:             * 
418:             * @param request current request
419:             * @param response Tomcat Response
420:             * @param sessionId The session id
421:             */
422:            protected void setNewSessionCookie(Request request,
423:                    Response response, String sessionId) {
424:                if (response != null) {
425:                    Context context = request.getContext();
426:                    if (context.getCookies()) {
427:                        // set a new session cookie
428:                        Cookie newCookie = new Cookie(
429:                                Globals.SESSION_COOKIE_NAME, sessionId);
430:                        newCookie.setMaxAge(-1);
431:                        String contextPath = null;
432:                        if (!response.getConnector().getEmptySessionPath()
433:                                && (context != null)) {
434:                            contextPath = context.getEncodedPath();
435:                        }
436:                        if ((contextPath != null) && (contextPath.length() > 0)) {
437:                            newCookie.setPath(contextPath);
438:                        } else {
439:                            newCookie.setPath("/");
440:                        }
441:                        if (request.isSecure()) {
442:                            newCookie.setSecure(true);
443:                        }
444:                        if (log.isDebugEnabled()) {
445:                            log.debug(sm.getString("jvmRoute.newSessionCookie",
446:                                    sessionId, Globals.SESSION_COOKIE_NAME,
447:                                    newCookie.getPath(), new Boolean(newCookie
448:                                            .getSecure())));
449:                        }
450:                        response.addCookie(newCookie);
451:                    }
452:                }
453:            }
454:
455:            // ------------------------------------------------------ Lifecycle Methods
456:
457:            /**
458:             * Add a lifecycle event listener to this component.
459:             * 
460:             * @param listener
461:             *            The listener to add
462:             */
463:            public void addLifecycleListener(LifecycleListener listener) {
464:
465:                lifecycle.addLifecycleListener(listener);
466:
467:            }
468:
469:            /**
470:             * Get the lifecycle listeners associated with this lifecycle. If this
471:             * Lifecycle has no listeners registered, a zero-length array is returned.
472:             */
473:            public LifecycleListener[] findLifecycleListeners() {
474:
475:                return lifecycle.findLifecycleListeners();
476:
477:            }
478:
479:            /**
480:             * Remove a lifecycle event listener from this component.
481:             * 
482:             * @param listener
483:             *            The listener to add
484:             */
485:            public void removeLifecycleListener(LifecycleListener listener) {
486:
487:                lifecycle.removeLifecycleListener(listener);
488:
489:            }
490:
491:            /**
492:             * Prepare for the beginning of active use of the public methods of this
493:             * component. This method should be called after <code>configure()</code>,
494:             * and before any of the public methods of the component are utilized.
495:             * 
496:             * @exception LifecycleException
497:             *                if this component detects a fatal error that prevents this
498:             *                component from being used
499:             */
500:            public void start() throws LifecycleException {
501:
502:                // Validate and update our current component state
503:                if (started)
504:                    throw new LifecycleException(sm
505:                            .getString("jvmRoute.valve.alreadyStarted"));
506:                lifecycle.fireLifecycleEvent(START_EVENT, null);
507:                started = true;
508:                if (cluster == null) {
509:                    Container hostContainer = getContainer();
510:                    // compatibility with JvmRouteBinderValve version 1.1
511:                    // ( setup at context.xml or context.xml.default )
512:                    if (!(hostContainer instanceof  Host)) {
513:                        if (log.isWarnEnabled())
514:                            log.warn(sm.getString("jvmRoute.configure.warn"));
515:                        hostContainer = hostContainer.getParent();
516:                    }
517:                    if (hostContainer instanceof  Host
518:                            && ((Host) hostContainer).getCluster() != null) {
519:                        cluster = (CatalinaCluster) ((Host) hostContainer)
520:                                .getCluster();
521:                    } else {
522:                        Container engine = hostContainer.getParent();
523:                        if (engine instanceof  Engine
524:                                && ((Engine) engine).getCluster() != null) {
525:                            cluster = (CatalinaCluster) ((Engine) engine)
526:                                    .getCluster();
527:                        }
528:                    }
529:                }
530:                if (cluster == null) {
531:                    throw new RuntimeException(
532:                            "No clustering support at container "
533:                                    + container.getName());
534:                }
535:
536:                if (log.isInfoEnabled())
537:                    log.info(sm.getString("jvmRoute.valve.started"));
538:
539:            }
540:
541:            /**
542:             * Gracefully terminate the active use of the public methods of this
543:             * component. This method should be the last one called on a given instance
544:             * of this component.
545:             * 
546:             * @exception LifecycleException
547:             *                if this component detects a fatal error that needs to be
548:             *                reported
549:             */
550:            public void stop() throws LifecycleException {
551:
552:                // Validate and update our current component state
553:                if (!started)
554:                    throw new LifecycleException(sm
555:                            .getString("jvmRoute.valve.notStarted"));
556:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
557:                started = false;
558:                cluster = null;
559:                numberOfSessions = 0;
560:                if (log.isInfoEnabled())
561:                    log.info(sm.getString("jvmRoute.valve.stopped"));
562:
563:            }
564:
565:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.