KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc5 > StandardService


1 /*
2  * Copyright 2002-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  * JBoss, the OpenSource WebOS
18  *
19  * Distributable under LGPL license.
20  * See terms of license at gnu.org.
21  */

22 package org.jboss.web.tomcat.tc5;
23
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.beans.PropertyChangeSupport JavaDoc;
26 import javax.management.MBeanRegistration JavaDoc;
27 import javax.management.MBeanServer JavaDoc;
28 import javax.management.ObjectName JavaDoc;
29
30 import org.apache.catalina.Container;
31 import org.apache.catalina.Engine;
32 import org.apache.catalina.Lifecycle;
33 import org.apache.catalina.LifecycleException;
34 import org.apache.catalina.LifecycleListener;
35 import org.apache.catalina.Server;
36 import org.apache.catalina.Service;
37 import org.apache.catalina.ServerFactory;
38 import org.apache.catalina.connector.Connector;
39 import org.apache.catalina.core.Constants;
40 import org.apache.catalina.core.ContainerBase;
41 import org.apache.catalina.util.LifecycleSupport;
42 import org.apache.catalina.util.StringManager;
43 import org.apache.commons.modeler.Registry;
44 import org.jboss.logging.Logger;
45
46
47 /**
48  * Standard implementation of the <code>Service</code> interface. The
49  * associated Container is generally an instance of Engine, but this is
50  * not required.
51  * <p/>
52  * This version does not start the connectors in the start method so that
53  * all web apps may be completely deployed before enabling the transport
54  * layer.
55  *
56  * @author Craig R. McClanahan
57  * @author Scott.Stark@jboss.org
58  * @version $Revision: 1.3.2.2 $
59  */

