KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > bridge > jsp > taglib > ContentTag


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.bridge.jsp.taglib;
11
12 import org.mmbase.bridge.jsp.taglib.util.Attribute;
13 import javax.servlet.jsp.JspTagException JavaDoc;
14 import javax.servlet.jsp.PageContext JavaDoc;
15 import javax.servlet.http.*;
16
17 import java.util.*;
18 import java.io.InputStream JavaDoc;
19 import java.net.URL JavaDoc;
20 import java.net.URLConnection JavaDoc;
21
22 import org.mmbase.util.transformers.*;
23 import org.mmbase.util.xml.DocumentReader;
24 import org.mmbase.util.functions.Parameters;
25
26 import org.mmbase.util.*;
27 import org.mmbase.security.UserContext;
28
29 import org.xml.sax.InputSource JavaDoc;
30 import org.w3c.dom.Element JavaDoc;
31
32
33 import org.mmbase.util.logging.Logger;
34 import org.mmbase.util.logging.Logging;
35
36 /**
37  * Provided environmental information to its body's tags.
38  *
39  * @author Michiel Meeuwissen
40  * @since MMBase-1.7
41  * @version $Id: ContentTag.java,v 1.57 2006/08/30 18:01:50 michiel Exp $
42  **/

43
44 public class ContentTag extends LocaleTag {
45     private static Logger log;
46
47
48     static final CharTransformer COPY = CopyCharTransformer.INSTANCE;
49
50     private static final long DEFAULT_EXPIRE_TIME = 60; // one minute
51

52     public static final String JavaDoc ESCAPER_KEY = "org.mmbase.bridge.jsp.taglib.escaper";
53
54     static final ContentTag DEFAULT = new ContentTag() {
55             public CharTransformer getWriteEscaper() { return COPY; }
56             public String JavaDoc getType() { return "text/html"; }
57             public String JavaDoc getEncoding(){ return "ISO-8859-1"; }
58         };
59
60     private static final Map defaultEscapers = new HashMap(); // contenttype id -> chartransformer id
61
private static final Map defaultPostProcessors = new HashMap(); // contenttype id -> chartransformer id
62
private static final Map defaultEncodings = new HashMap(); // contenttype id -> charset to be used in content-type header (defaults to UTF-8)
63

64     private static final Map contentTypes = new HashMap(); // contenttype id -> contenttype
65

66     private static final Map charTransformers = new HashMap(); // chartransformer id -> chartransformer instance.
67
private static final Map parameterizedCharTransformerFactories = new HashMap(); // chartransformer id -> chartransformer factories.
68

69     static {
70         try {
71             log = Logging.getLoggerInstance(ContentTag.class);
72             org.mmbase.util.XMLEntityResolver.registerPublicID("-//MMBase//DTD taglibcontent 1.0//EN", "taglibcontent_1_0.dtd", ContentTag.class);
73             ResourceWatcher watcher = new ResourceWatcher(ResourceLoader.getConfigurationRoot().getChildResourceLoader("taglib")) {
74                     public void onChange(String JavaDoc resource) {
75                         defaultEscapers.clear();
76                         defaultPostProcessors.clear();
77                         defaultEncodings.clear();
78                         charTransformers.clear();
79                         parameterizedCharTransformerFactories.clear();
80                         contentTypes.clear();
81                         initialize(getResourceLoader(), resource);
82                     }
83                 };
84             watcher.add("content.xml");
85             watcher.start();
86             watcher.onChange("content.xml");
87         } catch (Exception JavaDoc e) {
88             log.error(e.toString());
89         }
90     }
91
92
93     private static CharTransformer readCharTransformer(DocumentReader reader, Element JavaDoc parentElement, String JavaDoc id) {
94         List result = new ArrayList();
95         Iterator e = reader.getChildElements(parentElement, "class");
96         while (e.hasNext()) {
97             Element JavaDoc element = (Element JavaDoc) e.next();
98             String JavaDoc claz = reader.getElementValue(element);
99
100             String JavaDoc config = element.getAttribute("config");
101             boolean back = "true".equalsIgnoreCase(element.getAttribute("back"));
102
103             CharTransformer ct = Transformers.getCharTransformer(claz, config, " escaper " + id, back);
104             if (ct == null) continue;
105             result.add(ct);
106         }
107         if (result.size() == 0) {
108             return COPY;
109         } else if (result.size() == 1) {
110             return (CharTransformer) result.get(0);
111         } else {
112             ChainedCharTransformer cct = new ChainedCharTransformer();
113             cct.addAll(result);
114             return cct;
115         }
116     }
117
118     private static ParameterizedTransformerFactory readTransformerFactory(final DocumentReader reader, final Element JavaDoc parentElement, final String JavaDoc id) {
119         Iterator e = reader.getChildElements(parentElement, "class");
120         Element JavaDoc element = (Element JavaDoc) e.next();
121         final String JavaDoc claz = reader.getElementValue(element);
122
123         e = reader.getChildElements(parentElement, "param");
124         final Map configuredParams = new HashMap();
125         while (e.hasNext()) {
126             Element JavaDoc param = (Element JavaDoc) e.next();
127             String JavaDoc name = param.getAttribute("name");
128             String JavaDoc value = param.getAttribute("value");
129             if (! value.equals("")) {
130                 configuredParams.put(name, value);
131             }
132         }
133         if (configuredParams.size() == 0) {
134             return Transformers.getTransformerFactory(claz, " parameterizedescaper " + id);
135         } else {
136             return new ParameterizedTransformerFactory() {
137                     ParameterizedTransformerFactory wrapped = Transformers.getTransformerFactory(claz, " parameterizedescaper " + id);
138
139                     public Transformer createTransformer(Parameters parameters) {
140                         return wrapped.createTransformer(parameters);
141                     }
142                     public Parameters createParameters() {
143                         Parameters params = wrapped.createParameters();
144                         params.setAll(configuredParams);
145                         return params;
146                     }
147
148                 };
149         }
150     }
151     /**
152      * Initialize the write-escapers for MMBase taglib.
153      */

154     private static void initialize(ResourceLoader taglibLoader, String JavaDoc resource) {
155         log.service("Reading taglib write-escapers");
156         InputStream JavaDoc stream = ContentTag.class.getResourceAsStream("resources/taglibcontent.xml");
157         if (stream != null) {
158             log.service("Reading backwards compatible resource " + ContentTag.class.getName() + "/resources/taglibcontent.xml");
159             InputSource JavaDoc escapersSource = new InputSource JavaDoc(stream);
160             readXML(escapersSource);
161         }
162         List resources = taglibLoader.getResourceList(resource);
163         log.service("Using " + resources);
164         ListIterator i = resources.listIterator();
165         while (i.hasNext()) i.next();
166         while (i.hasPrevious()) {
167             try {
168                 URL JavaDoc u = (URL JavaDoc) i.previous();
169                 log.debug("Reading " + u);
170                 URLConnection JavaDoc con = u.openConnection();
171                 if (con.getDoInput()) {
172                     InputSource JavaDoc source = new InputSource JavaDoc(con.getInputStream());
173                     readXML(source);
174                 }
175             } catch (Exception JavaDoc e) {
176                 log.error(e);
177             }
178         }
179         {
180             List l = new ArrayList(charTransformers.keySet());
181             Collections.sort(l);
182             log.service("Found escapers: " + l);
183             l = new ArrayList(parameterizedCharTransformerFactories.keySet());
184             Collections.sort(l);
185             log.service("Found parameterized escapers: " + l);
186             l = new ArrayList(contentTypes.keySet());
187             Collections.sort(l);
188             log.service("Recognized content-types: " + l);
189         }
190
191     }
192
193     protected static void readXML(InputSource JavaDoc escapersSource) {
194
195         DocumentReader reader = new DocumentReader(escapersSource, ContentTag.class);
196         Element JavaDoc root = reader.getElementByPath("taglibcontent");
197
198         for (Iterator iter = reader.getChildElements(root, "escaper"); iter.hasNext();) {
199             Element JavaDoc element = (Element JavaDoc) iter.next();
200             String JavaDoc id = element.getAttribute("id");
201             CharTransformer ct = readCharTransformer(reader, element, id);
202             CharTransformer prev = (CharTransformer) charTransformers.put(id, ct);
203             if (prev != null) {
204                 log.warn("Replaced an escaper '" + id + "' : " + ct + "(was " + prev + ")");
205             } else {
206                 log.debug("Found an escaper '" + id + "' : " + ct);
207             }
208
209         }
210
211         log.debug("Reading content tag parameterizedescaperss");
212         for (Iterator iter = reader.getChildElements(root, "parameterizedescaper"); iter.hasNext();) {
213             Element JavaDoc element = (Element JavaDoc) iter.next();
214             String JavaDoc id = element.getAttribute("id");
215             ParameterizedTransformerFactory fact = readTransformerFactory(reader, element, id);
216             ParameterizedTransformerFactory prev = (ParameterizedTransformerFactory) parameterizedCharTransformerFactories.put(id, fact);
217             if (prev != null) {
218                 log.warn("Replaced an parameterized escaper '" + id + "' : " + fact + " (was " + prev + ")");
219             } else {
220                 log.debug("Found an parameterized escaper '" + id + "' : " + fact);
221             }
222
223             try {
224                 CharTransformer ct = (CharTransformer) fact.createTransformer(fact.createParameters());
225                 if (! charTransformers.containsKey("id")) {
226                     log.debug("Could be instantiated with default parameters too");
227                     charTransformers.put(id, ct);
228                 } else {
229                     log.service("Already a chartransformer with id " + id);
230                 }
231             } catch (Exception JavaDoc ex) {
232                 log.debug("Could not be instantiated with default parameters only: " + ex.getMessage());
233             }
234
235         }
236
237
238         Set postProcessors = new HashSet();
239         log.debug("Reading content tag post-processors");
240         for (Iterator iter = reader.getChildElements(root, "postprocessor"); iter.hasNext();) {
241             Element JavaDoc element = (Element JavaDoc) iter.next();
242             String JavaDoc id = element.getAttribute("id");
243             CharTransformer ct = readCharTransformer(reader, element, id);
244             CharTransformer prev = (CharTransformer) charTransformers.put(id, ct);
245             if (prev != null) {
246                 log.warn("Replaced an postprocessor '" + id + "' : " + ct + " (was " + prev + ")");
247             } else {
248                 log.debug("Found an postprocessor '" + id + "' : " + ct);
249             }
250             postProcessors.add(id);
251         }
252         if (postProcessors.size() > 0) {
253             log.service("Found post-processors: " + postProcessors);
254         }
255
256         for (Iterator iter = reader.getChildElements(root, "content"); iter.hasNext();) {
257             Element JavaDoc element = (Element JavaDoc) iter.next();
258             String JavaDoc type = element.getAttribute("type");
259             String JavaDoc id = element.getAttribute("id");
260             if (id.equals("")) {
261                 id = type;
262             }
263             contentTypes.put(id, type);
264             String JavaDoc defaultEscaper = element.getAttribute("defaultescaper");
265             if (! defaultEscaper.equals("")) {
266                 if (charTransformers.containsKey(defaultEscaper)) {
267                     defaultEscapers.put(id, defaultEscaper);
268                 } else {
269                     log.warn("Default escaper '" + defaultEscaper + "' for type + '"+ type + "' is not known");
270                 }
271             }
272             String JavaDoc defaultPostprocessor = element.getAttribute("defaultpostprocessor");
273             if (! defaultPostprocessor.equals("")) {
274                 if (charTransformers.containsKey(defaultPostprocessor)) {
275                     defaultPostProcessors.put(id, defaultPostprocessor);
276                 } else {
277                     log.warn("Default postprocessor '" + defaultPostprocessor + "' for type + '"+ type + "' is not known");
278                 }
279             }
280             String JavaDoc defaultEncoding = element.getAttribute("defaultencoding");
281             if (! defaultEncoding.equals("NOTSPECIFIED")) {
282                 defaultEncodings.put(id, defaultEncoding);
283             }
284         }
285
286     }
287
288
289     private Attribute type = Attribute.NULL;
290     private Attribute encoding = Attribute.NULL;
291     private Attribute escaper = Attribute.NULL;
292     private Attribute postprocessor = Attribute.NULL;
293     private Attribute expires = Attribute.NULL;
294     private Attribute status = Attribute.NULL;
295     private Attribute refresh = Attribute.NULL;
296
297
298     public void setType(String JavaDoc ct) throws JspTagException JavaDoc {
299         type = getAttribute(ct);
300     }
301
302     public void setEncoding(String JavaDoc e) throws JspTagException JavaDoc {
303         encoding = getAttribute(e);
304     }
305
306     public void setEscaper(String JavaDoc e) throws JspTagException JavaDoc {
307         escaper = getAttribute(e);
308     }
309
310     public void setPostprocessor(String JavaDoc e) throws JspTagException JavaDoc {
311         postprocessor = getAttribute(e);
312     }
313
314     public void setExpires(String JavaDoc e) throws JspTagException JavaDoc {
315         expires = getAttribute(e);
316     }
317
318
319     public String JavaDoc getType() throws JspTagException JavaDoc {
320         if (type == Attribute.NULL) {
321             return "text/html"; // implicit
322
} else {
323             String JavaDoc ct = type.getString(this);
324             String JavaDoc c = (String JavaDoc) contentTypes.get(ct);
325             if (c != null) return c;
326             return ct;
327         }
328     }
329
330     public void setStatus(String JavaDoc s) throws JspTagException JavaDoc {
331         status = getAttribute(s);
332     }
333     public void setRefresh(String JavaDoc r) throws JspTagException JavaDoc {
334         refresh = getAttribute(r);
335     }
336
337
338
339     /*
340     protected int getVersion() {
341         return 1;
342     }
343     */

344
345
346     /**
347      * @return A CharTransformer or null if no postprocessing needed
348      * @throws JspTagException can occur if taglibcontent.xml is misconfigured
349      */

350     protected CharTransformer getPostProcessor() throws JspTagException JavaDoc {
351         if (! postprocessor.getString(this).equals("")) {
352             return getCharTransformer(postprocessor.getString(this), this);
353         } else {
354             if (type != Attribute.NULL) {
355                 String JavaDoc defaultPostProcessor = (String JavaDoc) defaultPostProcessors.get(type.getString(this));
356                 if (defaultPostProcessor != null) {
357                     return getCharTransformer(defaultPostProcessor, this);
358                 }
359             }
360             return null;
361         }
362     }
363
364
365     public String JavaDoc getEncoding() throws JspTagException JavaDoc {
366         if (encoding == Attribute.NULL) {
367             String JavaDoc defaultEncoding = (String JavaDoc) defaultEncodings.get(getType());
368             if (defaultEncoding == null) {
369                 return "UTF-8"; // implicit
370
} else {
371                 return defaultEncoding;
372             }
373         } else {
374             return encoding.getString(this);
375         }
376     }
377
378     /**
379      * Gets a CharTransformer identified by <code>id<code>, withouth trying to create chains of
380      * them.
381      */

382     protected static CharTransformer getSimpleCharTransformer(String JavaDoc id, ContextReferrerTag tag) throws JspTagException JavaDoc {
383         CharTransformer c = (CharTransformer) charTransformers.get(id);
384         if (c == null && tag != null) c = (CharTransformer) tag.getContextProvider().getContextContainer().get(id);
385         if (c == null) {
386             int paramsPos = id.indexOf('(');
387             if (paramsPos > 0 && id.charAt(id.length() - 1) == ')') { // inline parameterized
388
// like substring(2,3)
389
String JavaDoc parameterized = id.substring(0, paramsPos);
390                 ParameterizedTransformerFactory factory = getTransformerFactory(parameterized);
391                 Parameters parameters = factory.createParameters();
392                 parameters.setAutoCasting(true);
393                 if (tag != null) {
394                     tag.fillStandardParameters(parameters);
395                 }
396                 parameters.setAll(StringSplitter.split(id.substring(paramsPos + 1, id.length() - 1)));
397                 c = (CharTransformer) factory.createTransformer(parameters);
398             } else {
399                 // try if there is a factory with this name, which would work with only 'standard' parameters.
400
ParameterizedTransformerFactory factory = getTransformerFactory(id);
401                 log.debug("Found factory for " + id + " " + factory);
402                 if (factory != null) {
403                     Parameters parameters = factory.createParameters();
404                     parameters.setAutoCasting(true);
405                     if (tag != null) {
406                         tag.fillStandardParameters(parameters);
407                     }
408                     c = (CharTransformer) factory.createTransformer(parameters);
409                 }
410             }
411         }
412         if (c == null) throw new JspTagException JavaDoc("The chartransformer " + id + " is unknown");
413         return c;
414     }
415
416     /**
417      * Gets a CharTransformer identified by <code>id</code>, which possibly can also be list of id's
418      * in which case a chain of chartransformers will be returned.
419      * @return A CharTransformer
420      * @throws JspTagException if not transformer with given id was configured
421      */

422
423     public static CharTransformer getCharTransformer(String JavaDoc id, ContextReferrerTag tag) throws JspTagException JavaDoc {
424
425         List transs = org.mmbase.util.StringSplitter.splitFunctions(id);
426
427         if (transs.size() > 1) {
428             ChainedCharTransformer ct = new ChainedCharTransformer();
429             // Iterator ids = StringSplitter.split(id).iterator();
430
Iterator ids = transs.iterator();
431             while (ids.hasNext()) {
432                 String JavaDoc i = (String JavaDoc) ids.next();
433                 CharTransformer c = getSimpleCharTransformer(i, tag);
434                 if (ct != COPY) {
435                     ct.add(c);
436                 }
437             }
438             return ct;
439         } else {
440             CharTransformer ct = getSimpleCharTransformer(id, tag);
441             if (ct != COPY) {
442                 return ct;
443             } else {
444                 return null;
445             }
446
447         }
448     }
449
450     /**
451      * Returns transformer factory with given id or throws exception if there is none
452      */

453     public static ParameterizedTransformerFactory getTransformerFactory(String JavaDoc id) throws JspTagException JavaDoc {
454         ParameterizedTransformerFactory fact = (ParameterizedTransformerFactory) parameterizedCharTransformerFactories.get(id);
455         if (fact == null) throw new JspTagException JavaDoc("The chartransformerfactory " + id + " is unknown");
456         return fact;
457     }
458
459     /**
460      * Called by children
461      * @return A CharTransformer (not null)
462      */

463
464     public CharTransformer getWriteEscaper() {
465         return (CharTransformer) pageContext.findAttribute(ESCAPER_KEY);
466     }
467     private CharTransformer prevEscaper = null;
468
469     protected void setWriteEscaper() throws JspTagException JavaDoc {
470         prevEscaper = getWriteEscaper();
471         CharTransformer esc;
472         if (! escaper.getString(this).equals("")) {
473             esc = getCharTransformer(escaper.getString(this), this);
474         } else {
475             String JavaDoc defaultEscaper = (String JavaDoc) defaultEscapers.get(getType());
476             if (defaultEscaper != null) {
477                 esc = getCharTransformer(defaultEscaper, this);
478             } else {
479                 esc = COPY;
480             }
481         }
482         pageContext.setAttribute(ESCAPER_KEY, esc, PageContext.REQUEST_SCOPE);
483     }
484     protected void unsetWriteEscaper() {
485         if (prevEscaper == null) {
486             pageContext.removeAttribute(ESCAPER_KEY, PageContext.REQUEST_SCOPE);
487         } else {
488             pageContext.setAttribute(ESCAPER_KEY, prevEscaper, PageContext.REQUEST_SCOPE);
489         }
490     }
491
492     /**
493      * @see org.mmbase.bridge.jsp.taglib.LocaleTag#determineLocale()
494      */

495     protected void determineLocale() throws JspTagException JavaDoc {
496         // only set the locale when attributes are present or inside CloudProviderTag
497
determineLocaleFromAttributes();
498         if (locale == null) {
499             determineFromCloudProvider();
500         }
501     }
502
503     public int doStartTag() throws JspTagException JavaDoc {
504         super.doStartTag();
505         setWriteEscaper();
506         String JavaDoc type = getType();
507
508         addedCacheHeaders = false;
509         if (! type.equals("")) {
510             HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
511             HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
512             if (locale != null) {
513                 response.setLocale(locale);
514             }
515             String JavaDoc enc = getEncoding();
516             log.debug("Found encoding " + enc);
517             if (enc.equals("")) {
518                 response.setContentType(getType()); // sadly, tomcat does not allow for not setting the charset, it will simply do it always
519
} else {
520                 response.setContentType(getType() + ";charset=" + enc);
521             }
522
523             if (expires == Attribute.NULL && request.getSession(false) == null) { // if no session, can as well cache in proxy
524
addNoCacheHeaders(request, response, DEFAULT_EXPIRE_TIME);
525             } else {
526                 // there is a session, or 'expires' was set explicitely
527
// perhaps default cache behaviour should be no-cache if there is a session?
528
long exp = expires.getLong(this, DEFAULT_EXPIRE_TIME);
529                 addNoCacheHeaders(request, response, exp);
530             }
531         }
532         if (getPostProcessor() == null) {
533             log.debug("no postprocessor");
534             return EVAL_BODY;
535         } else {
536             return EVAL_BODY_BUFFERED;
537         }
538     }
539     private boolean addedCacheHeaders = false;
540
541     /**
542      * The code first sets the Expires header to a date in the
543      * past. This indicates to the recipient that the page's content
544      * have already expired, as a hint that it's contents should not be
545      * cached. The no-cache value for the Pragma header is provided by
546      * version 1.0 of the HTTP protocol to further indicate that
547      * browsers and proxy servers should not cache a page. Version 1.1
548      * of HTTP replaces this header with a more specific Cache-Control
549      * header, but recommends including the Pragma header as well for
550      * backward compatibility.
551      *
552      * @param response - http response
553      * @param expire - seconds before content should expire
554      * @since MMBase 1.8.1
555      */

556     protected void addNoCacheHeaders(HttpServletRequest request, HttpServletResponse response, long expire) {
557         if (request.getAttribute(org.mmbase.bridge.jsp.taglib.pageflow.IncludeTag.INCLUDE_PATH_KEY) == null) {
558             if (expire <= 0) {
559                 // Add some header to make sure these pages are not cached anywhere.
560
// Set standard HTTP/1.1 no-cache headers.
561
response.setHeader("Cache-Control","no-cache, no-store, must-revalidate, proxy-revalidate");
562                 // Set IE extended HTTP/1.1 no-cache headers
563
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
564                 // Set standard HTTP/1.0 no-cache header.
565
response.setHeader("Pragma", "no-cache");
566                 response.setDateHeader ("Expires", -1);
567
568                 // long now = System.currentTimeMillis();
569
// according to rfc2616 sec14 'already expires' means that date-header is expires header
570
// sadly, this does not work:
571
// perhaps because tomcat overrides the date header later, so a difference of a second can occur
572
// response.setDateHeader("Date", now);
573
} else {
574                 // calc the string in GMT not localtime and add the offset
575
response.setDateHeader ("Expires", System.currentTimeMillis() + (expire * 1000));
576                 response.setHeader("Cache-Control", "public");
577             }
578             addedCacheHeaders = true;
579         } else {
580             addedCacheHeaders = false;
581         }
582     }
583
584     public int doEndTag() throws JspTagException JavaDoc {
585         unsetWriteEscaper();
586         return super.doEndTag();
587     }
588
589
590     /**
591      * Sets a user. This is used by cloud-tag.
592      */

593
594     void setUser(UserContext newUser) throws JspTagException JavaDoc {
595         if (addedCacheHeaders) {
596             if (newUser != null) {
597                 long exp = expires.getLong(this, DEFAULT_EXPIRE_TIME);
598                 if (exp > 0) {
599                     HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
600                     if (! response.containsHeader("Cache-Control")) {
601                         // This page is using the non-anonymous cloud. Cache control must be private.
602
response.setHeader("Cache-Control", "private");
603                     }
604                 }
605             }
606         }
607     }
608
609     public int doAfterBody() throws JspTagException JavaDoc {
610         if (bodyContent != null) {
611             CharTransformer post = getPostProcessor();
612             if (post != null) {
613                 if (log.isDebugEnabled()) {
614                     log.debug("A postprocessor was defined " + post);
615                     // log.trace("processing " + bodyContent.getString());
616
}
617
618                 post.transform(bodyContent.getReader(), bodyContent.getEnclosingWriter());
619
620             } else {
621                 if (EVAL_BODY == EVAL_BODY_BUFFERED) {
622                     // only needed for lousy app-servers
623
try {
624                         if (bodyContent != null) {
625                             bodyContent.writeOut(bodyContent.getEnclosingWriter());
626                         }
627                     } catch (java.io.IOException JavaDoc ioe){
628                         throw new TaglibException(ioe);
629                     }
630                 }
631             }
632         }
633         return SKIP_BODY;
634     }
635
636
637
638 }
639
640
Popular Tags