KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > cluster > tcp > SimpleTcpCluster


1 /*
2  * Copyright 1999,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.catalina.cluster.tcp;
18
19 import java.beans.PropertyChangeSupport JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import javax.management.MBeanServer JavaDoc;
26 import javax.management.MBeanServerFactory JavaDoc;
27 import javax.management.ObjectName JavaDoc;
28 import javax.management.modelmbean.ModelMBean JavaDoc;
29
30 import org.apache.catalina.Container;
31 import org.apache.catalina.Lifecycle;
32 import org.apache.catalina.LifecycleEvent;
33 import org.apache.catalina.LifecycleException;
34 import org.apache.catalina.LifecycleListener;
35 import org.apache.catalina.Manager;
36 import org.apache.catalina.Valve;
37 import org.apache.catalina.cluster.CatalinaCluster;
38 import org.apache.catalina.cluster.ClusterManager;
39 import org.apache.catalina.cluster.ClusterMessage;
40 import org.apache.catalina.cluster.Constants;
41 import org.apache.catalina.cluster.Member;
42 import org.apache.catalina.cluster.MembershipListener;
43 import org.apache.catalina.cluster.MembershipService;
44 import org.apache.catalina.cluster.MessageListener;
45 import org.apache.catalina.cluster.io.ListenCallback;
46 import org.apache.catalina.cluster.session.ReplicationStream;
47 import org.apache.catalina.cluster.session.SessionMessage;
48 import org.apache.catalina.core.StandardHost;
49 import org.apache.catalina.util.LifecycleSupport;
50 import org.apache.catalina.util.StringManager;
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.modeler.ManagedBean;
53 import org.apache.commons.modeler.Registry;
54 import org.apache.tomcat.util.IntrospectionUtils;
55
56 /**
57  * A <b>Cluster </b> implementation using simple multicast. Responsible for
58  * setting up a cluster and provides callers with a valid multicast
59  * receiver/sender.
60  *
61  * FIXME remove install/remove/start/stop context dummys
62  * FIXME better stats
63  * FIXME factor out receiver handling
64  * FIXME Support JMX and Lifecycle Listener Notification (start/stop member) (start/stop context/manager)
65  * FIXME optimize message package creation
66  * FIXME better compress message handling
67  * FIXME Clearer implementation from notifyListenersOnReplication flag
68  *
69  * @author Filip Hanik
70  * @author Remy Maucherat
71  * @author Peter Rossbach
72  * @version $Revision: 1.59 $, $Date: 2005/03/25 22:11:39 $
73  */

