KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > StandardService


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

17
18
19 package org.apache.catalina.core;
20
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeSupport JavaDoc;
24 import javax.management.MBeanRegistration JavaDoc;
25 import javax.management.MBeanServer JavaDoc;
26 import javax.management.ObjectName JavaDoc;
27 import org.apache.catalina.Container;
28 import org.apache.catalina.Engine;
29 import org.apache.catalina.Lifecycle;
30 import org.apache.catalina.LifecycleException;
31 import org.apache.catalina.LifecycleListener;
32 import org.apache.catalina.Server;
33 import org.apache.catalina.Service;
34 import org.apache.catalina.ServerFactory;
35 import org.apache.catalina.connector.Connector;
36 import org.apache.catalina.util.LifecycleSupport;
37 import org.apache.catalina.util.StringManager;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.tomcat.util.modeler.Registry;
41
42
43 /**
44  * Standard implementation of the <code>Service</code> interface. The
45  * associated Container is generally an instance of Engine, but this is
46  * not required.
47  *
48  * @author Craig R. McClanahan
49  */

50
51 public class StandardService
52         implements Lifecycle, Service, MBeanRegistration JavaDoc
53  {
54     private static Log log = LogFactory.getLog(StandardService.class);
55    
56
57     // ----------------------------------------------------- Instance Variables
58

59
60     /**
61      * Descriptive information about this component implementation.
62      */

63     private static final String JavaDoc info =
64         "org.apache.catalina.core.StandardService/1.0";
65
66
67     /**
68      * The name of this service.
69      */

70     private String JavaDoc name = null;
71
72
73     /**
74      * The lifecycle event support for this component.
75      */

76     private LifecycleSupport lifecycle = new LifecycleSupport(this);
77
78
79     /**
80      * The string manager for this package.
81      */

82     private static final StringManager sm =
83         StringManager.getManager(Constants.Package);
84
85     /**
86      * The <code>Server</code> that owns this Service, if any.
87      */

88     private Server JavaDoc server = null;
89
90     /**
91      * Has this component been started?
92      */

93     private boolean started = false;
94
95
96     /**
97      * The property change support for this component.
98      */

99     protected PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(this);
100
101
102     /**
103      * The set of Connectors associated with this Service.
104      */

105     protected Connector connectors[] = new Connector[0];
106
107
108     /**
109      * The Container associated with this Service. (In the case of the
110      * org.apache.catalina.startup.Embedded subclass, this holds the most
111      * recently added Engine.)
112      */

113     protected Container container = null;
114
115
116     /**
117      * Has this component been initialized?
118      */

119     protected boolean initialized = false;
120
121
122     // ------------------------------------------------------------- Properties
123

124
125     /**
126      * Return the <code>Container</code> that handles requests for all
127      * <code>Connectors</code> associated with this Service.
128      */

129     public Container getContainer() {
130
131         return (this.container);
132
133     }
134
135
136     /**
137      * Set the <code>Container</code> that handles requests for all
138      * <code>Connectors</code> associated with this Service.
139      *
140      * @param container The new Container
141      */

142     public void setContainer(Container container) {
143
144         Container oldContainer = this.container;
145         if ((oldContainer != null) && (oldContainer instanceof Engine))
146             ((Engine) oldContainer).setService(null);
147         this.container = container;
148         if ((this.container != null) && (this.container instanceof Engine))
149             ((Engine) this.container).setService(this);
150         if (started && (this.container != null) &&
151             (this.container instanceof Lifecycle)) {
152             try {
153                 ((Lifecycle) this.container).start();
154             } catch (LifecycleException e) {
155                 ;
156             }
157         }
158         synchronized (connectors) {
159             for (int i = 0; i < connectors.length; i++)
160                 connectors[i].setContainer(this.container);
161         }
162         if (started && (oldContainer != null) &&
163             (oldContainer instanceof Lifecycle)) {
164             try {
165                 ((Lifecycle) oldContainer).stop();
166             } catch (LifecycleException e) {
167                 ;
168             }
169         }
170
171         // Report this property change to interested listeners
172
support.firePropertyChange("container", oldContainer, this.container);
173
174     }
175
176     public ObjectName JavaDoc getContainerName() {
177         if( container instanceof ContainerBase ) {
178             return ((ContainerBase)container).getJmxName();
179         }
180         return null;
181     }
182
183
184     /**
185      * Return descriptive information about this Service implementation and
186      * the corresponding version number, in the format
187      * <code>&lt;description&gt;/&lt;version&gt;</code>.
188      */

189     public String JavaDoc getInfo() {
190
191         return (info);
192
193     }
194
195
196     /**
197      * Return the name of this Service.
198      */

199     public String JavaDoc getName() {
200
201         return (this.name);
202
203     }
204
205
206     /**
207      * Set the name of this Service.
208      *
209      * @param name The new service name
210      */

211     public void setName(String JavaDoc name) {
212
213         this.name = name;
214
215     }
216
217
218     /**
219      * Return the <code>Server</code> with which we are associated (if any).
220      */

221     public Server JavaDoc getServer() {
222
223         return (this.server);
224
225     }
226
227
228     /**
229      * Set the <code>Server</code> with which we are associated (if any).
230      *
231      * @param server The server that owns this Service
232      */

233     public void setServer(Server JavaDoc server) {
234
235         this.server = server;
236
237     }
238
239
240     // --------------------------------------------------------- Public Methods
241

242
243     /**
244      * Add a new Connector to the set of defined Connectors, and associate it
245      * with this Service's Container.
246      *
247      * @param connector The Connector to be added
248      */

249     public void addConnector(Connector connector) {
250
251         synchronized (connectors) {
252             connector.setContainer(this.container);
253             connector.setService(this);
254             Connector results[] = new Connector[connectors.length + 1];
255             System.arraycopy(connectors, 0, results, 0, connectors.length);
256             results[connectors.length] = connector;
257             connectors = results;
258
259             if (initialized) {
260                 try {
261                     connector.initialize();
262                 } catch (LifecycleException e) {
263                     log.error("Connector.initialize", e);
264                 }
265             }
266
267             if (started && (connector instanceof Lifecycle)) {
268                 try {
269                     ((Lifecycle) connector).start();
270                 } catch (LifecycleException e) {
271                     log.error("Connector.start", e);
272                 }
273             }
274
275             // Report this property change to interested listeners
276
support.firePropertyChange("connector", null, connector);
277         }
278
279     }
280
281     public ObjectName JavaDoc[] getConnectorNames() {
282         ObjectName JavaDoc results[] = new ObjectName JavaDoc[connectors.length];
283         for( int i=0; i<results.length; i++ ) {
284             // if it's a coyote connector
285
//if( connectors[i] instanceof CoyoteConnector ) {
286
// results[i]=((CoyoteConnector)connectors[i]).getJmxName();
287
//}
288
}
289         return results;
290     }
291
292
293     /**
294      * Add a property change listener to this component.
295      *
296      * @param listener The listener to add
297      */

298     public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
299
300         support.addPropertyChangeListener(listener);
301
302     }
303
304
305     /**
306      * Find and return the set of Connectors associated with this Service.
307      */