60 public class StandardService
61    implements Lifecycle, Service, MBeanRegistration JavaDoc
62 {
63    private static Logger log = Logger.getLogger(StandardService.class);
64
65    // ----------------------------------------------------- Instance Variables
66

67
68    /**
69     * The set of Connectors associated with this Service.
70     */

71    private Connector connectors[] = new Connector[0];
72
73
74    /**
75     * The Container associated with this Service.
76     */

77    private Container container = null;
78
79
80    /**
81     * The debugging detail level for this component.
82     */

83    private int debug = 0;
84
85
86    /**
87     * Descriptive information about this component implementation.
88     */

89    private static final String JavaDoc info =
90       "org.jboss.web.tomcat.tc5.StandardService/1.0";
91
92
93    /**
94     * Has this component been initialized?
95     */

96    private boolean initialized = false;
97
98
99    /**
100     * The name of this service.
101     */

102    private String JavaDoc name = null;
103
104
105    /**
106     * The lifecycle event support for this component.
107     */

108    private LifecycleSupport lifecycle = new LifecycleSupport(this);
109
110
111    /**
112     * The string manager for this package.
113     */

114    private static final StringManager sm =
115       StringManager.getManager(Constants.Package);
116
117    /**
118     * The <code>Server</code> that owns this Service, if any.
119     */

120    private Server JavaDoc server = null;
121
122    /**
123     * Has this component been started?
124     */

125    private boolean started = false;
126
127
128    /**
129     * The property change support for this component.
130     */

131    protected PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(this);
132
133
134    // ------------------------------------------------------------- Properties
135

136
137    /**
138     * Return the <code>Container</code> that handles requests for all
139     * <code>Connectors</code> associated with this Service.
140     */

141    public Container getContainer()
142    {
143
144       return (this.container);
145
146    }
147
148
149    /**
150     * Set the <code>Container</code> that handles requests for all
151     * <code>Connectors</code> associated with this Service.
152     *
153     * @param container The new Container
154     */

155    public void setContainer(Container container)
156    {
157
158       Container oldContainer = this.container;
159       if ((oldContainer != null) && (oldContainer instanceof Engine))
160          ((Engine) oldContainer).setService(null);
161       this.container = container;
162       if ((this.container != null) && (this.container instanceof Engine))
163          ((Engine) this.container).setService(this);
164       if (started && (this.container != null) &&
165          (this.container instanceof Lifecycle))
166       {
167          try
168          {
169             ((Lifecycle) this.container).start();
170          }
171          catch (LifecycleException e)
172          {
173             ;
174          }
175       }
176       synchronized (connectors)
177       {
178          for (int i = 0; i < connectors.length; i++)
179             connectors[i].setContainer(this.container);
180       }
181       if (started && (oldContainer != null) &&
182          (oldContainer instanceof Lifecycle))
183       {
184          try
185          {
186             ((Lifecycle) oldContainer).stop();
187          }
188          catch (LifecycleException e)
189          {
190             ;
191          }
192       }
193
194       // Report this property change to interested listeners
195
support.firePropertyChange("container", oldContainer, this.container);
196
197    }
198
199    public ObjectName JavaDoc getContainerName()
200    {
201       if (container instanceof ContainerBase)
202       {
203          return ((ContainerBase) container).getJmxName();
204       }
205       return null;
206    }
207
208
209    /**
210     * Return the debugging detail level of this component.
211     */

212    public int getDebug()
213    {
214
215       return (this.debug);
216
217    }
218
219
220    /**
221     * Set the debugging detail level of this component.
222     *
223     * @param debug The new debugging detail level
224     */

225    public void setDebug(int debug)
226    {
227
228       this.debug = debug;
229
230    }
231
232
233    /**
234     * Return descriptive information about this Service implementation and
235     * the corresponding version number, in the format
236     * <code>&lt;description&gt;/&lt;version&gt;</code>.
237     */

238    public String JavaDoc getInfo()
239    {
240
241       return (info);
242
243    }
244
245
246    /**
247     * Return the name of this Service.
248     */

249    public String JavaDoc getName()
250    {
251
252       return (this.name);
253
254    }
255
256
257    /**
258     * Set the name of this Service.
259     *
260     * @param name The new service name
261     */

262    public void setName(String JavaDoc name)
263    {
264
265       this.name = name;
266
267    }
268
269
270    /**
271     * Return the <code>Server</code> with which we are associated (if any).
272     */

273    public Server JavaDoc getServer()
274    {
275
276       return (this.server);
277
278    }
279
280
281    /**
282     * Set the <code>Server</code> with which we are associated (if any).
283     *
284     * @param server The server that owns this Service
285     */

286    public void setServer(Server JavaDoc server)
287    {
288
289       this.server = server;
290
291    }
292
293
294    // --------------------------------------------------------- Public Methods
295

296
297    /**
298     * Add a new Connector to the set of defined Connectors, and associate it
299     * with this Service's Container.
300     *
301     * @param connector The Connector to be added
302     */

303    public void addConnector(Connector connector)
304    {
305
306       synchronized (connectors)
307       {
308          connector.setContainer(this.container);
309          connector.setService(this);
310          Connector results[] = new Connector[connectors.length + 1];
311          System.arraycopy(connectors, 0, results, 0, connectors.length);
312          results[connectors.length] = connector;
313          connectors = results;
314
315          if (initialized)
316          {
317             try
318             {
319                connector.initialize();
320             }
321             catch (LifecycleException e)
322             {
323                e.printStackTrace(System.err);
324             }
325          }
326
327          if (started && (connector instanceof Lifecycle))
328          {
329             try
330             {
331                ((Lifecycle) connector).start();
332             }
333             catch (LifecycleException e)
334             {
335                ;
336             }
337          }
338
339          // Report this property change to interested listeners
340
support.firePropertyChange("connector", null, connector);
341       }
342
343    }
344
345    public ObjectName JavaDoc[] getConnectorNames()
346    {
347       ObjectName JavaDoc results[] = new ObjectName JavaDoc[connectors.length];
348       for (int i = 0; i < results.length; i++)
349       {
350          // if it's a coyote connector
351
//if( connectors[i] instanceof CoyoteConnector ) {
352
// results[i]=((CoyoteConnector)connectors[i]).getJmxName();
353
//}
354
}
355       return results;
356    }
357
358
359    /**
360     * Add a property change listener to this component.
361     *
362     * @param listener The listener to add
363     */

364    public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener)
365    {
366
367       support.addPropertyChangeListener(listener);
368
369    }
370
371
372    /**
373     * Find and return the set of Connectors associated with this Service.
374     */

375    public Connector[] findConnectors()
376    {
377
378       return (connectors);
379
380    }
381
382
383    /**
384     * Remove the specified Connector from the set associated from this
385     * Service. The removed Connector will also be disassociated from our
386     * Container.
387     *
388     * @param connector The Connector to be removed
389     */