74
75 public class SimpleTcpCluster implements CatalinaCluster, Lifecycle,
76         MembershipListener, ListenCallback, LifecycleListener {
77
78     public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
79             .getLog(SimpleTcpCluster.class);
80
81     // ----------------------------------------------------- Instance Variables
82

83     /**
84      * Descriptive information about this component implementation.
85      */

86     protected static final String JavaDoc info = "SimpleTcpCluster/1.0";
87
88     /**
89      * the service that provides the membership
90      */

91     protected MembershipService membershipService = null;
92
93     /**
94      * Whether to expire sessions when shutting down
95      */

96     protected boolean expireSessionsOnShutdown = true;
97
98     /**
99      * Print debug to std.out?
100      */

101     protected boolean printToScreen = false;
102
103     /**
104      * Replicate only sessions that have been marked dirty false=replicate
105      * sessions after each request
106      */

107     protected boolean useDirtyFlag = false;
108
109     /**
110      * Name for logging purpose
111      */

112     protected String JavaDoc clusterImpName = "SimpleTcpCluster";
113
114     /**
115      * The string manager for this package.
116      */

117     protected StringManager sm = StringManager.getManager(Constants.Package);
118
119     /**
120      * The cluster name to join
121      */

122     protected String JavaDoc clusterName = null;
123
124     /**
125      * The Container associated with this Cluster.
126      */

127     protected Container container = null;
128
129     /**
130      * The lifecycle event support for this component.
131      */

132     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
133
134     /**
135      * Globale MBean Server
136      */

137     private MBeanServer JavaDoc mserver = null;
138
139     /**
140      * Current Catalina Registry
141      */

142     private Registry registry = null;
143
144     /**
145      * Has this component been started?
146      */

147     protected boolean started = false;
148
149     /**
150      * The property change support for this component.
151      */

152     protected PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(this);
153
154     /**
155      * The context name <->manager association for distributed contexts.
156      */

157     protected HashMap JavaDoc managers = new HashMap JavaDoc();
158
159     /**
160      * Sending Stats
161      */

162     private long nrOfMsgsReceived = 0;
163
164     private long msgSendTime = 0;
165
166     private long lastChecked = System.currentTimeMillis();
167
168     //sort members by alive time
169
protected MemberComparator memberComparator = new MemberComparator();
170
171     private String JavaDoc managerClassName = "org.apache.catalina.cluster.session.DeltaManager";
172
173     /**
174      * Sender to send data with
175      */

176     private org.apache.catalina.cluster.ClusterSender clusterSender;
177
178     /**
179      * Receiver to register call back with
180      */

181     private org.apache.catalina.cluster.ClusterReceiver clusterReceiver;
182
183     private org.apache.catalina.Valve valve;
184
185     private org.apache.catalina.cluster.ClusterDeployer clusterDeployer;
186
187     /**
188      * Listeners of messages
189      */

190     protected Vector JavaDoc clusterListeners = new Vector JavaDoc();
191
192     /**
193      * Currently only implemented for the delta manager
194      */

195     private boolean notifyListenersOnReplication = true;
196
197     private ObjectName JavaDoc objectName = null;
198
199     // ------------------------------------------------------------- Properties
200

201     public SimpleTcpCluster() {
202     }
203
204     /**
205      * Return descriptive information about this Cluster implementation and the
206      * corresponding version number, in the format
207      * <code>&lt;description&gt;/&lt;version&gt;</code>.
208      */

209     public String JavaDoc getInfo() {
210         return (info);
211     }
212
213     /**
214      * Set the name of the cluster to join, if no cluster with this name is
215      * present create one.
216      *
217      * @param clusterName
218      * The clustername to join
219      */

220     public void setClusterName(String JavaDoc clusterName) {
221         this.clusterName = clusterName;
222     }
223
224     /**
225      * Return the name of the cluster that this Server is currently configured
226      * to operate within.
227      *
228      * @return The name of the cluster associated with this server
229      */

230     public String JavaDoc getClusterName() {
231         return clusterName;
232     }
233
234     /**
235      * Set the Container associated with our Cluster
236      *
237      * @param container
238      * The Container to use
239      */

240     public void setContainer(Container container) {
241         Container oldContainer = this.container;
242         this.container = container;
243         support.firePropertyChange("container", oldContainer, this.container);
244         //this.container.
245
}
246
247     /**
248      * Get the Container associated with our Cluster
249      *
250      * @return The Container associated with our Cluster
251      */

252     public Container getContainer() {
253         return (this.container);
254     }
255
256     /**
257      * Sets the configurable protocol stack. This is a setting in server.xml
258      * where you can configure your protocol.
259      *
260      * @param protocol
261      * the protocol stack - this method is called by the server
262      * configuration at startup
263      * @see <a HREF="www.javagroups.com">JavaGroups </a> for details
264      */

265     public void setProtocol(String JavaDoc protocol) {
266     }
267
268     /**
269      * Returns the protocol.
270      */

271     public String JavaDoc getProtocol() {
272         return null;
273     }
274
275     public Member[] getMembers() {
276         Member[] members = membershipService.getMembers();
277         //sort by alive time
278
java.util.Arrays.sort(members, memberComparator);
279         return members;
280     }
281
282     /**
283      * Return the member that represents this node.
284      *
285      * @return Member
286      */

287     public Member getLocalMember() {
288         return membershipService.getLocalMember();
289     }
290
291     // --------------------------------------------------------- Public Methods
292

293     public synchronized Manager createManager(String JavaDoc name) {
294         if (log.isDebugEnabled())
295             log.debug("Creating ClusterManager for context " + name
296                     + " using class " + getManagerClassName());
297         ClusterManager manager = null;
298         try {
299             manager = (ClusterManager) getClass().getClassLoader().loadClass(
300                     getManagerClassName()).newInstance();
301         } catch (Exception JavaDoc x) {
302             log.error("Unable to load class for replication manager", x);
303             manager = new org.apache.catalina.cluster.session.SimpleTcpReplicationManager();
304         }
305         addManager(name, manager);
306         return manager;
307     }
308
309     /* remove an application form cluster replication bus
310      * FIXME notify someone (JMX(Listener)
311      * @see org.apache.catalina.cluster.CatalinaCluster#removeManager(java.lang.String)
312      */

313     public void removeManager(String JavaDoc name) {
314         managers.remove(name);
315     }
316
317     /* add an application to cluster replication bus
318      * FIXME notify someone (JMX(Listener)
319      * @see org.apache.catalina.cluster.CatalinaCluster#addManager(java.lang.String, org.apache.catalina.cluster.ClusterManager)
320      */

321     public void addManager(String JavaDoc name, ClusterManager manager) {
322         manager.setName(name);
323         manager.setCluster(this);
324         manager.setDistributable(true);
325         manager.setExpireSessionsOnShutdown(expireSessionsOnShutdown);
326         manager.setUseDirtyFlag(useDirtyFlag);
327         manager.setNotifyListenersOnReplication(notifyListenersOnReplication);
328         managers.put(name, manager);
329     }
330
331     public Manager getManager(String JavaDoc name) {
332         return (Manager) managers.get(name);
333     }
334
335     // ------------------------------------------------------ Lifecycle Methods
336

337     /**
338      * Add a lifecycle event listener to this component.
339      *
340      * @param listener
341      * The listener to add
342      */

343     public void addLifecycleListener(LifecycleListener listener) {
344         lifecycle.addLifecycleListener(listener);
345     }
346
347     /**
348      * Execute a periodic task, such as reloading, etc. This method will be
349      * invoked inside the classloading context of this container. Unexpected
350      * throwables will be caught and logged.
351      */

352     public void backgroundProcess() {
353         if (clusterDeployer != null)
354             clusterDeployer.backgroundProcess();
355
356     }
357
358     /**
359      * Get the lifecycle listeners associated with this lifecycle. If this
360      * Lifecycle has no listeners registered, a zero-length array is returned.
361      */

362     public LifecycleListener[] findLifecycleListeners() {
363
364         return lifecycle.findLifecycleListeners();
365
366     }
367
368     /**
369      * Remove a lifecycle event listener from this component.
370      *
371      * @param listener
372      * The listener to remove
373      */

374     public void removeLifecycleListener(LifecycleListener listener) {
375         lifecycle.removeLifecycleListener(listener);
376     }
377
378     /**
379      * Prepare for the beginning of active use of the public methods of this
380      * component. This method should be called after <code>configure()</code>,
381      * and before any of the public methods of the component are utilized. <BR>
382      * Starts the cluster communication channel, this will connect with the
383      * other nodes in the cluster, and request the current session state to be
384      * transferred to this node.
385      *
386      * FIXME notify someone (JMX(Listener)
387      * @exception IllegalStateException
388      * if this component has already been started
389      * @exception LifecycleException
390      * if this component detects a fatal error that prevents this
391      * component from being used
392      */

393     public void start() throws LifecycleException {
394         if (started)
395             throw new LifecycleException(sm.getString("cluster.alreadyStarted"));
396         if (log.isInfoEnabled())
397             log.info("Cluster is about to start");
398         try {
399             if (log.isDebugEnabled())
400                 log.debug("Invoking addValve on " + getContainer()
401                         + " with class=" + valve.getClass().getName());
402             if (valve != null) {
403                 IntrospectionUtils.callMethodN(getContainer(), "addValve",
404                         new Object JavaDoc[] { valve }, new Class JavaDoc[] { Thread
405                                 .currentThread().getContextClassLoader()
406                                 .loadClass("org.apache.catalina.Valve") });
407
408             }
409             registerMBeans();
410             clusterReceiver.setSendAck(clusterSender.isWaitForAck());
411             clusterReceiver.setCatalinaCluster(this);
412             clusterReceiver.start();
413             clusterSender.setCatalinaCluster(this);
414             clusterSender.start();
415             membershipService.setLocalMemberProperties(clusterReceiver
416                     .getHost(), clusterReceiver.getPort());
417             membershipService.addMembershipListener(this);
418             membershipService.start();
419             //set the deployer.
420
try {
421                 if (clusterDeployer != null) {
422                     clusterDeployer.setCluster(this);
423                     clusterDeployer.start();
424                 }
425             } catch (Throwable JavaDoc x) {
426                 log
427                         .fatal(
428                                 "Unable to retrieve the container deployer. Cluster deployment disabled.",
429                                 x);
430             } //catch
431
this.started = true;
432         } catch (Exception JavaDoc x) {
433             log.error("Unable to start cluster.", x);
434             throw new LifecycleException(x);
435         }
436     }
437
438     /*
439      * send a cluster message to one member
440      *
441      * @see org.apache.catalina.cluster.CatalinaCluster#send(org.apache.catalina.cluster.ClusterMessage,
442      * org.apache.catalina.cluster.Member)
443      */

444     public void send(ClusterMessage msg, Member dest) {
445         try {
446             msg.setAddress(membershipService.getLocalMember());
447             Member destination = dest;
448
449             if (msg instanceof SessionMessage) {
450                 SessionMessage smsg = (SessionMessage) msg;
451                 //if we request session state, send to the oldest of members
452
if ((destination == null)
453                         && (smsg.getEventType() == SessionMessage.EVT_GET_ALL_SESSIONS)
454                         && (membershipService.getMembers().length > 0)) {
455                     destination = membershipService.getMembers()[0];
456                 }
457             }
458             byte[] data = createMessageData(msg);
459             if (destination != null) {
460                 Member tcpdest = dest;
461                 if ((tcpdest != null)
462                         && (!membershipService.getLocalMember().equals(tcpdest))) {
463                     clusterSender.sendMessage(msg.getUniqueId(), data, tcpdest);
464                 }
465             } else {
466                 clusterSender.sendMessage(msg.getUniqueId(), data);
467             }
468         } catch (Exception JavaDoc x) {
469             log.error("Unable to send message through cluster sender.", x);
470         }
471     }
472
473     /**
474      * Send Message create Timestamp and generate message bytes form msg
475      * @param msg cluster message
476      * @return cluster message as byte array
477      * @throws IOException
478      */

479     protected byte[] createMessageData(ClusterMessage msg) throws IOException JavaDoc {
480         msg.setTimestamp(System.currentTimeMillis());
481         java.io.ByteArrayOutputStream JavaDoc outs = new java.io.ByteArrayOutputStream JavaDoc();
482         java.io.ObjectOutputStream JavaDoc out = new java.io.ObjectOutputStream JavaDoc(
483                 outs);
484         out.writeObject(msg);
485         byte[] data = outs.toByteArray();
486         return data;
487     }
488
489     /**
490      * send message to all cluster members
491      *
492      * @see org.apache.catalina.cluster.CatalinaCluster#send(org.apache.catalina.cluster.ClusterMessage)
493      */

494     public void send(ClusterMessage msg) {
495         send(msg, null);
496     }
497
498     /**
499      * Gracefully terminate the active use of the public methods of this
500      * component. This method should be the last one called on a given instance
501      * of this component. <BR>
502      * This will disconnect the cluster communication channel and stop the
503      * listener thread.
504      *
505      * FIXME notify someone (JMX(Listener)
506      * @exception IllegalStateException
507      * if this component has not been started
508      * @exception LifecycleException
509      * if this component detects a fatal error that needs to be
510      * reported
511      */

512     public void stop() throws LifecycleException {
513
514         if (!started)
515             throw new IllegalStateException JavaDoc(sm.getString("cluster.notStarted"));
516         unregisterMBeans();
517
518         membershipService.stop();
519         membershipService.removeMembershipListener();
520         try {
521             clusterSender.stop();
522         } catch (Exception JavaDoc x) {
523             log.error("Unable to stop cluster sender.", x);
524         }
525         try {
526             clusterReceiver.stop();
527             clusterReceiver.setCatalinaCluster(null);
528         } catch (Exception JavaDoc x) {
529             log.error("Unable to stop cluster receiver.", x);
530         }
531         if (clusterDeployer != null) {
532             clusterDeployer.stop();
533         }
534         started = false;
535     }
536
537     /* New cluster member is registered
538      * FIXME notify someone (JMX(Listener)
539      * @see org.apache.catalina.cluster.MembershipListener#memberAdded(org.apache.catalina.cluster.Member)
540      */

541     public void memberAdded(Member member) {
542         try {
543             if (log.isInfoEnabled())
544                 log.info("Replication member added:" + member);
545             clusterSender.add(member);
546         } catch (Exception JavaDoc x) {
547             log.error("Unable to connect to replication system.", x);
548         }
549
550     }
551
552     /* Cluster member is gone
553      * FIXME notify someone (JMX(Listener)
554      * @see org.apache.catalina.cluster.MembershipListener#memberDisappeared(org.apache.catalina.cluster.Member)
555      */

556     public void memberDisappeared(Member member) {
557         if (log.isInfoEnabled())
558             log.info("Received member disappeared:" + member);
559         try {
560             clusterSender.remove(member);
561         } catch (Exception JavaDoc x) {
562             log.error("Unable remove cluster node from replication system.", x);
563         }
564
565     }
566
567     public void setExpireSessionsOnShutdown(boolean expireSessionsOnShutdown) {
568         this.expireSessionsOnShutdown = expireSessionsOnShutdown;
569     }
570
571     public void setPrintToScreen(boolean printToScreen) {
572         this.printToScreen = printToScreen;
573     }
574
575     /**
576      * @return Returns the msgSendTime.
577      */

578     public long getMsgSendTime() {
579         return msgSendTime;
580     }
581
582     /**
583      * @return Returns the lastChecked.
584      */

585     public long getLastChecked() {
586         return lastChecked;
587     }
588
589     /**
590      * @return Returns the nrOfMsgsReceived.
591      */

592     public long getNrOfMsgsReceived() {
593         return nrOfMsgsReceived;
594     }
595
596     /**
597      * @return Returns the expireSessionsOnShutdown.
598      */

599     public boolean isExpireSessionsOnShutdown() {
600         return expireSessionsOnShutdown;
601     }
602
603     /**
604      * @return Returns the printToScreen.
605      */

606     public boolean isPrintToScreen() {
607         return printToScreen;
608     }
609
610     /**
611      * @return Returns the useDirtyFlag.
612      */

613     public boolean isUseDirtyFlag() {
614         return useDirtyFlag;
615     }
616
617     public void setUseDirtyFlag(boolean useDirtyFlag) {
618         this.useDirtyFlag = useDirtyFlag;
619     }
620
621     public void messageDataReceived(byte[] data) {
622         long timeSent = System.currentTimeMillis();
623         try {
624             ReplicationStream stream = new ReplicationStream(
625                     new java.io.ByteArrayInputStream JavaDoc(data), getClass()
626                             .getClassLoader());
627             Object JavaDoc myobj = stream.readObject();
628             if (log.isDebugEnabled()
629                     && myobj != null && myobj instanceof ClusterMessage)
630                 log.debug("Assuming clocks are synched: Replication for "
631                         + ((ClusterMessage) myobj).getUniqueId() + " took="
632                         + (System.currentTimeMillis() - ((ClusterMessage) myobj).getTimestamp())
633                         + " ms.");
634             if (myobj != null && myobj instanceof SessionMessage) {
635
636                 SessionMessage msg = (SessionMessage) myobj;
637                 String JavaDoc ctxname = msg.getContextName();
638                 //check if the message is a EVT_GET_ALL_SESSIONS,
639
//if so, wait until we are fully started up
640
if (ctxname == null) {
641                     java.util.Iterator JavaDoc i = managers.keySet().iterator();
642                     while (i.hasNext()) {
643                         String JavaDoc key = (String JavaDoc) i.next();
644                         ClusterManager mgr = (ClusterManager) managers.get(key);
645                         if (mgr != null)
646                             mgr.messageDataReceived(msg);
647                         else {
648                             //this happens a lot before the system has started
649
// up
650
if (log.isDebugEnabled())
651                                 log.debug("Context manager doesn't exist:"
652                                         + key);
653                         }
654                     }
655                 } else {
656                     ClusterManager mgr = (ClusterManager) managers.get(ctxname);
657                     if (mgr != null)
658                         mgr.messageDataReceived(msg);
659                     else if (log.isWarnEnabled())
660                         log.warn("Context manager doesn't exist:" + ctxname);
661                 }
662             } else {
663                 //invoke all the listeners
664
for (int i = 0; i < clusterListeners.size(); i++) {
665                     MessageListener listener = (MessageListener) clusterListeners
666                             .elementAt(i);
667                     if (myobj != null && myobj instanceof ClusterMessage
668                             && listener.accept((ClusterMessage) myobj)) {
669                       listener.messageReceived((ClusterMessage) myobj);
670                     } else
671                         if(log.isDebugEnabled())
672                             log.debug("Message " + myobj.toString()
673                                     + " from type " + myobj.getClass().getName()
674                                     + " transfered but no listener registered");
675                 }
676             }
677
678         } catch (Exception JavaDoc x) {
679             log.error("Unable to deserialize session message.", x);
680         } finally {
681             perfMessageRecvd(timeSent);
682         }
683     }
684
685     public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
686         if (log.isDebugEnabled())
687             log.debug("\nlifecycleEvent\n\nType" + lifecycleEvent.getType()
688                     + "\nData" + lifecycleEvent.getData() + "\n\n\n");
689     }
690
691     // --------------------------------------------------------- Cluster Wide
692
// Deployments
693
/**
694      * Start an existing web application, attached to the specified context path
695      * in all the other nodes in the cluster. Only starts a web application if
696      * it is not running.
697      *
698      * @param contextPath
699      * The context path of the application to be started
700      *
701      * @exception IllegalArgumentException
702      * if the specified context path is malformed (it must be ""
703      * or start with a slash)
704      * @exception IllegalArgumentException
705      * if the specified context path does not identify a
706      * currently installed web application
707      * @exception IOException
708      * if an input/output error occurs during startup
709      */