308     public Connector[] findConnectors() {
309
310         return (connectors);
311
312     }
313
314
315     /**
316      * Remove the specified Connector from the set associated from this
317      * Service. The removed Connector will also be disassociated from our
318      * Container.
319      *
320      * @param connector The Connector to be removed
321      */

322     public void removeConnector(Connector connector) {
323
324         synchronized (connectors) {
325             int j = -1;
326             for (int i = 0; i < connectors.length; i++) {
327                 if (connector == connectors[i]) {
328                     j = i;
329                     break;
330                 }
331             }
332             if (j < 0)
333                 return;
334             if (started && (connectors[j] instanceof Lifecycle)) {
335                 try {
336                     ((Lifecycle) connectors[j]).stop();
337                 } catch (LifecycleException e) {
338                     log.error("Connector.stop", e);
339                 }
340             }
341             connectors[j].setContainer(null);
342             connector.setService(null);
343             int k = 0;
344             Connector results[] = new Connector[connectors.length - 1];
345             for (int i = 0; i < connectors.length; i++) {
346                 if (i != j)
347                     results[k++] = connectors[i];
348             }
349             connectors = results;
350
351             // Report this property change to interested listeners
352
support.firePropertyChange("connector", connector, null);
353         }
354
355     }
356
357
358     /**
359      * Remove a property change listener from this component.
360      *
361      * @param listener The listener to remove
362      */

