KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.ArrayList JavaDoc;
23
24 import javax.management.ObjectName JavaDoc;
25
26 import org.apache.catalina.Contained;
27 import org.apache.catalina.Container;
28 import org.apache.catalina.Lifecycle;
29 import org.apache.catalina.LifecycleException;
30 import org.apache.catalina.LifecycleListener;
31 import org.apache.catalina.Pipeline;
32 import org.apache.catalina.Valve;
33 import org.apache.catalina.util.LifecycleSupport;
34 import org.apache.catalina.util.StringManager;
35 import org.apache.catalina.valves.ValveBase;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.tomcat.util.modeler.Registry;
39
40
41 /**
42  * Standard implementation of a processing <b>Pipeline</b> that will invoke
43  * a series of Valves that have been configured to be called in order. This
44  * implementation can be used for any type of Container.
45  *
46  * <b>IMPLEMENTATION WARNING</b> - This implementation assumes that no
47  * calls to <code>addValve()</code> or <code>removeValve</code> are allowed
48  * while a request is currently being processed. Otherwise, the mechanism
49  * by which per-thread state is maintained will need to be modified.
50  *
51  * @author Craig R. McClanahan
52  */

53
54 public class StandardPipeline
55     implements Pipeline, Contained, Lifecycle
56  {
57
58     private static Log log = LogFactory.getLog(StandardPipeline.class);
59
60     // ----------------------------------------------------------- Constructors
61

62
63     /**
64      * Construct a new StandardPipeline instance with no associated Container.
65      */

66     public StandardPipeline() {
67
68         this(null);
69
70     }
71
72
73     /**
74      * Construct a new StandardPipeline instance that is associated with the
75      * specified Container.
76      *
77      * @param container The container we should be associated with
78      */

79     public StandardPipeline(Container container) {
80
81         super();
82         setContainer(container);
83
84     }
85
86
87     // ----------------------------------------------------- Instance Variables
88

89
90     /**
91      * The basic Valve (if any) associated with this Pipeline.
92      */

93     protected Valve basic = null;
94
95
96     /**
97      * The Container with which this Pipeline is associated.
98      */

99     protected Container container = null;
100
101
102     /**
103      * Descriptive information about this implementation.
104      */

105     protected String JavaDoc info = "org.apache.catalina.core.StandardPipeline/1.0";
106
107
108     /**
109      * The lifecycle event support for this component.
110      */

111     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
112
113
114     /**
115      * The string manager for this package.
116      */

117     protected static StringManager sm =
118         StringManager.getManager(Constants.Package);
119
120
121     /**
122      * Has this component been started yet?
123      */

124     protected boolean started = false;
125
126
127     /**
128      * The first valve associated with this Pipeline.
129      */

130     protected Valve first = null;
131
132
133     // --------------------------------------------------------- Public Methods
134

135
136     /**
137      * Return descriptive information about this implementation class.
138      */

139     public String JavaDoc getInfo() {
140
141         return (this.info);
142
143     }
144
145
146     // ------------------------------------------------------ Contained Methods
147

148
149     /**
150      * Return the Container with which this Pipeline is associated.
151      */

152     public Container getContainer() {
153
154         return (this.container);
155
156     }
157
158
159     /**
160      * Set the Container with which this Pipeline is associated.
161      *
162      * @param container The new associated container
163      */

164     public void setContainer(Container container) {
165
166         this.container = container;
167
168     }
169
170
171     // ------------------------------------------------------ Lifecycle Methods
172

173
174     /**
175      * Add a lifecycle event listener to this component.
176      *
177      * @param listener The listener to add
178      */

179     public void addLifecycleListener(LifecycleListener listener) {
180
181         lifecycle.addLifecycleListener(listener);
182
183     }
184
185
186     /**
187      * Get the lifecycle listeners associated with this lifecycle. If this
188      * Lifecycle has no listeners registered, a zero-length array is returned.
189      */

190     public LifecycleListener[] findLifecycleListeners() {
191
192         return lifecycle.findLifecycleListeners();
193
194     }
195
196
197     /**
198      * Remove a lifecycle event listener from this component.
199      *
200      * @param listener The listener to remove
201      */

202     public void removeLifecycleListener(LifecycleListener listener) {
203
204         lifecycle.removeLifecycleListener(listener);
205
206     }
207
208     /**
209      * Prepare for active use of the public methods of this Component.
210      *
211      * @exception LifecycleException if this component detects a fatal error
212      * that prevents it from being started
213      */

214     public synchronized void start() throws LifecycleException {
215
216         // Validate and update our current component state
217
if (started)
218             throw new LifecycleException
219                 (sm.getString("standardPipeline.alreadyStarted"));
220
221         // Notify our interested LifecycleListeners
222
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
223
224         started = true;
225
226         // Start the Valves in our pipeline (including the basic), if any
227
Valve current = first;
228         if (current == null) {
229             current = basic;
230         }
231         while (current != null) {
232             if (current instanceof Lifecycle)
233                 ((Lifecycle) current).start();
234             registerValve(current);
235             current = current.getNext();
236         }
237
238         // Notify our interested LifecycleListeners
239
lifecycle.fireLifecycleEvent(START_EVENT, null);
240
241         // Notify our interested LifecycleListeners
242
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
243
244     }
245
246
247     /**
248      * Gracefully shut down active use of the public methods of this Component.
249      *
250      * @exception LifecycleException if this component detects a fatal error
251      * that needs to be reported
252      */

253     public synchronized void stop() throws LifecycleException {
254
255         // Validate and update our current component state
256
if (!started)
257             throw new LifecycleException
258                 (sm.getString("standardPipeline.notStarted"));
259
260         // Notify our interested LifecycleListeners
261
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
262
263         // Notify our interested LifecycleListeners
264
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
265         started = false;
266
267         // Stop the Valves in our pipeline (including the basic), if any
268
Valve current = first;
269         if (current == null) {
270             current = basic;
271         }
272         while (current != null) {
273             if (current instanceof Lifecycle)
274                 ((Lifecycle) current).stop();
275             unregisterValve(current);
276             current = current.getNext();
277         }
278
279         // Notify our interested LifecycleListeners
280
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
281     }
282
283     private void registerValve(Valve valve) {
284
285         if( valve instanceof ValveBase &&
286                 ((ValveBase)valve).getObjectName()==null ) {
287             try {
288                 
289                 String JavaDoc domain=((ContainerBase)container).getDomain();
290                 if( container instanceof StandardContext ) {
291                     domain=((StandardContext)container).getEngineName();
292                 }
293                 if( container instanceof StandardWrapper) {
294                     Container ctx=((StandardWrapper)container).getParent();
295                     domain=((StandardContext)ctx).getEngineName();
296                 }
297                 ObjectName JavaDoc vname=((ValveBase)valve).createObjectName(
298                         domain,
299                         ((ContainerBase)container).getJmxName());
300                 if( vname != null ) {
301                     ((ValveBase)valve).setObjectName(vname);
302                     Registry.getRegistry(null, null).registerComponent
303                         (valve, vname, valve.getClass().getName());
304                     ((ValveBase)valve).setController
305                         (((ContainerBase)container).getJmxName());
306                 }
307             } catch( Throwable JavaDoc t ) {
308                 log.info( "Can't register valve " + valve , t );
309             }
310         }
311     }
312     
313     private void unregisterValve(Valve valve) {
314         if( valve instanceof ValveBase ) {
315             try {
316                 ValveBase vb=(ValveBase)valve;
317                 if( vb.getController()!=null &&
318                         vb.getController() ==
319                         ((ContainerBase)container).getJmxName() ) {
320                     
321                     ObjectName JavaDoc vname=vb.getObjectName();
322                     Registry.getRegistry(null, null).getMBeanServer()
323                         .unregisterMBean(vname);
324                     ((ValveBase)valve).setObjectName(null);
325                 }
326             } catch( Throwable JavaDoc t ) {
327                 log.info( "Can't unregister valve " + valve , t );
328             }
329         }
330     }
331
332     // ------------------------------------------------------- Pipeline Methods
333

334
335     /**
336      * <p>Return the Valve instance that has been distinguished as the basic
337      * Valve for this Pipeline (if any).
338      */

339     public Valve getBasic() {
340
341         return (this.basic);
342
343     }
344
345
346     /**
347      * <p>Set the Valve instance that has been distinguished as the basic
348      * Valve for this Pipeline (if any). Prioer to setting the basic Valve,
349      * the Valve's <code>setContainer()</code> will be called, if it
350      * implements <code>Contained</code>, with the owning Container as an
351      * argument. The method may throw an <code>IllegalArgumentException</code>
352      * if this Valve chooses not to be associated with this Container, or
353      * <code>IllegalStateException</code> if it is already associated with
354      * a different Container.</p>
355      *
356      * @param valve Valve to be distinguished as the basic Valve
357      */

358     public void setBasic(Valve valve) {
359
360         // Change components if necessary
361
Valve oldBasic = this.basic;
362         if (oldBasic == valve)
363             return;
364
365         // Stop the old component if necessary
366
if (oldBasic != null) {
367             if (started && (oldBasic instanceof Lifecycle)) {
368                 try {
369                     ((Lifecycle) oldBasic).stop();
370                 } catch (LifecycleException e) {
371                     log.error("StandardPipeline.setBasic: stop", e);
372                 }
373             }
374             if (oldBasic instanceof Contained) {
375                 try {
376                     ((Contained) oldBasic).setContainer(null);
377                 } catch (Throwable JavaDoc t) {
378                     ;
379                 }
380             }
381         }
382
383         // Start the new component if necessary
384
if (valve == null)
385             return;
386         if (valve instanceof Contained) {
387             ((Contained) valve).setContainer(this.container);
388         }
389         if (valve instanceof Lifecycle) {
390             try {
391                 ((Lifecycle) valve).start();
392             } catch (LifecycleException e) {
393                 log.error("StandardPipeline.setBasic: start", e);
394                 return;
395             }
396         }
397
398         // Update the pipeline
399
Valve current = first;
400         while (current != null) {
401             if (current.getNext() == oldBasic) {
402                 current.setNext(valve);
403                 break;
404             }
405             current = current.getNext();
406         }
407         
408         this.basic = valve;
409
410     }
411
412
413     /**
414      * <p>Add a new Valve to the end of the pipeline associated with this
415      * Container. Prior to adding the Valve, the Valve's
416      * <code>setContainer()</code> method will be called, if it implements
417      * <code>Contained</code>, with the owning Container as an argument.
418      * The method may throw an
419      * <code>IllegalArgumentException</code> if this Valve chooses not to
420      * be associated with this Container, or <code>IllegalStateException</code>
421      * if it is already associated with a different Container.</p>
422      *
423      * @param valve Valve to be added
424      *
425      * @exception IllegalArgumentException if this Container refused to
426      * accept the specified Valve
427      * @exception IllegalArgumentException if the specifie Valve refuses to be
428      * associated with this Container
429      * @exception IllegalStateException if the specified Valve is already
430      * associated with a different Container
431      */

432     public void addValve(Valve valve) {
433     
434         // Validate that we can add this Valve
435
if (valve instanceof Contained)
436             ((Contained) valve).setContainer(this.container);
437
438         // Start the new component if necessary
439
if (started) {
440             if (valve instanceof Lifecycle) {
441                 try {
442                     ((Lifecycle) valve).start();
443                 } catch (LifecycleException e) {
444                     log.error("StandardPipeline.addValve: start: ", e);
445                 }
446             }
447             // Register the newly added valve
448
registerValve(valve);
449         }
450
451         // Add this Valve to the set associated with this Pipeline
452
if (first == null) {
453             first = valve;
454             valve.setNext(basic);
455         } else {
456             Valve current = first;
457             while (current != null) {
458                 if (current.getNext() == basic) {
459                     current.setNext(valve);
460                     valve.setNext(basic);
461                     break;
462                 }
463                 current = current.getNext();
464             }
465         }
466
467     }
468
469
470     /**
471      * Return the set of Valves in the pipeline associated with this
472      * Container, including the basic Valve (if any). If there are no
473      * such Valves, a zero-length array is returned.
474      */

475     public Valve[] getValves() {
476
477         ArrayList JavaDoc valveList = new ArrayList JavaDoc();
478         Valve current = first;
479         if (current == null) {
480             current = basic;
481         }
482         while (current != null) {
483             valveList.add(current);
484             current = current.getNext();
485         }
486
487         return ((Valve[]) valveList.toArray(new Valve[0]));
488
489     }
490
491     public ObjectName JavaDoc[] getValveObjectNames() {
492
493         ArrayList JavaDoc valveList = new ArrayList JavaDoc();
494         Valve current = first;
495         if (current == null) {
496             current = basic;
497         }
498         while (current != null) {
499             if (current instanceof ValveBase) {
500                 valveList.add(((ValveBase) current).getObjectName());
501             }
502             current = current.getNext();
503         }
504
505         return ((ObjectName JavaDoc[]) valveList.toArray(new ObjectName JavaDoc[0]));
506
507     }
508
509     /**
510      * Remove the specified Valve from the pipeline associated with this
511      * Container, if it is found; otherwise, do nothing. If the Valve is
512      * found and removed, the Valve's <code>setContainer(null)</code> method
513      * will be called if it implements <code>Contained</code>.
514      *
515      * @param valve Valve to be removed
516      */

517     public void removeValve(Valve valve) {
518
519         Valve current;
520         if(first == valve) {
521             first = first.getNext();
522             current = null;
523         } else {
524             current = first;
525         }
526         while (current != null) {
527             if (current.getNext() == valve) {
528                 current.setNext(valve.getNext());
529                 break;
530             }
531             current = current.getNext();
532         }
533
534         if (first == basic) first = null;
535
536         if (valve instanceof Contained)
537             ((Contained) valve).setContainer(null);
538
539         // Stop this valve if necessary
540
if (started) {
541             if (valve instanceof Lifecycle) {
542                 try {
543                     ((Lifecycle) valve).stop();
544                 } catch (LifecycleException e) {
545                     log.error("StandardPipeline.removeValve: stop: ", e);
546                 }
547             }
548             // Unregister the removed valave
549
unregisterValve(valve);
550         }
551     
552     }
553
554
555     public Valve getFirst() {
556         if (first != null) {
557             return first;
558         } else {
559             return basic;
560         }
561     }
562
563
564 }
565
Popular Tags