710     public void startContext(String JavaDoc contextPath) throws IOException JavaDoc {
711         return;
712     }
713
714     /**
715      * Install a new web application, whose web application archive is at the
716      * specified URL, into this container with the specified context path. A
717      * context path of "" (the empty string) should be used for the root
718      * application for this container. Otherwise, the context path must start
719      * with a slash.
720      * <p>
721      * If this application is successfully installed, a ContainerEvent of type
722      * <code>PRE_INSTALL_EVENT</code> will be sent to registered listeners
723      * before the associated Context is started, and a ContainerEvent of type
724      * <code>INSTALL_EVENT</code> will be sent to all registered listeners
725      * after the associated Context is started, with the newly created
726      * <code>Context</code> as an argument.
727      *
728      * @param contextPath
729      * The context path to which this application should be installed
730      * (must be unique)
731      * @param war
732      * A URL of type "jar:" that points to a WAR file, or type
733      * "file:" that points to an unpacked directory structure
734      * containing the web application to be installed
735      *
736      * @exception IllegalArgumentException
737      * if the specified context path is malformed (it must be ""
738      * or start with a slash)
739      * @exception IllegalStateException
740      * if the specified context path is already attached to an
741      * existing web application
742      */

743     public void installContext(String JavaDoc contextPath, URL JavaDoc war) {
744         if (log.isDebugEnabled())
745             log.debug("\n\n\n\nCluster Install called for context:"
746                     + contextPath + "\n\n\n\n");
747     }
748
749     /**
750      * Stop an existing web application, attached to the specified context path.
751      * Only stops a web application if it is running.
752      *
753      * @param contextPath
754      * The context path of the application to be stopped
755      *
756      * @exception IllegalArgumentException
757      * if the specified context path is malformed (it must be ""
758      * or start with a slash)
759      * @exception IllegalArgumentException
760      * if the specified context path does not identify a
761      * currently installed web application
762      * @exception IOException
763      * if an input/output error occurs while stopping the web
764      * application
765      */

