BodyContent Class |
Class name:
javax.servlet.jsp.tagext.BodyContent
Extends:
javax.servlet.jsp.JspWriter
Implements:
None
Implemented by:
Internal container-dependent class
Description
The container creates an instance of the BodyContent class to hold the result of evaluating the element's body content if the corresponding tag handler implements the BodyTag interface. The container makes the BodyContent instance available to the tag handler by calling the setBodyContent() method, so the tag handler can process the body content.

Let's look at a tag handler class that extends the BodyTagSupport class. The EncodeHTMLTag class is the tag handler class for a custom action called <ora:encodeHTML>. This action reads its body; replaces all characters with a special meaning in HTML, such as single quotes, double quotes, less-than symbols, greater-than symbols, and ampersands, with their corresponding HTML character entities (i.e., &#39;, &#34;, &lt;, &gt;, and &amp;); and inserts the result in the response body. The following example shows how the action can be used in a JSP page:

    <%@ page language="java" %>
    <%@ taglib uri="/orataglib" prefix="ora" %>
    <html>
      <head>
        <title>Encoded HTML Example</title>
      </head>
      <body>
        <h1>Encoded HTML Example</h1>
        The following text is encoded by the
        &lt;ora:encodeHTML&gt; custom action:
        <pre>
          <ora:encodeHTML>
            HTML 3.2 Documents start with a <!DOCTYPE>
            declaration followed by an HTML element containing
            a HEAD and then a BODY element:

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
            <HTML>
            <HEAD>
            <TITLE>A study of population dynamics</TITLE>
            ... other head elements
            </HEAD>
            <BODY>
            ... document body
            </BODY>
            </HTML>
          </ora:encodeHTML>
        </pre>
      </body>
    </html>

Note that the body of the <ora:encodeHTML> action in the JSP page example contains HTML elements. If the special characters aren't converted to HTML character entities, the browser interprets the HTML and shows the result of that interpretation instead of the elements themselves. Thanks to the conversion performed by the custom action, however, the page is processed correctly.

Besides static text, the action body can contain any JSP element. A more realistic example of the use of this action is to insert text from a database into a JSP page, without having to worry about how special characters in the text are interpreted by the browser. The tag handler class is very trivial, as shown here:

    package com.ora.jsp.tags.generic;

    import java.io.*;
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import com.ora.jsp.util.*;

    public class EncodeHTMLTag extends BodyTagSupport {

        public int doAfterBody() throws JspException {
            BodyContent bc = getBodyContent();
            JspWriter out = getPreviousOut();
            try {
                out.write(toHTMLString(bc.getString()));
            }
            catch (IOException e) {} // Ignore
            return SKIP_BODY;
        }

        private String toHTMLString(String in) {
            StringBuffer out = new StringBuffer();
            for (int i = 0; in != null & i < in.length();
              i++) {
                char c = in.charAt(i);
                if (c == '\'') {
                    out.append("&#39;");
                }
                else if (c == '\"') {
                    out.append("&#34;");
                }
                else if (c == '<') {
                    out.append("&lt;");
                }
                else if (c == '>') {
                    out.append("&gt;");
                }
                else if (c == '&') {
                    out.append("&amp;");
                }
                else {
                    out.append(c);
                }
            }
            return out.toString();
        }
    }

The action doesn't have any attributes, so the tag handler doesn't need any instance variables and property access methods. The tag handler can reuse all the BodyTag methods implemented by the BodyTagSupport class except the doAfterBody() method.

Two utility methods provided by the BodyTagSupport class are used in the doAfterBody() method. The getBodyContent() method returns a reference to the BodyContent object that contains the result of processing the action's body. The getPreviousOut() method returns the BodyContent of the enclosing action, if any, or the main JspWriter for the page if the action is at the top level.

You may wonder why the method is called getPreviousOut() and not getOut(). The name is intended to emphasize the fact that you want to use the object assigned as the output to the enclosing element in a hierarchy of nested action elements. Say you have the following action elements in a page:

      <xmp:foo>
        <xmp:bar>
          Some template text
        </xmp:bar>
    </xmp:foo>

The web container first creates a JspWriter and assigns it to the out variable for the page. When it encounters the <xmp:foo> action, it creates a BodyContent object and temporarily assigns it to the out variable. It then creates another BodyContent for the <xmp:bar> action and, again, assigns it to out. The web container keeps track of this hierarchy of output objects. Template text and output produced by the standard JSP elements end up in the current output object. Each element can access its own BodyContent object by calling the getBodyContent() method, then read the content. For the <xmp:bar> element, the content is the template text. After processing the content, it can write it to the <xmp:foo> body by getting the BodyContent for this element through the getPreviousOut() method. Finally, the <xmp:foo> element can process the content provided by the <xmp:bar> element and add it to the top-level output object: the JspWriter object it gets by calling the getPreviousOut() method.

The tag handler in this example converts all special characters it finds in its BodyContent object with the toHTMLString() method. Using the getString() method, it gets the content of the BodyContent object and uses it as the argument to the toHTMLString() method. The result is written to the JspWriter obtained by calling getPreviousOut().

The doAfterBody() method in this example returns SKIP_BODY, telling the container to continue by calling doEndTag(). For a tag handler that implements an iterating custom action, doAfterBody() can instead return EVAL_BODY_TAG. The container then evaluates the element's body again, writing the result to the BodyContent for the element, and calls doAfterBody(). The process is repeated until doAfterBody() returns SKIP_BODY.

clearBody() |
public void clearBody()
Removes all buffered content for this instance.

flush() |
public void flush() throws java.io.IOException
Overwrites the behavior inherited from JspWriter to always throw an IOException, since it's invalid to flush a BodyContent instance.

getEnclosingWriter() |
public JspWriter getEnclosingWriter()
Returns the enclosing JspWriter; in other words, either the top-level JspWriter or the JspWriter (BodyContent subclass) of the parent tag handler.

getReader() |
public abstract java.io.Reader getReader()
Returns the value of this BodyContent object as a Reader with the content produced by evaluating the element's body.

getString() |
public abstract String getString()
Returns the value of this BodyContent object as a String with the content produced by evaluating the element's body.

writeOut() |
public abstract void writeOut(java.io.Writer out) throws java.io.IOException
Writes the content of this BodyContent object into a Writer.

BodyContent() |
protected BodyContent(JspWriter e)
Creates a new instance with the specified JspWriter as the enclosing writer.