KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > valves > SemaphoreValve


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.valves;
20
21
22 import java.io.IOException JavaDoc;
23 import java.util.concurrent.Semaphore JavaDoc;
24
25 import javax.servlet.ServletException JavaDoc;
26
27 import org.apache.catalina.Lifecycle;
28 import org.apache.catalina.LifecycleException;
29 import org.apache.catalina.LifecycleListener;
30 import org.apache.catalina.connector.Request;
31 import org.apache.catalina.connector.Response;
32 import org.apache.catalina.util.LifecycleSupport;
33 import org.apache.catalina.util.StringManager;
34
35
36 /**
37  * <p>Implementation of a Valve that limits concurrency.</p>
38  *
39  * <p>This Valve may be attached to any Container, depending on the granularity
40  * of the concurrency control you wish to perform.</p>
41  *
42  * @author Remy Maucherat
43  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
44  */

45
46 public class SemaphoreValve
47     extends ValveBase
48     implements Lifecycle {
49
50
51     // ----------------------------------------------------- Instance Variables
52

53
54     /**
55      * The descriptive information related to this implementation.
56      */

57     private static final String JavaDoc info =
58         "org.apache.catalina.valves.SemaphoreValve/1.0";
59
60
61     /**
62      * The string manager for this package.
63      */

64     private StringManager sm =
65         StringManager.getManager(Constants.Package);
66
67
68     /**
69      * Semaphore.
70      */

71     protected Semaphore JavaDoc semaphore = null;
72     
73
74     /**
75      * The lifecycle event support for this component.
76      */

77     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
78
79
80     /**
81      * Has this component been started yet?
82      */

83     private boolean started = false;
84
85
86     // ------------------------------------------------------------- Properties
87

88     
89     /**
90      * Concurrency level of the semaphore.
91      */

92     protected int concurrency = 10;
93     public int getConcurrency() { return concurrency; }
94     public void setConcurrency(int concurrency) { this.concurrency = concurrency; }
95     
96
97     /**
98      * Fairness of the semaphore.
99      */

100     protected boolean fairness = false;
101     public boolean getFairness() { return fairness; }
102     public void setFairness(boolean fairness) { this.fairness = fairness; }
103     
104
105     /**
106      * Block until a permit is available.
107      */

108     protected boolean block = true;
109     public boolean getBlock() { return block; }
110     public void setBlock(boolean block) { this.block = block; }
111     
112
113     /**
114      * Block interruptibly until a permit is available.
115      */

116     protected boolean interruptible = false;
117     public boolean getInterruptible() { return interruptible; }
118     public void setInterruptible(boolean interruptible) { this.interruptible = interruptible; }
119     
120
121     // ------------------------------------------------------ Lifecycle Methods
122

123
124     /**
125      * Add a lifecycle event listener to this component.
126      *
127      * @param listener The listener to add
128      */

129     public void addLifecycleListener(LifecycleListener listener) {
130
131         lifecycle.addLifecycleListener(listener);
132
133     }
134
135
136     /**
137      * Get the lifecycle listeners associated with this lifecycle. If this
138      * Lifecycle has no listeners registered, a zero-length array is returned.
139      */

140     public LifecycleListener[] findLifecycleListeners() {
141
142         return lifecycle.findLifecycleListeners();
143
144     }
145
146
147     /**
148      * Remove a lifecycle event listener from this component.
149      *
150      * @param listener The listener to add
151      */

152     public void removeLifecycleListener(LifecycleListener listener) {
153
154         lifecycle.removeLifecycleListener(listener);
155
156     }
157
158
159     /**
160      * Prepare for the beginning of active use of the public methods of this
161      * component. This method should be called after <code>configure()</code>,
162      * and before any of the public methods of the component are utilized.
163      *
164      * @exception LifecycleException if this component detects a fatal error
165      * that prevents this component from being used
166      */

167     public void start() throws LifecycleException {
168
169         // Validate and update our current component state
170
if (started)
171             throw new LifecycleException
172                 (sm.getString("semaphoreValve.alreadyStarted"));
173         lifecycle.fireLifecycleEvent(START_EVENT, null);
174         started = true;
175
176         semaphore = new Semaphore JavaDoc(concurrency, fairness);
177
178     }
179
180
181     /**
182      * Gracefully terminate the active use of the public methods of this
183      * component. This method should be the last one called on a given
184      * instance of this component.
185      *
186      * @exception LifecycleException if this component detects a fatal error
187      * that needs to be reported
188      */

189     public void stop() throws LifecycleException {
190
191         // Validate and update our current component state
192
if (!started)
193             throw new LifecycleException
194                 (sm.getString("semaphoreValve.notStarted"));
195         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
196         started = false;
197
198         semaphore = null;
199
200     }
201
202     
203     // --------------------------------------------------------- Public Methods
204

205
206     /**
207      * Return descriptive information about this Valve implementation.
208      */

209     public String JavaDoc getInfo() {
210         return (info);
211     }
212
213
214     /**
215      * Do concurrency control on the request using the semaphore.
216      *
217      * @param request The servlet request to be processed
218      * @param response The servlet response to be created
219      *
220      * @exception IOException if an input/output error occurs
221      * @exception ServletException if a servlet error occurs
222      */

223     public void invoke(Request request, Response response)
224         throws IOException JavaDoc, ServletException JavaDoc {
225
226         if (controlConcurrency(request, response)) {
227             boolean shouldRelease = true;
228             try {
229                 if (block) {
230                     if (interruptible) {
231                         try {
232                             semaphore.acquire();
233                         } catch (InterruptedException JavaDoc e) {
234                             shouldRelease = false;
235                             permitDenied(request, response);
236                             return;
237                         }
238                     } else {
239                         semaphore.acquireUninterruptibly();
240                     }
241                 } else {
242                     if (!semaphore.tryAcquire()) {
243                         shouldRelease = false;
244                         permitDenied(request, response);
245                         return;
246                     }
247                 }
248                 getNext().invoke(request, response);
249             } finally {
250                 if (shouldRelease) {
251                     semaphore.release();
252                 }
253             }
254         } else {
255             getNext().invoke(request, response);
256         }
257
258     }
259
260     
261     /**
262      * Subclass friendly method to add conditions.
263      */

264     public boolean controlConcurrency(Request request, Response response) {
265         return true;
266     }
267     
268
269     /**
270      * Subclass friendly method to add error handling when a permit isn't granted.
271      */

272     public void permitDenied(Request request, Response response)
273         throws IOException JavaDoc, ServletException JavaDoc {
274     }
275     
276
277 }
278
Popular Tags