766     public void stop(String JavaDoc contextPath) throws IOException JavaDoc {
767         return;
768     }
769
770     public Log getLogger() {
771         return log;
772     }
773
774     // --------------------------------------------- Inner Class
775

776     // --------------------------------------------- Performance
777

778     private void perfMessageRecvd(long timeSent) {
779         nrOfMsgsReceived++;
780         long current = System.currentTimeMillis();
781         msgSendTime += (current - timeSent);
782         if (log.isDebugEnabled()) {
783             if ((current - lastChecked) > 5000) {
784                 log.debug("Calc msg send time total=" + msgSendTime
785                         + "ms num request=" + nrOfMsgsReceived
786                         + " average per msg="
787                         + (msgSendTime / nrOfMsgsReceived) + "ms.");
788                 lastChecked=current ;
789             }
790         }
791     }
792
793     public String JavaDoc getManagerClassName() {
794         return managerClassName;
795     }
796
797     public void setManagerClassName(String JavaDoc managerClassName) {
798         this.managerClassName = managerClassName;
799     }
800
801     public org.apache.catalina.cluster.ClusterSender getClusterSender() {
802         return clusterSender;
803     }
804
805     public void setClusterSender(
806             org.apache.catalina.cluster.ClusterSender clusterSender) {
807         this.clusterSender = clusterSender;
808     }
809
810     public org.apache.catalina.cluster.ClusterReceiver getClusterReceiver() {
811         return clusterReceiver;
812     }
813
814     public void setClusterReceiver(
815             org.apache.catalina.cluster.ClusterReceiver clusterReceiver) {
816         this.clusterReceiver = clusterReceiver;
817     }
818
819     public MembershipService getMembershipService() {
820         return membershipService;
821     }
822
823     public void setMembershipService(MembershipService membershipService) {
824         this.membershipService = membershipService;
825     }
826
827     public void addValve(Valve valve) {
828         this.valve = valve;
829     }
830
831     public Valve getValve() {
832         return valve;
833     }
834
835     public void addClusterListener(MessageListener listener) {
836         if (!clusterListeners.contains(listener)) {
837             clusterListeners.addElement(listener);
838         }
839     }
840
841     public void removeClusterListener(MessageListener listener) {
842         clusterListeners.removeElement(listener);
843     }
844
845     public org.apache.catalina.cluster.ClusterDeployer getClusterDeployer() {
846         return clusterDeployer;
847     }
848
849     public void setClusterDeployer(
850             org.apache.catalina.cluster.ClusterDeployer clusterDeployer) {
851         this.clusterDeployer = clusterDeployer;
852     }
853
854     public boolean getNotifyListenersOnReplication() {
855         return notifyListenersOnReplication;
856     }
857
858     public void setNotifyListenersOnReplication(
859             boolean notifyListenersOnReplication) {
860         this.notifyListenersOnReplication = notifyListenersOnReplication;
861     }
862
863     // --------------------------------------------- JMX MBeans
864