363     public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
364
365         support.removePropertyChangeListener(listener);
366
367     }
368
369
370     /**
371      * Return a String representation of this component.
372      */

373     public String JavaDoc toString() {
374
375         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("StandardService[");
376         sb.append(getName());
377         sb.append("]");
378         return (sb.toString());
379
380     }
381
382
383     // ------------------------------------------------------ Lifecycle Methods
384

385
386     /**
387      * Add a LifecycleEvent listener to this component.
388      *
389      * @param listener The listener to add
390      */

391     public void addLifecycleListener(LifecycleListener listener) {
392
393         lifecycle.addLifecycleListener(listener);
394
395     }
396
397
398     /**
399      * Get the lifecycle listeners associated with this lifecycle. If this
400      * Lifecycle has no listeners registered, a zero-length array is returned.
401      */

402     public LifecycleListener[] findLifecycleListeners() {
403
404         return lifecycle.findLifecycleListeners();
405
406     }
407
408
409     /**
410      * Remove a LifecycleEvent listener from this component.
411      *
412      * @param listener The listener to remove
413      */

414     public void removeLifecycleListener(LifecycleListener listener) {
415
416         lifecycle.removeLifecycleListener(listener);
417
418     }
419
420
421     /**
422      * Prepare for the beginning of active use of the public methods of this
423      * component. This method should be called before any of the public
424      * methods of this component are utilized. It should also send a
425      * LifecycleEvent of type START_EVENT to any registered listeners.
426      *
427      * @exception LifecycleException if this component detects a fatal error
428      * that prevents this component from being used
429      */

430     public void start() throws LifecycleException {
431
432         // Validate and update our current component state
433
if (log.isInfoEnabled() && started) {
434             log.info(sm.getString("standardService.start.started"));
435         }
436         
437         if( ! initialized )
438             init();
439
440         // Notify our interested LifecycleListeners
441
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
442         if(log.isInfoEnabled())
443             log.info(sm.getString("standardService.start.name", this.name));
444         lifecycle.fireLifecycleEvent(START_EVENT, null);
445         started = true;
446
447         // Start our defined Container first
448
if (container != null) {
449             synchronized (container) {
450                 if (container instanceof Lifecycle) {
451                     ((Lifecycle) container).start();
452                 }
453             }
454         }
455
456         // Start our defined Connectors second
457
synchronized (connectors) {
458             for (int i = 0; i < connectors.length; i++) {
459                 if (connectors[i] instanceof Lifecycle)
460                     ((Lifecycle) connectors[i]).start();
461             }
462         }
463
464         // Notify our interested LifecycleListeners
465
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
466
467     }
468
469
470     /**
471      * Gracefully terminate the active use of the public methods of this
472      * component. This method should be the last one called on a given
473      * instance of this component. It should also send a LifecycleEvent
474      * of type STOP_EVENT to any registered listeners.
475      *
476      * @exception LifecycleException if this component detects a fatal error
477      * that needs to be reported
478      */

