View Javadoc
1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.   
35   * 
36   * <p>When {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}
37   * is called on the first ScopedHandler in a chain of HandlerWrappers,
38   * the {@link #doScope(String, Request, HttpServletRequest, HttpServletResponse)} method is
39   * called on all contained ScopedHandlers, before the
40   * {@link #doHandle(String, Request, HttpServletRequest, HttpServletResponse)} method
41   * is called on all contained handlers.</p>
42   *
43   * <p>For example if Scoped handlers A, B &amp; C were chained together, then
44   * the calling order would be:</p>
45   * <pre>
46   * A.handle(...)
47   *   A.doScope(...)
48   *     B.doScope(...)
49   *       C.doScope(...)
50   *         A.doHandle(...)
51   *           B.doHandle(...)
52   *              C.doHandle(...)
53   * </pre>
54   *
55   * <p>If non scoped handler X was in the chained A, B, X &amp; C, then
56   * the calling order would be:</p>
57   * <pre>
58   * A.handle(...)
59   *   A.doScope(...)
60   *     B.doScope(...)
61   *       C.doScope(...)
62   *         A.doHandle(...)
63   *           B.doHandle(...)
64   *             X.handle(...)
65   *               C.handle(...)
66   *                 C.doHandle(...)
67   * </pre>
68   *
69   * <p>A typical usage pattern is:</p>
70   * <pre>
71   *     private static class MyHandler extends ScopedHandler
72   *     {
73   *         public void doScope(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
74   *         {
75   *             try
76   *             {
77   *                 setUpMyScope();
78   *                 super.doScope(target,request,response);
79   *             }
80   *             finally
81   *             {
82   *                 tearDownMyScope();
83   *             }
84   *         }
85   *
86   *         public void doHandle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
87   *         {
88   *             try
89   *             {
90   *                 doMyHandling();
91   *                 super.doHandle(target,request,response);
92   *             }
93   *             finally
94   *             {
95   *                 cleanupMyHandling();
96   *             }
97   *         }
98   *     }
99   * </pre>
100  */
101 public abstract class ScopedHandler extends HandlerWrapper
102 {
103     private static final ThreadLocal<ScopedHandler> __outerScope= new ThreadLocal<ScopedHandler>();
104     protected ScopedHandler _outerScope;
105     protected ScopedHandler _nextScope;
106 
107     /* ------------------------------------------------------------ */
108     /**
109      * @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart()
110      */
111     @Override
112     protected void doStart() throws Exception
113     {
114         try
115         {
116             _outerScope=__outerScope.get();
117             if (_outerScope==null)
118                 __outerScope.set(this);
119 
120             super.doStart();
121 
122             _nextScope= getChildHandlerByClass(ScopedHandler.class);
123 
124         }
125         finally
126         {
127             if (_outerScope==null)
128                 __outerScope.set(null);
129         }
130     }
131 
132     /** ------------------------------------------------------------ */
133     /*
134      */
135     @Override
136     public final void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
137     {
138         if (isStarted())
139         {
140             if (_outerScope==null)
141                 doScope(target,baseRequest,request, response);
142             else
143                 doHandle(target,baseRequest,request, response);
144         }
145     }
146 
147     /* ------------------------------------------------------------ */
148     /**
149      * Scope the handler
150      * <p>Derived implementations should call {@link #nextScope(String, Request, HttpServletRequest, HttpServletResponse)}
151      */
152     public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
153         throws IOException, ServletException
154     {
155         nextScope(target,baseRequest,request,response);
156     }
157 
158     /* ------------------------------------------------------------ */
159     /**
160      * Scope the handler
161      */
162     public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
163         throws IOException, ServletException
164     {
165         if (_nextScope!=null)
166             _nextScope.doScope(target,baseRequest,request, response);
167         else if (_outerScope!=null)
168             _outerScope.doHandle(target,baseRequest,request, response);
169         else
170             doHandle(target,baseRequest,request, response);
171     }
172 
173     /* ------------------------------------------------------------ */
174     /**
175      * Do the handler work within the scope.
176      * <p>Derived implementations should call {@link #nextHandle(String, Request, HttpServletRequest, HttpServletResponse)} 
177      */
178     public abstract void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
179         throws IOException, ServletException;
180 
181     /* ------------------------------------------------------------ */
182     /*
183      * Do the handler work within the scope.
184      */
185     public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
186     {
187         if (_nextScope!=null && _nextScope==_handler)
188             _nextScope.doHandle(target,baseRequest,request, response);
189         else if (_handler!=null)
190             super.handle(target,baseRequest,request,response);
191     }
192 }