865     /**
866      * register Means at cluster
867      *
868      * @param host
869      * clustered host
870      */

871     protected void registerMBeans() {
872         try {
873             getMBeanServer();
874             String JavaDoc domain = mserver.getDefaultDomain();
875             String JavaDoc name = ":type=Cluster";
876             if (container instanceof StandardHost) {
877                 domain = ((StandardHost) container).getDomain();
878                 name += ",host=" + container.getName();
879             }
880             ObjectName JavaDoc clusterName = new ObjectName JavaDoc(domain + name);
881
882             if (mserver.isRegistered(clusterName)) {
883                 if (log.isWarnEnabled())
884                     log.warn(sm.getString("cluster.mbean.register.allready",
885                             clusterName));
886                 return;
887             }
888             setObjectName(clusterName);
889             mserver.registerMBean(getManagedBean(this), getObjectName());
890         } catch (Exception JavaDoc ex) {
891             log.error(ex.getMessage(), ex);
892         }
893     }
894
895     protected void unregisterMBeans() {
896         if (mserver != null) {
897             try {
898                 mserver.unregisterMBean(getObjectName());
899             } catch (Exception JavaDoc e) {
900                 log.error(e);
901             }
902         }
903     }
904
905     /**
906      * Get current Catalina MBean Server and load mbean registry
907      *
908      * @return
909      * @throws Exception
910      */

