View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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 & 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 & 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      */
151     public abstract void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
152         throws IOException, ServletException;
153 
154     /* ------------------------------------------------------------ */
155     /*
156      * Scope the handler
157      */
158     public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
159         throws IOException, ServletException
160     {
161         // this method has been manually inlined in several locations, but
162         // is called protected by an if(never()), so your IDE can find those
163         // locations if this code is changed.
164         if (_nextScope!=null)
165             _nextScope.doScope(target,baseRequest,request, response);
166         else if (_outerScope!=null)
167             _outerScope.doHandle(target,baseRequest,request, response);
168         else
169             doHandle(target,baseRequest,request, response);
170     }
171 
172     /* ------------------------------------------------------------ */
173     /*
174      * Do the handler work within the scope.
175      */
176     public abstract void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
177         throws IOException, ServletException;
178 
179     /* ------------------------------------------------------------ */
180     /*
181      * Do the handler work within the scope.
182      */
183     public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
184     {
185         // this method has been manually inlined in several locations, but
186         // is called protected by an if(never()), so your IDE can find those
187         // locations if this code is changed.
188         if (_nextScope!=null && _nextScope==_handler)
189             _nextScope.doHandle(target,baseRequest,request, response);
190         else if (_handler!=null)
191             _handler.handle(target,baseRequest, request, response);
192     }
193 
194     /* ------------------------------------------------------------ */
195     protected boolean never()
196     {
197         return false;
198     }
199 
200 }