390    public void removeConnector(Connector connector)
391    {
392
393       synchronized (connectors)
394       {
395          int j = -1;
396          for (int i = 0; i < connectors.length; i++)
397          {
398             if (connector == connectors[i])
399             {
400                j = i;
401                break;
402             }
403          }
404          if (j < 0)
405             return;
406          if (started && (connectors[j] instanceof Lifecycle))
407          {
408             try
409             {
410                ((Lifecycle) connectors[j]).stop();
411             }
412             catch (LifecycleException e)
413             {
414                ;
415             }
416          }
417          connectors[j].setContainer(null);
418          connector.setService(null);
419          int k = 0;
420          Connector results[] = new Connector[connectors.length - 1];
421          for (int i = 0; i < connectors.length; i++)
422          {
423             if (i != j)
424                results[k++] = connectors[i];
425          }
426          connectors = results;
427
428          // Report this property change to interested listeners
429
support.firePropertyChange("connector", connector, null);
430       }
431
432    }
433
434
435    /**
436     * Remove a property change listener from this component.
437     *
438     * @param listener The listener to remove
439     */

440    public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener)
441    {
442
443       support.removePropertyChangeListener(listener);
444
445    }
446
447
448    /**
449     * Return a String representation of this component.
450     */

451    public String JavaDoc toString()
452    {
453
454       StringBuffer JavaDoc sb = new StringBuffer JavaDoc("StandardService[");
455       sb.append(getName());
456       sb.append("]");
457       return (sb.toString());
458
459    }
460
461
462    // ------------------------------------------------------ Lifecycle Methods
463

464
465    /**
466     * Add a LifecycleEvent listener to this component.
467     *
468     * @param listener The listener to add
469     */

470    public void addLifecycleListener(LifecycleListener listener)
471    {
472
473       lifecycle.addLifecycleListener(listener);
474
475    }
476
477
478    /**
479     * Get the lifecycle listeners associated with this lifecycle. If this
480     * Lifecycle has no listeners registered, a zero-length array is returned.
481     */

482    public LifecycleListener[] findLifecycleListeners()
483    {
484
485       return lifecycle.findLifecycleListeners();
486
487    }
488
489
490    /**
491     * Remove a LifecycleEvent listener from this component.
492     *
493     * @param listener The listener to remove
494     */

495    public void removeLifecycleListener(LifecycleListener listener)
496    {
497
498       lifecycle.removeLifecycleListener(listener);
499
500    }
501
502
503    /**
504     * Prepare for the beginning of active use of the public methods of this
505     * component. This method should be called before any of the public
506     * methods of this component are utilized. It should also send a
507     * LifecycleEvent of type START_EVENT to any registered listeners.
508     *
509     * @throws LifecycleException if this component detects a fatal error
510     * that prevents this component from being used
511     */

512    public void start() throws LifecycleException
513    {
514
515       // Validate and update our current component state
516
if (started)
517       {
518          log.info(sm.getString("standardService.start.started"));
519       }
520
521       if (!initialized)
522          init();
523
524       // Notify our interested LifecycleListeners
525
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
526
527       log.info(sm.getString("standardService.start.name", this.name));
528       lifecycle.fireLifecycleEvent(START_EVENT, null);
529       started = true;
530
531       // Start our defined Container first
532
if (container != null)
533       {
534          synchronized (container)
535          {
536             if (container instanceof Lifecycle)
537             {
538                ((Lifecycle) container).start();
539             }
540          }
541       }
542
543       /* Start our defined Connectors second
544       synchronized (connectors) {
545           for (int i = 0; i < connectors.length; i++) {
546               if (connectors[i] instanceof Lifecycle)
547                   ((Lifecycle) connectors[i]).start();
548           }
549       }
550 */

551       // Notify our interested LifecycleListeners
552
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
553
554    }
555
556
557    /**
558     * Gracefully terminate the active use of the public methods of this
559     * component. This method should be the last one called on a given
560     * instance of this component. It should also send a LifecycleEvent
561     * of type STOP_EVENT to any registered listeners.
562     *
563     * @throws LifecycleException if this component detects a fatal error
564     * that needs to be reported
565     */