911     protected MBeanServer JavaDoc getMBeanServer() throws Exception JavaDoc {
912         if (mserver == null) {
913             if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
914                 mserver = (MBeanServer JavaDoc) MBeanServerFactory
915                         .findMBeanServer(null).get(0);
916             } else {
917                 mserver = MBeanServerFactory.createMBeanServer();
918             }
919             registry = Registry.getRegistry(null, null);
920             registry.loadMetadata(this.getClass()
921                     .getResourceAsStream("mbeans-descriptors.xml"));
922         }
923         return (mserver);
924     }
925
926     /**
927      * Returns the ModelMBean
928      *
929      * @param object
930      * The Object to get the ModelMBean for
931      * @return The ModelMBean
932      * @throws Exception
933      * If an error occurs this constructors throws this exception
934      */

935     protected ModelMBean JavaDoc getManagedBean(Object JavaDoc object) throws Exception JavaDoc {
936         ModelMBean JavaDoc mbean = null;
937         if (registry != null) {
938             ManagedBean managedBean = registry.findManagedBean(object
939                     .getClass().getName());
940             mbean = managedBean.createMBean(object);
941         }
942         return mbean;
943     }
944
945     public void setObjectName(ObjectName JavaDoc name) {
946         objectName = name ;
947     }
948
949     public ObjectName JavaDoc getObjectName() {
950         return objectName;
951     }
952
953     // --------------------------------------------- Inner Class
954

955     private class MemberComparator implements java.util.Comparator JavaDoc {
956
957         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
958             try {
959                 return compare((Member) o1, (Member) o2);
960             } catch (ClassCastException JavaDoc x) {
961                 return 0;
962             }
963         }
964
965         public int compare(Member m1, Member m2) {
966             //longer alive time, means sort first
967
long result = m2.getMemberAliveTime() - m1.getMemberAliveTime();
968             if (result < 0)
969                 return -1;
970             else if (result == 0)
971                 return 0;
972             else
973                 return 1;
974         }
975     }
976
977 }
Popular Tags