KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > comp > helper > ComponentGateway


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: ComponentGateway.java,v 1.19 2004/02/01 05:16:27 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.comp.helper;
21
22 import java.io.*;
23 import java.util.*;
24 import javax.servlet.*;
25 import javax.servlet.http.*;
26
27 import org.apache.log4j.*;
28 import org.w3c.dom.*;
29
30 import org.enhydra.barracuda.core.comp.*;
31 import org.enhydra.barracuda.core.event.*;
32 import org.enhydra.barracuda.core.helper.servlet.*;
33 import org.enhydra.barracuda.core.util.dom.*;
34 import org.enhydra.barracuda.core.view.*;
35 import org.enhydra.barracuda.plankton.data.*;
36 import org.enhydra.barracuda.plankton.http.URLRewriter;
37 import org.enhydra.barracuda.plankton.exceptions.*;
38
39 /**
40  * <p>The component gateway is a servlet that provides a very simple
41  * interface to the Barracuda component model
42  */

43 public abstract class ComponentGateway extends HttpServlet {
44
45     //public vars...eventually, these should probably be final
46
protected static final Logger logger = Logger.getLogger(ComponentGateway.class.getName());
47 // public static boolean printPretty = false;
48
// public static boolean preventCaching = false;
49
public boolean recycleChildren = false;
50
51     //-------------------- ComponentGateway ----------------------
52
/**
53      * <p>Handle the default HttpRequest. This is the method developers
54      * will typically override. The developers shaould add any components
55      * to the root component and then return the underlying DOM Document (that
56      * backs their components) so it can be rendered
57      *
58      * @param root the root component which will get rendered as a result
59      * of this request
60      * @param vc the ViewContext object describes what features the
61      * client view is capable of supporting
62      * @param req the servlet request
63      * @param resp the servlet response
64      * @return the Document to be rendered
65      * @throws ServletException
66      * @throws IOException
67      */

68     public abstract Document handleDefault (BComponent root, ViewContext vc, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, RenderException, EventException;
69
70     /**
71      * <p>Handle an EventException. Basically, this is where we handle the
72      * really bad, unexpected type of event exceptions. Generally, as you code,
73      * if you want to interrupt the dispatch and fire a new event, you should
74      * throw an InterruptDispatchException. Only throw EventExceptions in
75      * truly exceptional circumstances.
76      *
77      * @param e the EventException to handle
78      * @param vc the ViewContext object describes what features the
79      * client view is capable of supporting
80      * @param req the servlet request
81      * @param resp the servlet response
82      * @throws ServletException
83      * @throws IOException
84      */

85     public void handleEventException (EventException e, ViewContext vc, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
86         //first see what the base exception is...if it's a servlet exception
87
//or an IOException, rethrow it...
88
Exception JavaDoc rootException = NestableException.getRootException(e);
89         if (rootException instanceof ServletException) throw (ServletException) rootException;
90         if (rootException instanceof IOException) throw (IOException) rootException;
91
92         //csc_061202.1 - added
93
//set the caching hdrs (this will allow the static resources to be cached by the browser)
94
resp.setHeader("Cache-Control","max-age=0");
95         resp.setDateHeader("Last-Modified", System.currentTimeMillis());
96
97         //if we get an EventException, log it and print the base exception
98
resp.setContentType("text/html");
99         PrintWriter out = resp.getWriter();
100         ExceptionUtil.logExceptionAsHTML(out, e, req);
101         logger.warn("Unexpected event exception: ", e);
102         if (rootException!=e) {
103             logger.warn("Root Exception: ", rootException);
104         }
105     }
106
107     /**
108      * <p>Handle a RenderException. Basically, this is where we handle the
109      * really bad, unexpected type of errors that occur while unexpectedldy
110      * rendering the component hierarchy.
111      *
112      * @param e the RenderException to handle
113      * @param vc the ViewContext object describes what features the
114      * client view is capable of supporting
115      * @param req the servlet request
116      * @param resp the servlet response
117      * @throws ServletException
118      * @throws IOException
119      */

120     public void handleRenderException (RenderException e, ViewContext vc, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
121         //first see what the base exception is...if it's a servlet exception
122
//or an IOException, rethrow it...
123
Exception JavaDoc rootException = NestableException.getRootException(e);
124         if (rootException instanceof ServletException) throw (ServletException) rootException;
125         if (rootException instanceof IOException) throw (IOException) rootException;
126
127         //csc_061202.1 - added
128
//set the caching hdrs (this will allow the static resources to be cached by the browser)
129
resp.setHeader("Cache-Control","max-age=0");
130         resp.setDateHeader("Last-Modified", System.currentTimeMillis());
131
132         //if we get a RenderException, log it and print the base exception
133
resp.setContentType("text/html");
134         PrintWriter out = resp.getWriter();
135         ExceptionUtil.logExceptionAsHTML(out, e, req);
136         logger.warn("Unexpected event exception: ", e);
137         if (rootException!=e) {
138             logger.warn("Root Exception:", rootException);
139         }
140     }
141
142     /**
143      * <p>Get a DOMWriter. By default, we use a DefaultDOMWriter. If
144      * you'd like to use something else, override this method.
145      *
146      * @return a DOMWriter to be used to render the DOM
147      */

148     public DOMWriter getDOMWriter() {
149         //return DefaultDOM writer
150
// return new DefaultDOMWriter(printPretty, preventCaching);
151
//since we don't override defaults here and there are no setter methods for
152
//printPretty, preventCaching, and maxAge in this class, don't bother storing
153
//this stuff in this class. Let DefaultDOMWriter deal with the defaults.
154
//If one wants specific behavior, override this method and set up the DOMWriter
155
//however you want.
156
return new DefaultDOMWriter();
157     }
158
159
160
161
162     //-------------------- HTTPServlet ---------------------------
163
/**
164      * <p>By default the GET request is mapped to the handleDefault method
165      *
166      * @param req the servlet request
167      * @param resp the servlet response
168      * @throws ServletException
169      * @throws IOException
170      */

171     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
172 //csc_102201.1_start
173
// handleDefault(new HttpServletRequestWrapper(req), resp);
174
boolean handled = ScriptDetector.checkClientReq(req, resp);
175 //csc_010404_1 if (!handled) handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
176
if (!handled) handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
177
//csc_102201.1_end
178
}
179     
180     /**
181      * <p>By default the POST request is mapped to the handleDefault method
182      *
183      * @param req the servlet request
184      * @param resp the servlet response
185      * @throws ServletException
186      * @throws IOException
187      */

188     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
189 //csc_010404_1 handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
190
handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
191
}
192     
193     /**
194      * <p>By default the OPTIONS request is mapped to the handleDefault method
195      *
196      * @param req the servlet request
197      * @param resp the servlet response
198      * @throws ServletException
199      * @throws IOException
200      */