479     public void stop() throws LifecycleException {
480
481         // Validate and update our current component state
482
if (!started) {
483             return;
484         }
485
486         // Notify our interested LifecycleListeners
487
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
488
489         // Stop our defined Connectors first
490
synchronized (connectors) {
491             for (int i = 0; i < connectors.length; i++) {
492                 connectors[i].pause();
493             }
494         }
495
496         // Heuristic: Sleep for a while to ensure pause of the connector
497
try {
498             Thread.sleep(1000);
499         } catch (InterruptedException JavaDoc e) {
500             // Ignore
501
}
502
503         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
504         if(log.isInfoEnabled())
505             log.info
506                 (sm.getString("standardService.stop.name", this.name));
507         started = false;
508
509         // Stop our defined Container second
510
if (container != null) {
511             synchronized (container) {
512                 if (container instanceof Lifecycle) {
513                     ((Lifecycle) container).stop();
514                 }
515             }
516         }
517         // FIXME pero -- Why container stop first? KeepAlive connetions can send request!
518
// Stop our defined Connectors first
519
synchronized (connectors) {
520             for (int i = 0; i < connectors.length; i++) {
521                 if (connectors[i] instanceof Lifecycle)
522                     ((Lifecycle) connectors[i]).stop();
523             }
524         }
525
526         if( oname==controller ) {
527             // we registered ourself on init().
528
// That should be the typical case - this object is just for
529
// backward compat, nobody should bother to load it explicitely
530
Registry.getRegistry(null, null).unregisterComponent(oname);
531         }
532         
533
534         // Notify our interested LifecycleListeners
535
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
536
537     }
538
539
540     /**
541      * Invoke a pre-startup initialization. This is used to allow connectors
542      * to bind to restricted ports under Unix operating environments.
543      */

544     public void initialize()
545             throws LifecycleException
546     {
547         // Service shouldn't be used with embeded, so it doesn't matter
548
if (initialized) {
549             if(log.isInfoEnabled())
550                 log.info(sm.getString("standardService.initialize.initialized"));
551             return;
552         }
553         initialized = true;
554
555         if( oname==null ) {
556             try {
557                 // Hack - Server should be deprecated...
558
Container engine=this.getContainer();
559                 domain=engine.getName();
560                 oname=new ObjectName JavaDoc(domain + ":type=Service,serviceName="+name);
561                 this.controller=oname;
562                 Registry.getRegistry(null, null)
563                     .registerComponent(this, oname, null);
564             } catch (Exception JavaDoc e) {
565                 log.error(sm.getString("standardService.register.failed",domain),e);
566             }
567             
568             
569         }
570         if( server==null ) {
571             // Register with the server
572
// HACK: ServerFactory should be removed...
573

574             ServerFactory.getServer().addService(this);
575         }
576                
577
578         // Initialize our defined Connectors
579
synchronized (connectors) {
580                 for (int i = 0; i < connectors.length; i++) {
581                     connectors[i].initialize();
582                 }
583         }
584     }
585     
586     public void destroy() throws LifecycleException {
587         if( started ) stop();
588         // FIXME unregister should be here probably -- stop doing that ?
589
}
590
591     public void init() {
592         try {
593             initialize();
594         } catch( Throwable JavaDoc t ) {
595             log.error(sm.getString("standardService.initialize.failed",domain),t);
596         }
597     }
598
599     protected String JavaDoc type;
600     protected String JavaDoc domain;
601     protected String JavaDoc suffix;
602     protected ObjectName JavaDoc oname;
603     protected ObjectName JavaDoc controller;
604     protected MBeanServer JavaDoc mserver;
605
606     public ObjectName JavaDoc getObjectName() {
607         return oname;
608     }
609
610     public String JavaDoc getDomain() {
611         return domain;
612     }
613
614     public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server,
615                                   ObjectName JavaDoc name) throws Exception JavaDoc {
616         oname=name;
617         mserver=server;
618         domain=name.getDomain();
619         return name;
620     }
621
622     public void postRegister(Boolean JavaDoc registrationDone) {
623     }
624
625     public void preDeregister() throws Exception JavaDoc {
626     }
627
628     public void postDeregister() {
629     }
630
631 }
632
Popular Tags