566    public void stop() throws LifecycleException
567    {
568
569       // Validate and update our current component state
570
if (!started)
571       {
572          return;
573       }
574
575       // Notify our interested LifecycleListeners
576
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
577
578       // Stop our defined Connectors first
579
synchronized (connectors)
580       {
581          for (int i = 0; i < connectors.length; i++)
582          {
583             connectors[i].pause();
584          }
585       }
586
587       // Heuristic: Sleep for a while to ensure pause of the connector
588
try
589       {
590          Thread.sleep(1000);
591       }
592       catch (InterruptedException JavaDoc e)
593       {
594          // Ignore
595
}
596
597       lifecycle.fireLifecycleEvent(STOP_EVENT, null);
598
599       log.info
600          (sm.getString("standardService.stop.name", this.name));
601       started = false;
602
603       // Stop our defined Container second
604
if (container != null)
605       {
606          synchronized (container)
607          {
608             if (container instanceof Lifecycle)
609             {
610                ((Lifecycle) container).stop();
611             }
612          }
613       }
614
615       // Stop our defined Connectors first
616
synchronized (connectors)
617       {
618          for (int i = 0; i < connectors.length; i++)
619          {
620             if (connectors[i] instanceof Lifecycle)
621                ((Lifecycle) connectors[i]).stop();
622          }
623       }
624
625       if (oname == controller)
626       {
627          // we registered ourself on init().
628
// That should be the typical case - this object is just for
629
// backward compat, nobody should bother to load it explicitely
630
Registry.getRegistry(null, null).unregisterComponent(oname);
631       }
632         
633
634       // Notify our interested LifecycleListeners
635
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
636
637    }
638
639
640    /**
641     * Invoke a pre-startup initialization. This is used to allow connectors
642     * to bind to restricted ports under Unix operating environments.
643     */

644    public void initialize()
645       throws LifecycleException
646    {
647       // Service shouldn't be used with embeded, so it doesn't matter
648
if (initialized)
649       {
650          log.info(sm.getString("standardService.initialize.initialized"));
651          return;
652       }
653       initialized = true;
654
655       if (oname == null)
656       {
657          try
658          {
659             // Hack - Server should be deprecated...
660
Container engine = this.getContainer();
661             domain = engine.getName();
662             oname = new ObjectName JavaDoc(domain + ":type=Service,serviceName=" + name);
663             this.controller = oname;
664             Registry.getRegistry(null, null)
665                .registerComponent(this, oname, null);
666          }
667          catch (Exception JavaDoc e)
668          {
669             log.error("Error registering ", e);
670          }
671
672
673       }
674       if (server == null)
675       {
676          // Register with the server
677
// HACK: ServerFactory should be removed...
678

679          ServerFactory.getServer().addService(this);
680       }
681                
682
683       // Initialize our defined Connectors
684
synchronized (connectors)
685       {
686          for (int i = 0; i < connectors.length; i++)
687          {
688             connectors[i].initialize();
689          }
690       }
691    }
692
693    public void destroy() throws LifecycleException
694    {
695       if (started) stop();
696       // unregister should be here probably
697
}
698
699    public void init()
700    {
701       try
702       {
703          initialize();
704       }
705       catch (Throwable JavaDoc t)
706       {
707          t.printStackTrace();
708       }
709    }
710
711    protected String JavaDoc type;
712    protected String JavaDoc domain;
713    protected String JavaDoc suffix;
714    protected ObjectName JavaDoc oname;
715    protected ObjectName JavaDoc controller;
716    protected MBeanServer JavaDoc mserver;
717
718    public ObjectName JavaDoc getObjectName()
719    {
720       return oname;
721    }
722
723    public String JavaDoc getDomain()
724    {
725       return domain;
726    }
727
728    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server,
729       ObjectName JavaDoc name) throws Exception JavaDoc
730    {
731       oname = name;
732       mserver = server;
733       domain = name.getDomain();
734       return name;
735    }
736
737    public void postRegister(Boolean JavaDoc registrationDone)
738    {
739    }
740
741    public void preDeregister() throws Exception JavaDoc
742    {
743    }
744
745    public void postDeregister()
746    {
747    }
748
749 }
750
Popular Tags