1
17
18
19 package org.apache.catalina.core;
20
21
22 import java.io.IOException;
23 import java.util.concurrent.atomic.AtomicInteger;
24
25 import javax.servlet.DispatcherType;
26 import javax.servlet.RequestDispatcher;
27 import javax.servlet.Servlet;
28 import javax.servlet.ServletException;
29 import javax.servlet.UnavailableException;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.apache.catalina.Container;
33 import org.apache.catalina.Context;
34 import org.apache.catalina.Globals;
35 import org.apache.catalina.LifecycleException;
36 import org.apache.catalina.connector.ClientAbortException;
37 import org.apache.catalina.connector.Request;
38 import org.apache.catalina.connector.Response;
39 import org.apache.catalina.valves.ValveBase;
40 import org.apache.coyote.CloseNowException;
41 import org.apache.tomcat.util.ExceptionUtils;
42 import org.apache.tomcat.util.buf.MessageBytes;
43 import org.apache.tomcat.util.log.SystemLogHandler;
44 import org.apache.tomcat.util.res.StringManager;
45
46
52 final class StandardWrapperValve
53 extends ValveBase {
54
55
56 public StandardWrapperValve() {
57 super(true);
58 }
59
60
61
62
63
64
65
66 private volatile long processingTime;
67 private volatile long maxTime;
68 private volatile long minTime = Long.MAX_VALUE;
69 private final AtomicInteger requestCount = new AtomicInteger(0);
70 private final AtomicInteger errorCount = new AtomicInteger(0);
71
72
73
76 private static final StringManager sm =
77 StringManager.getManager(Constants.Package);
78
79
80
81
82
83
93 @Override
94 public final void invoke(Request request, Response response)
95 throws IOException, ServletException {
96
97
98 boolean unavailable = false;
99 Throwable throwable = null;
100
101 long t1=System.currentTimeMillis();
102 requestCount.incrementAndGet();
103 StandardWrapper wrapper = (StandardWrapper) getContainer();
104 Servlet servlet = null;
105 Context context = (Context) wrapper.getParent();
106
107
108 if (!context.getState().isAvailable()) {
109 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
110 sm.getString("standardContext.isUnavailable"));
111 unavailable = true;
112 }
113
114
115 if (!unavailable && wrapper.isUnavailable()) {
116 container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
117 wrapper.getName()));
118 long available = wrapper.getAvailable();
119 if ((available > 0L) && (available < Long.MAX_VALUE)) {
120 response.setDateHeader("Retry-After", available);
121 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
122 sm.getString("standardWrapper.isUnavailable",
123 wrapper.getName()));
124 } else if (available == Long.MAX_VALUE) {
125 response.sendError(HttpServletResponse.SC_NOT_FOUND,
126 sm.getString("standardWrapper.notFound",
127 wrapper.getName()));
128 }
129 unavailable = true;
130 }
131
132
133 try {
134 if (!unavailable) {
135 servlet = wrapper.allocate();
136 }
137 } catch (UnavailableException e) {
138 container.getLogger().error(
139 sm.getString("standardWrapper.allocateException",
140 wrapper.getName()), e);
141 long available = wrapper.getAvailable();
142 if ((available > 0L) && (available < Long.MAX_VALUE)) {
143 response.setDateHeader("Retry-After", available);
144 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
145 sm.getString("standardWrapper.isUnavailable",
146 wrapper.getName()));
147 } else if (available == Long.MAX_VALUE) {
148 response.sendError(HttpServletResponse.SC_NOT_FOUND,
149 sm.getString("standardWrapper.notFound",
150 wrapper.getName()));
151 }
152 } catch (ServletException e) {
153 container.getLogger().error(sm.getString("standardWrapper.allocateException",
154 wrapper.getName()), StandardWrapper.getRootCause(e));
155 throwable = e;
156 exception(request, response, e);
157 } catch (Throwable e) {
158 ExceptionUtils.handleThrowable(e);
159 container.getLogger().error(sm.getString("standardWrapper.allocateException",
160 wrapper.getName()), e);
161 throwable = e;
162 exception(request, response, e);
163 servlet = null;
164 }
165
166 MessageBytes requestPathMB = request.getRequestPathMB();
167 DispatcherType dispatcherType = DispatcherType.REQUEST;
168 if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
169 request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
170 request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
171 requestPathMB);
172
173 ApplicationFilterChain filterChain =
174 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
175
176
177
178 Container container = this.container;
179 try {
180 if ((servlet != null) && (filterChain != null)) {
181
182 if (context.getSwallowOutput()) {
183 try {
184 SystemLogHandler.startCapture();
185 if (request.isAsyncDispatching()) {
186 request.getAsyncContextInternal().doInternalDispatch();
187 } else {
188 filterChain.doFilter(request.getRequest(),
189 response.getResponse());
190 }
191 } finally {
192 String log = SystemLogHandler.stopCapture();
193 if (log != null && log.length() > 0) {
194 context.getLogger().info(log);
195 }
196 }
197 } else {
198 if (request.isAsyncDispatching()) {
199 request.getAsyncContextInternal().doInternalDispatch();
200 } else {
201 filterChain.doFilter
202 (request.getRequest(), response.getResponse());
203 }
204 }
205
206 }
207 } catch (ClientAbortException | CloseNowException e) {
208 if (container.getLogger().isDebugEnabled()) {
209 container.getLogger().debug(sm.getString(
210 "standardWrapper.serviceException", wrapper.getName(),
211 context.getName()), e);
212 }
213 throwable = e;
214 exception(request, response, e);
215 } catch (IOException e) {
216 container.getLogger().error(sm.getString(
217 "standardWrapper.serviceException", wrapper.getName(),
218 context.getName()), e);
219 throwable = e;
220 exception(request, response, e);
221 } catch (UnavailableException e) {
222 container.getLogger().error(sm.getString(
223 "standardWrapper.serviceException", wrapper.getName(),
224 context.getName()), e);
225
226
227 wrapper.unavailable(e);
228 long available = wrapper.getAvailable();
229 if ((available > 0L) && (available < Long.MAX_VALUE)) {
230 response.setDateHeader("Retry-After", available);
231 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
232 sm.getString("standardWrapper.isUnavailable",
233 wrapper.getName()));
234 } else if (available == Long.MAX_VALUE) {
235 response.sendError(HttpServletResponse.SC_NOT_FOUND,
236 sm.getString("standardWrapper.notFound",
237 wrapper.getName()));
238 }
239
240
241 } catch (ServletException e) {
242 Throwable rootCause = StandardWrapper.getRootCause(e);
243 if (!(rootCause instanceof ClientAbortException)) {
244 container.getLogger().error(sm.getString(
245 "standardWrapper.serviceExceptionRoot",
246 wrapper.getName(), context.getName(), e.getMessage()),
247 rootCause);
248 }
249 throwable = e;
250 exception(request, response, e);
251 } catch (Throwable e) {
252 ExceptionUtils.handleThrowable(e);
253 container.getLogger().error(sm.getString(
254 "standardWrapper.serviceException", wrapper.getName(),
255 context.getName()), e);
256 throwable = e;
257 exception(request, response, e);
258 } finally {
259
260 if (filterChain != null) {
261 filterChain.release();
262 }
263
264
265 try {
266 if (servlet != null) {
267 wrapper.deallocate(servlet);
268 }
269 } catch (Throwable e) {
270 ExceptionUtils.handleThrowable(e);
271 container.getLogger().error(sm.getString("standardWrapper.deallocateException",
272 wrapper.getName()), e);
273 if (throwable == null) {
274 throwable = e;
275 exception(request, response, e);
276 }
277 }
278
279
280
281 try {
282 if ((servlet != null) &&
283 (wrapper.getAvailable() == Long.MAX_VALUE)) {
284 wrapper.unload();
285 }
286 } catch (Throwable e) {
287 ExceptionUtils.handleThrowable(e);
288 container.getLogger().error(sm.getString("standardWrapper.unloadException",
289 wrapper.getName()), e);
290 if (throwable == null) {
291 exception(request, response, e);
292 }
293 }
294 long t2=System.currentTimeMillis();
295
296 long time=t2-t1;
297 processingTime += time;
298 if( time > maxTime) maxTime=time;
299 if( time < minTime) minTime=time;
300 }
301 }
302
303
304
305
306
317 private void exception(Request request, Response response,
318 Throwable exception) {
319 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);
320 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
321 response.setError();
322 }
323
324 public long getProcessingTime() {
325 return processingTime;
326 }
327
328 public long getMaxTime() {
329 return maxTime;
330 }
331
332 public long getMinTime() {
333 return minTime;
334 }
335
336 public int getRequestCount() {
337 return requestCount.get();
338 }
339
340 public int getErrorCount() {
341 return errorCount.get();
342 }
343
344 public void incrementErrorCount() {
345 errorCount.incrementAndGet();
346 }
347
348 @Override
349 protected void initInternal() throws LifecycleException {
350
351 }
352 }
353