1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18 
19 package org.eclipse.jetty.server.handler;
20 
21 import java.io.IOException;
22 
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 
27 import org.eclipse.jetty.server.Request;
28 
29 
30 /* ------------------------------------------------------------ */
31 /** ScopedHandler.
32  *
33  * A ScopedHandler is a HandlerWrapper where the wrapped handlers
34  * each define a scope.   When {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}
35  * is called on the first ScopedHandler in a chain of HandlerWrappers,
36  * the {@link #doScope(String, Request, HttpServletRequest, HttpServletResponse)} method is
37  * called on all contained ScopedHandlers, before the
38  * {@link #doHandle(String, Request, HttpServletRequest, HttpServletResponse)} method
39  * is called on all contained handlers.
40  *
41  * <p>For example if Scoped handlers A, B & C were chained together, then
42  * the calling order would be:<pre>
43  * A.handle(...)
44  *   A.doScope(...)
45  *     B.doScope(...)
46  *       C.doScope(...)
47  *         A.doHandle(...)
48  *           B.doHandle(...)
49  *              C.doHandle(...)
50  * <pre>
51  *
52  * <p>If non scoped handler X was in the chained A, B, X & C, then
53  * the calling order would be:<pre>
54  * A.handle(...)
55  *   A.doScope(...)
56  *     B.doScope(...)
57  *       C.doScope(...)
58  *         A.doHandle(...)
59  *           B.doHandle(...)
60  *             X.handle(...)
61  *               C.handle(...)
62  *                 C.doHandle(...)
63  * <pre>
64  *
65  * <p>A typical usage pattern is:<pre>
66  *     private static class MyHandler extends ScopedHandler
67  *     {
68  *         public void doScope(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
69  *         {
70  *             try
71  *             {
72  *                 setUpMyScope();
73  *                 super.doScope(target,request,response);
74  *             }
75  *             finally
76  *             {
77  *                 tearDownMyScope();
78  *             }
79  *         }
80  *
81  *         public void doHandle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
82  *         {
83  *             try
84  *             {
85  *                 doMyHandling();
86  *                 super.doHandle(target,request,response);
87  *             }
88  *             finally
89  *             {
90  *                 cleanupMyHandling();
91  *             }
92  *         }
93  *     }
94  * </pre>
95  */
96 public abstract class ScopedHandler extends HandlerWrapper
97 {
98     private static final ThreadLocal<ScopedHandler> __outerScope= new ThreadLocal<ScopedHandler>();
99     protected ScopedHandler _outerScope;
100     protected ScopedHandler _nextScope;
101 
102     /* ------------------------------------------------------------ */
103     /**
104      * @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart()
105      */
106     @Override
doStart()107     protected void doStart() throws Exception
108     {
109         try
110         {
111             _outerScope=__outerScope.get();
112             if (_outerScope==null)
113                 __outerScope.set(this);
114 
115             super.doStart();
116 
117             _nextScope= (ScopedHandler)getChildHandlerByClass(ScopedHandler.class);
118 
119         }
120         finally
121         {
122             if (_outerScope==null)
123                 __outerScope.set(null);
124         }
125     }
126 
127 
128     /* ------------------------------------------------------------ */
129     /*
130      */
131     @Override
handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)132     public final void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
133     {
134         if (_outerScope==null)
135             doScope(target,baseRequest,request, response);
136         else
137             doHandle(target,baseRequest,request, response);
138     }
139 
140     /* ------------------------------------------------------------ */
141     /*
142      * Scope the handler
143      */
doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)144     public abstract void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
145         throws IOException, ServletException;
146 
147     /* ------------------------------------------------------------ */
148     /*
149      * Scope the handler
150      */
nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)151     public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
152         throws IOException, ServletException
153     {
154         // this method has been manually inlined in several locations, but
155         // is called protected by an if(never()), so your IDE can find those
156         // locations if this code is changed.
157         if (_nextScope!=null)
158             _nextScope.doScope(target,baseRequest,request, response);
159         else if (_outerScope!=null)
160             _outerScope.doHandle(target,baseRequest,request, response);
161         else
162             doHandle(target,baseRequest,request, response);
163     }
164 
165     /* ------------------------------------------------------------ */
166     /*
167      * Do the handler work within the scope.
168      */
doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)169     public abstract void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
170         throws IOException, ServletException;
171 
172     /* ------------------------------------------------------------ */
173     /*
174      * Do the handler work within the scope.
175      */
nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response)176     public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
177     {
178         // this method has been manually inlined in several locations, but
179         // is called protected by an if(never()), so your IDE can find those
180         // locations if this code is changed.
181         if (_nextScope!=null && _nextScope==_handler)
182             _nextScope.doHandle(target,baseRequest,request, response);
183         else if (_handler!=null)
184             _handler.handle(target,baseRequest, request, response);
185     }
186 
187     /* ------------------------------------------------------------ */
never()188     protected boolean never()
189     {
190         return false;
191     }
192 
193 }
194