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 & 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 * <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 }