201     protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
202 //csc_010404_1 handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
203
handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
204
}
205     
206     /**
207      * <p>By default the DELETE request is mapped to the handleDefault method
208      *
209      * @param req the servlet request
210      * @param resp the servlet response
211      * @throws ServletException
212      * @throws IOException
213      */

214     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
215 //csc_010404_1 handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
216
handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
217
}
218     
219     /**
220      * <p>By default the PUT request is mapped to the handleDefault method
221      *
222      * @param req the servlet request
223      * @param resp the servlet response
224      * @throws ServletException
225      * @throws IOException
226      */

227     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
228 //csc_010404_1 handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
229
handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
230
}
231     
232     /**
233      * <p>By default the TRACE request is mapped to the handleDefault method
234      *
235      * @param req the servlet request
236      * @param resp the servlet response
237      * @throws ServletException
238      * @throws IOException
239      */

240     protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
241 //csc_010404_1 handleDefault(new org.enhydra.barracuda.core.helper.servlet.HttpServletRequestWrapper(req), resp);
242
handleDefault(new DefaultServletRequestWrapper(req), new DefaultServletResponseWrapper(resp)); //csc_010404_1
243
}
244
245     protected void handleDefault(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
246
247         long bmillis = 0;
248         long smillis = 0;
249         long emillis = 0;
250         long elapsed1 = 0;
251         long elapsed2 = 0;
252         if (logger.isInfoEnabled()) bmillis = System.currentTimeMillis();
253         if (logger.isInfoEnabled()) logger.info("Handling incoming HTTP request in "+this);
254
255         ViewContext vc = null;
256         try {
257             //Session ObjectRepository
258
ObjectRepository.setupSessionRepository(req); //csc_022101.1
259

260             //start by figuring out the ViewCapabilities
261
if (logger.isDebugEnabled()) logger.debug("Create the ViewContext");
262 //csc_101701.1 vc = new DefaultViewContext(new ViewCapabilities(req, resp));
263
vc = new DefaultViewContext(new ViewCapabilities(req, resp), req, resp); //csc_101701.1
264

265             //create our root component
266
if (logger.isDebugEnabled()) logger.debug("Create component root");
267             BComponent broot = new BComponent();
268             broot.setName("Root");
269
270             //give the implementation a chance to add any components to the root
271
if (logger.isDebugEnabled()) logger.debug("Handling default");
272             Document doc = handleDefault(broot, vc, req, resp);
273             
274             //now init the component
275
if (logger.isDebugEnabled()) logger.debug("Invoking initCycle on component hierarchy");
276             broot.initCycle();
277             
278             //now render the component
279
if (logger.isDebugEnabled()) logger.debug("Rendering component hierarchy");
280             if (logger.isDebugEnabled()) smillis = System.currentTimeMillis();
281             broot.render(vc);
282             if (logger.isDebugEnabled()) elapsed1 = System.currentTimeMillis()-smillis;
283
284             //its possible the implementor may want to recycle children...if so, remove them
285
//prior to calling destroy on the root
286
if (recycleChildren) {
287                 if (logger.isDebugEnabled()) logger.debug("Recycling child components");
288                 List children = broot.getChildren();
289                 if (children!=null) {
290                     for (int i=children.size()-1; i>=0; i--) {
291                         broot.removeChild(i);
292                     }
293                 }
294             }
295
296             //now destroy the component
297
if (logger.isDebugEnabled()) logger.debug("Invoking destroyCycle on component hierarchy");
298             broot.destroyCycle();
299
300             //csc_102201.1
301
//now adjust the outgoing page (this is critical to make sure we
302
//can accurately detect client scripting)
303
ScriptDetector.prepareClientResp(doc, vc);
304
305             //now render the page
306
if (logger.isDebugEnabled()) logger.debug("Rendering the DOM");
307             if (logger.isInfoEnabled()) smillis = System.currentTimeMillis();
308             this.getDOMWriter().write(doc, resp);
309             if (logger.isInfoEnabled()) {
310                 elapsed2 = System.currentTimeMillis()-smillis;
311                 emillis = System.currentTimeMillis();
312             }
313
314             if (logger.isInfoEnabled()) logger.info("Dispatching complete! (rendered in "+(elapsed1)+"/written in "+(elapsed2)+" of "+(emillis-bmillis)+" millis)");
315
316         } catch (ClientSideRedirectException re) {
317             //csc_082302.2 - note that if you are using this class, it does not currently
318
//support persisting the local repository state across client side redirects the
319
//way ApplicationGateway does. ApplicationGateway does this by persisting the
320
//event context (which internally saves the local repository context too), but
321
//here we have no event context, and I'm not sure if its worth the effort to
322
//mimic the logic that goes on in DefaultEventContext here (or in some other class).
323
//I suppose it all depends on how many people are using components but not events
324
//(my guess is not many, so for now, I'm not going to worry about it. If this impacts
325
//you, holler...
326

327             //if we get a redirect exception, request the browser to redirect accordingly
328
// if (logger.isInfoEnabled()) logger.info("ClientSideRedirectException...redirecting to "+re.getRedirectURL());
329
// resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
330
// resp.setHeader("Location", re.getRedirectURL());
331

332             String JavaDoc url = URLRewriter.encodeRedirectURL(req, resp, re.getRedirectURL());
333             url = ScriptDetector.prepareRedirectURL(url, vc.getViewCapabilities()); //csc_102501.2
334
if (logger.isInfoEnabled()) logger.info("ClientSideRedirectException...redirecting to "+url);
335             resp.sendRedirect(url);
336
337         } catch (RenderException e) {
338             //if we get a RenderException, handle it
339
if (logger.isInfoEnabled()) logger.info("Handling RenderException:"+e);
340             handleRenderException(e, vc, req, resp);
341             
342         } catch (EventException e) {
343             //if we get an EventException, handle it
344
if (logger.isInfoEnabled()) logger.info("Handling EventException:"+e);
345             handleEventException(e, vc, req, resp);
346             
347         } finally {
348             //make sure we always clean up session/local repository stuff
349
ObjectRepository.removeSessionRepository(); //csc_022101.1
350
ObjectRepository.removeLocalRepository(); //csc_022101.1
351
}
352     }
353 }
354
Popular Tags