KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > event > helper > BlockIterateHandler


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: BlockIterateHandler.java,v 1.17 2004/02/02 22:15:02 shawnw Exp $
19  */

20 package org.enhydra.barracuda.core.event.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 import org.w3c.dom.html.*;
30
31 import org.enhydra.barracuda.core.comp.*;
32 import org.enhydra.barracuda.core.util.dom.*;
33 import org.enhydra.barracuda.core.event.*;
34 import org.enhydra.barracuda.core.view.*;
35 import org.enhydra.barracuda.plankton.*;
36
37 import org.enhydra.xml.io.*;
38
39 /**
40  *
41  */

42 public abstract class BlockIterateHandler extends DefaultBaseEventListener {
43
44     //public vars...eventually, these should probably be final
45
public static Logger localLogger = Logger.getLogger(BlockIterateHandler.class.getName());
46     protected static final String JavaDoc NODE_ITERATOR_FLAG = "Dir::Block_Iterate.".toLowerCase();
47
48     //other vars
49
// protected String spaces = " ";
50
protected ViewContext vc = null;
51     protected BlockIterator bi = null;
52     
53     /**
54      * Public noargs constructor
55      */

56 // public BlockIterateHandler() {}
57

58
59     //-------------------- BlockIterateHandler -------------------
60
public void setViewContext(ViewContext ivc) {
61         vc = ivc;
62     }
63     
64     public ViewContext getViewContext() {
65         return vc;
66     }
67     
68     public void updateModelInTemplate(TemplateModel model) {
69         if (bi!=null) bi.updateModelInTemplate(model);
70     }
71     
72     public DOMWriter getDOMWriter() {
73         DefaultDOMWriter dw = new DefaultDOMWriter();
74         dw.setLeaveWriterOpen(true);
75         return dw;
76     }
77
78     /**
79      * you can override this method to handle any initializion
80      * needs for the handler. Its invoked after the view context info
81      * has been set up
82      */

83     public void initHandler() {
84     }
85
86     public abstract Class JavaDoc getTemplateClass();
87
88     public abstract BlockIterator getIterator(String JavaDoc key);
89
90     /**
91      * Handle the ViewEvent
92      */

93     public void handleViewEvent(ViewEventContext vec) throws EventException, ServletException, IOException {
94         long bmillis = 0;
95 // long smillis = 0;
96
// long emillis = 0;
97
// long elapsed1 = 0;
98
// long elapsed2 = 0;
99
if (localLogger.isInfoEnabled()) bmillis = System.currentTimeMillis();
100         if (localLogger.isInfoEnabled()) localLogger.info("Handling ViewEvent in "+this);
101
102         try {
103             //start by figuring out the ViewCapabilities
104
if (localLogger.isDebugEnabled()) localLogger.debug("Create the ViewContext");
105             setViewContext(new DefaultViewContext(vec));
106             HttpServletResponse resp = vec.getResponse();
107             PrintWriter out = resp.getWriter();
108
109             //give the handler a chance to initialize
110
initHandler();
111
112             //load the localized DOM template
113
if (localLogger.isDebugEnabled()) localLogger.debug("Getting the DOM Template");
114 //csc_061702.1 Document page = DefaultDOMLoader.getGlobalInstance().getDOM(getTemplateClass());
115
Document page = DefaultDOMLoader.getGlobalInstance().getDOM(getTemplateClass(), vec.getViewCapabilities().getClientLocale()); //csc_061702.1
116

117 //csc_012804_1_start
118
/*
119             //csc_061202.1 - added
120             //set the caching hdrs (this will allow the static resources to be cached by the browser)
121             resp.setHeader("Cache-Control","max-age=0");
122             resp.setDateHeader("Last-Modified", System.currentTimeMillis());
123
124             //set the content header & then process the page
125             boolean isHtml = false;
126             String responseType = "text/xml";
127             if (page instanceof HTMLDocument) {
128                 responseType = "text/html";
129                 isHtml = true;
130             }
131             resp.setContentType(responseType);
132             if (localLogger.isDebugEnabled()) localLogger.debug("Printing page (content type: "+responseType+")");
133 */

134             //prepare the response (sets the appropriate headers)
135
getDOMWriter().prepareResponse(resp);
136 //csc_012804_1_end
137

138           //saw_020204_1 begin
139
//This is a bit of an ugly hack, but our HTML DOM trees don't have a DOCTYPE node within
140
//them which means we can't print it out via normal means (apparently DOMFormatter
141
//usually does this for us when it encounters a Document node and the appropriate
142
//OutputOptions. Since we don't want the whole DOM tree to print at once we can't simply
143
//pass the Document node to the DOMWriter (and therefore DOMFormatter).
144
DOMWriter dw = getDOMWriter();
145             if (dw instanceof DefaultDOMWriter && page.getDoctype()==null) {
146                 OutputOptions oo = ((DefaultDOMWriter) dw).getOutputOptions();
147                 if (oo==null) oo = DefaultDOMWriter.getDefaultOutputOptions(page);
148                 
149                 if (!oo.getOmitDocType()) {
150                     out.print("<!DOCTYPE ");
151                     out.print(page.getDocumentElement().getNodeName());
152                     
153                     String JavaDoc publicId = oo.getPublicId();
154                     if (publicId!=null) out.print(" PUBLIC \""+publicId+"\"");
155                     
156                     String JavaDoc systemId = oo.getSystemId();
157                     if (systemId!=null) out.print(" \""+systemId+"\"");
158                     
159                     out.println(">");
160                 }
161             }
162           //saw_020204_1 end
163

164             
165 //saw_020204_1 Element root = page.getDocumentElement();
166
//csc_012804_1 printNode(page, out, 0, isHtml);
167
printNode(page, out, 0, (page instanceof HTMLDocument)); //csc_012804_1
168
out.close();
169
170             if (localLogger.isInfoEnabled()) localLogger.info("ViewEvent handled! (rendered in "+(System.currentTimeMillis()-bmillis)+" millis)");
171         
172         } catch (RenderException e) {
173             //if we get an EventException, handle it
174
if (localLogger.isInfoEnabled()) localLogger.info("Unexpected RenderException:"+e);
175             throw new EventException ("Unexpected RenderException:"+e, e);
176
177         } catch (IOException e) {
178             localLogger.warn("Unexpected IOException:"+e);
179             e.printStackTrace();
180             throw e;
181
182         } catch (RuntimeException JavaDoc e) {
183             localLogger.warn("Unexpected RuntimeException:"+e);
184             e.printStackTrace();
185             throw e;
186             
187         } finally {
188             //cleanup
189
vc = null;
190             bi = null;
191             
192             //as a final measure, ask the system to invoke gc()
193
System.gc();
194         }
195
196     }
197
198     public void printNode(Node node, PrintWriter out, int depth, boolean isHtml) throws RenderException, IOException {
199         //element
200
if (node instanceof Element) {
201             Element el = (Element) node;
202             //first of all, look for the Node_Iterator directive in the attributes
203
String JavaDoc blockIteratorName = null;
204             Attr attr = el.getAttributeNode("class");
205             if (attr!=null) {
206                 String JavaDoc value = attr.getValue();
207                 int spos = value.toLowerCase().indexOf(NODE_ITERATOR_FLAG);
208                 if (spos>-1) {
209                     int lpos = value.length();
210                     int epos = value.indexOf(" ", spos+NODE_ITERATOR_FLAG.length());
211                     if (epos<0 || epos>lpos) epos = lpos;
212                     blockIteratorName = value.substring(spos+NODE_ITERATOR_FLAG.length(), epos);
213                     value = value.substring(0,spos)+(epos<lpos ? value.substring(epos+1, lpos) : "");
214                     attr.setValue(value);
215                 }
216             }
217
218             //if we have a blockIteratorName, use that
219
if (blockIteratorName!=null) {
220                 if (localLogger.isDebugEnabled()) localLogger.debug("Found Block_Iterator directive:"+blockIteratorName);
221                 int cntr = 0;
222                 bi = getIterator(blockIteratorName);
223                 if (bi!=null) {
224                     try {
225                         //pre-iterate
226
bi.preIterate(); //csc_111003_1
227

228                         //iterate
229
while (bi.hasNext()) {
230                             //get the new node (which the component has already rendered into)
231
Node templateNode = node.cloneNode(true);
232     // vc.putState(ViewContext.TEMPLATE_NODE, templateNode);
233
// bi.setTemplateNode(templateNode);
234
Node newNode = bi.next(getViewContext(), templateNode);
235                             cntr++;
236                             if (localLogger.isDebugEnabled()) localLogger.debug("Got block "+cntr+", node: "+newNode);
237                             if (newNode==null) continue;
238                         
239                             //now render this node to the output stream
240
DOMWriter dw = getDOMWriter();
241                             dw.setLeaveWriterOpen(true);
242                             dw.write(newNode, out);
243                             if (localLogger.isDebugEnabled()) localLogger.debug("Successfully rendered node!");
244                         }
245                     } finally {
246                         //post-iterate
247
if (bi!=null) bi.postIterate(); //csc_111003_1
248

249                         bi = null;
250                     }
251                 } else {
252                     if (localLogger.isDebugEnabled()) localLogger.warn("Failed to locate corresponding BlockIterator class!");
253                     out.println("");
254                     out.println("");
255                     out.println("<!-- Missing Iterator: "+blockIteratorName+" -->");
256                     out.println("");
257                 }
258
259             //otherwise, just print the tag and attributes
260
} else {
261                 //unfortunately, there's really no way to defer this to the
262
//DOMWriter, since we have no idea if the child nodes contain
263
//any block iterator tags. Consequently, we have to manually
264
//print the tag...
265

266                 //csc_013004_1
267
//this is a VERY hacky way of doing this, but I can't think of anything else
268
//right now without expanding the DOMWriter interface, and I'm not sure we really
269
//want to do that. Baically, if we are writing to a CommaSeparatedDOMWriter there
270
//are certain tags that should get converted to "" (ie. they don't get printed, but
271
//their children still get processed). SO...
272
String JavaDoc tag = el.getTagName().toLowerCase();
273                 boolean printNode = true;
274                 DOMWriter dw = getDOMWriter();
275                 if (dw instanceof CommaSeparatedDOMWriter) {
276                     printNode = (!tag.equals(CommaSeparatedDOMWriter.DOCUMENT_TYPE) &&
277                                  !tag.equals(CommaSeparatedDOMWriter.ELEMENT_ROW) &&
278                                  !tag.equals(CommaSeparatedDOMWriter.ELEMENT_HEADER) &&
279                                  !tag.equals(CommaSeparatedDOMWriter.ELEMENT_COLUMN));
280                 }
281
282                 //now print the start tag
283
if (printNode) {
284                     out.print("<"+el.getTagName());
285                     String JavaDoc sep = " ";
286                     NamedNodeMap nnm = el.getAttributes();
287                     for (int i=0, max=nnm.getLength(); i<max; i++) {
288                         attr = (Attr) nnm.item(i);
289                         out.print(sep+attr);
290                     }
291                     out.print(">");
292                 }
293                         
294                 //print the children
295
printChildNodes(node, out, depth, isHtml);
296         
297                 //print the closing tag (if it's not forbidden, as the given html tags are)
298
if (printNode) {
299                     if (!isHtml ||
300                        (!tag.equals("area") && !tag.equals("base") && !tag.equals("basefont") &&
301                         !tag.equals("br") && !tag.equals("col") && !tag.equals("frame") &&
302                         !tag.equals("hr") && !tag.equals("image") && !tag.equals("input") &&
303                         !tag.equals("isindex") && !tag.equals("link") && !tag.equals("meta") &&
304                         !tag.equals("param"))) {
305                         out.print("</"+el.getTagName()+">");
306                     }
307                 }
308             }
309         
310 //csc_012804_1_start
311
/*
312 this is now handled in the default 'else' portion below
313         //character data
314         } else if (node instanceof CharacterData) {
315             //we want to defer this node back to the DOMWriter (because some writers may want to suppress this)
316 // if (node instanceof Comment) out.print("<!-- ");
317 // out.print(((CharacterData) node).getData());
318 // if (node instanceof Comment) out.print("-->");
319             getDOMWriter().write(node, out);
320 */

321 //csc_012804_1_end
322

323         //node with child nodes
324
} else if (node.hasChildNodes()) {
325 //System.out.println("Has children:"+node.getClass().getName());
326
printChildNodes(node, out, depth, isHtml);
327
328         //anything else - just defer back to the DOMWriter...
329
} else {
330 //csc_012804_1_start
331
// System.out.println("Unhandled element:"+node.getClass().getName());
332
// org.enhydra.barracuda.plankton.data.CollectionsUtil.printStackTrace(Classes.getAllInterfaces(node));
333
DOMWriter dw = getDOMWriter();
334             dw.setLeaveWriterOpen(true);
335             dw.write(node, out);
336 //csc_012804_1_end
337
}
338     }
339
340     public void printChildNodes(Node node, PrintWriter out, int depth, boolean isHtml) throws RenderException, IOException {
341         Node child = node.getFirstChild();
342         if (child==null) return;
343         do {
344             printNode(child, out, depth+1, isHtml);
345             child = child.getNextSibling();
346         } while (child!=null);
347     }
348 }
349
Popular Tags