You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by pi...@locus.apache.org on 2000/09/19 21:19:23 UTC
cvs commit: jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler ParserController.java ParserXJspSax.java ParserXJspSaxHandler.java XmlOutputter.java PageInfoImpl.java
pierred 00/09/19 12:19:22
Added: jasper/src/share/org/apache/jasper/compiler
ParserController.java ParserXJspSax.java
ParserXJspSaxHandler.java XmlOutputter.java
PageInfoImpl.java
Log:
New classes for the support of XML syntax in jasper
Revision Changes Path
1.1 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParserController.java
Index: ParserController.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.io.*;
import java.util.*;
import javax.servlet.jsp.tagext.*;
import org.xml.sax.InputSource;
import org.apache.jasper.*;
import org.apache.jasper.logging.Logger;
/**
* Controller for the parsing of a JSP page.
* <p>
* A translation unit (JSP source file and any files included via the
* include directive) may involve the processing of JSP pages
* written with different syntaxes (currently the original JSP syntax,
* as well as the XML syntax (as of JSP 1.2)). This class encapsulates
* the behavior related to the selection and invocation of
* the proper parser.
*
* Note: There's some 'commented out' code that would allow
* the dynamic generation of a DTD so we could use a validating
* parser. Should be working, but would like to investigate
* XML schema before using validating parser.
*
* @author Pierre Delisle
*/
public class ParserController {
/*
* The compilation context
*/
private JspCompilationContext ctxt;
/*
* The filename and path of the file being currently parsed.
* This is used to define the path to a file that may
* be included by that 'parent' file.
*/
private String currentFilePath = null;
private String currentFileName = null;
/*
* The parse 'event handler', shared by both
* types of parsers.
*/
private ParseEventListener jspHandler = null;
/*
* Document information which tells us what
* kind of document we are dealing with.
*/
private boolean isXml;
/*
* Static information used in the process of figuring out
* the kind of document we're dealing with.
*/
private static final String XML_PROLOG_TAG = "<?xml";
private static final String JSP_ROOT_TAG = "<jsp:root";
/*
* Information to allow us to dynamically generate the
* DTD to be used to validate the XML document.
* @@@[This has been pulled out for the time being.
* We only support non-validating SAX parser. Might want
* to put it back eventually, or use XML Schema]
*/
/* NOT COMPILED
static final String JSP_TAGLIB_TAG = "jsp:directive.taglib";
boolean hasTaglib; // does xml document have tag lib(s)?
InputSource dtdInputSource;
static String jspDtd_part1 = null;
static String jspDtd_part2 = null;
*/
/*
* Cached value of the class name of the SAX2 driver.
*/
String sax2DriverClassName;
//*********************************************************************
// Constructor
public ParserController(JspCompilationContext ctxt) {
this.ctxt = ctxt; // @@@ can we assert that ctxt is not null?
jspHandler = new JspParseEventListener(ctxt, this);
sax2DriverClassName = ctxt.getOptions().getSax2DriverClassName();
/* @@@ NOT COMPILED
// Cache the content of the jsp DTD
if (jspDtd_part1 == null) {
jspDtd_part1 = getFileContent("/org/apache/jasper/resources/jsp12_part1.dtd");
jspDtd_part2 = getFileContent("/org/apache/jasper/resources/jsp12_part2.dtd");
}
*/
}
//*********************************************************************
// Accessors
public ParseEventListener getParseEventListener() {
return jspHandler;
}
//*********************************************************************
// Parse
public void parse(String inFileName) throws JasperException {
parse(inFileName, null);
}
/**
* Parse the jsp page provided as an argument.
* First invoked by the compiler, then invoked recursively by the
* parser event handler for each 'include' directive.
*
* @param The name of the jsp file to be parsed.
*/
public void parse(String inFileName, String encoding)
throws JasperException
{
//p("parse(" + inFileName + ", " + encoding + ")");
resolveFileName(inFileName);
if (encoding == null) {
encoding = "8859_1"; // default per JSP spec
// XXX - longer term, this should really be:
// System.getProperty("file.encoding", "8859_1");
// but this doesn't work right now, so we stick with ASCII
}
// @@@ need to do a pass at JSP doc to find encoding as specified
// @@@ in page directive (see JspParseEventListener)
File file = new File(currentFileName);
currentFilePath = (ctxt == null)
? file.getAbsolutePath()
: ctxt.getRealPath(file.toString());
//p("currentFilePath: " + currentFilePath);
InputStreamReader reader = null;
try {
// Figure out what type of JSP document we are dealing with
reader = getReader(file, encoding);
figureOutJspDocument(file, encoding, reader);
//p("isXml = " + isXml + " hasTaglib = " + hasTaglib);
// dispatch to the proper parser
try {
reader.close();
} catch (IOException ex) {}
reader = getReader(file, encoding);
if (isXml) {
(new ParserXJspSax(currentFilePath, reader, jspHandler, sax2DriverClassName)).parse();
} else {
(new Parser(ctxt, file, encoding, reader, jspHandler)).parse();
}
} catch (FileNotFoundException ex) {
throw new JasperException(ex);
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception any) {}
}
}
}
//*********************************************************************
// Figure out input Document
private void figureOutJspDocument(File file,
String encoding,
InputStreamReader reader)
throws JasperException
{
JspReader jspReader;
try {
jspReader = new JspReader(ctxt, file, encoding, reader);
} catch (FileNotFoundException ex) {
throw new JasperException(ex);
}
jspReader.setSingleFile(true);
Mark startMark = jspReader.mark();
// check the prolog (ideally it's been included if it is an xml doc)
Mark mark = jspReader.skipUntil(XML_PROLOG_TAG);
if (mark != null) {
isXml = true;
} else {
// must have the jsp:root tag
jspReader.reset(startMark);
mark = jspReader.skipUntil(JSP_ROOT_TAG);
if (mark != null) {
isXml = true;
} else {
isXml = false;
return;
}
}
/* NOT COMPILED
// This is an XML document. Let's see if it uses tag libraries.
jspReader.reset(startMark);
Vector taglibMarks = new Vector();
mark = jspReader.skipUntil(JSP_TAGLIB_TAG);
while (mark != null) {
taglibMarks.add(mark);
mark = jspReader.skipUntil(JSP_TAGLIB_TAG);
}
hasTaglib = (taglibMarks.size() > 0);
if (!hasTaglib) return;
// The JSP document uses tag libraries. We parse the tag libraries and then
// we will generate the JSP DTD on the fly to include the custom tags.
// This way, we can use a validating xml parser.
dtdInputSource = buildDtd(jspReader, taglibMarks);
*/
}
/* NOT COMPILED
private InputSource buildDtd(JspReader jspReader, Vector taglibMarks)
throws JasperException
{
TagLibraries libraries = new TagLibraries(null);
Enumeration enum1 = taglibMarks.elements();
while (enum1.hasMoreElements()) {
Mark mark = (Mark)enum1.nextElement();
jspReader.reset(mark);
jspReader.advance(JSP_TAGLIB_TAG.length());
Hashtable attrs = jspReader.parseTagAttributes();
p("taglib attributes are: " + attrs);
JspUtil.checkAttributes("Taglib directive", attrs,
ParserJsp.Directive.tagDvalidAttrs, mark);
String uri = (String) attrs.get("uri");
String prefix = (String) attrs.get("prefix");
p("uri = " + uri + " prefix = " + prefix);
try {
TagLibraryInfo tli = new TagLibraryInfoImpl(ctxt, prefix, uri);
libraries.addTagLibrary(prefix, tli);
} catch (Exception ex) {
// @@@
ex.printStackTrace();
Object[] args = new Object[] { uri, ex.getMessage() };
throw new CompileException(mark,
Constants.getString("jsp.error.badtaglib",
args));
}
}
// Build a JSP DTD on the fly that will include the custom tag
// ibraries.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StringBuffer part1Buf = new StringBuffer();
StringBuffer bufXmlns = new StringBuffer();
StringBuffer bufTags = new StringBuffer();
part1Buf.append(jspDtd_part1);
Enumeration enum2 = libraries.getTagLibInfos();
while (enum2.hasMoreElements()) {
TagLibraryInfo tli = (TagLibraryInfo)enum2.nextElement();
bufXmlns.append("\nxmlns:").append(tli.getPrefixString()).append(" CDATA #FIXED \"");
bufXmlns.append(tli.getURI()).append("\"");
TagInfo[] tags = tli.getTags();
for (int i=0; i<tags.length; i++) {
TagInfo tag = tags[i];
part1Buf.append("\n|").append(tli.getPrefixString()).append(":").append(tag.getTagName());
part1Buf.append("\n");
bufTags.append("\n<!ELEMENT ");
bufTags.append(tli.getPrefixString());
bufTags.append(":");
bufTags.append(tag.getTagName());
bufTags.append(' ');
if (TagInfo.BODY_CONTENT_EMPTY.equalsIgnoreCase(tag.getBodyContent())) {
bufTags.append("EMPTY>");
} else {
bufTags.append("#PCDATA>");
}
TagAttributeInfo[] tais = tag.getAttributes();
if (tais.length > 0) {
bufTags.append("\n<!ATTLIST ");
bufTags.append(tli.getPrefixString());
bufTags.append(":");
bufTags.append("tag.getTagName()");
bufTags.append(' ');
for (int j=0; j<tais.length; j++) {
TagAttributeInfo tai = tais[j];
bufTags.append('\n'); //@@@ newline
bufTags.append(tai.getName());
if (tai.canBeRequestTime()) {
bufTags.append(" PCDATA ");
} else {
bufTags.append(" CDATA ");
}
if (tai.isRequired()) {
bufTags.append("#REQUIRED");
} else {
bufTags.append("#IMPLIED");
}
}
}
}
}
part1Buf.append(jspDtd_part2);
part1Buf.append(bufXmlns).append(">\n");
part1Buf.append(bufTags);
p("---------ZE DTD:-----------");
p(part1Buf.toString());
p("ZE DTD:----END-------");
CharArrayReader car = new CharArrayReader(part1Buf.toString().toCharArray());
return new InputSource(car);
}
*/
//*********************************************************************
// Utility methods
/*
* Resolve the name of the file and update global
* 'parentFileName' so we can properly include
* other jsp pages that are relative to this one.
*/
private void resolveFileName(String inFileName) {
String baseDir = (currentFileName == null)
? null
: currentFileName.substring(
0, currentFileName.lastIndexOf("/") + 1);
//@@@ if no '/', would fail???
boolean isAbsolute = inFileName.startsWith("/");
if (baseDir == null || isAbsolute) {
currentFileName = inFileName;
} else {
currentFileName = baseDir + inFileName;
}
//p("resolveFileName() currentFileName: " + currentFileName);
}
private InputStreamReader getReader(File file, String encoding)
throws JasperException
{
InputStream in;
InputStreamReader reader;
try {
if (ctxt == null) {
in = new FileInputStream(file);
reader = new InputStreamReader(in, encoding);
} else {
String fileName = ctxt.getRealPath(file.toString());
in = ctxt.getResourceAsStream(file.toString());
if (in == null) {
throw new FileNotFoundException(fileName);
}
reader = new InputStreamReader(in, encoding);
}
return reader;
} catch (FileNotFoundException ex) {
throw new JasperException(ex);
} catch (UnsupportedEncodingException ex) {
throw new JasperException(ex);
}
}
/* NOT COMPILED
private String getFileContent(String fileName) {
InputStream inStream;
StringBuffer sb = new StringBuffer();
inStream = getClass().getResourceAsStream(fileName);
InputStreamReader in = new InputStreamReader(inStream);
char[] buf = new char[1024];
try {
for (int i=0 ; (i=in.read(buf)) != -1 ;) {
sb.append(buf, 0 , i);
}
return sb.toString().trim();
} catch (IOException ex) {
p("IOException on jsp12.dtd");
ex.printStackTrace();
return null;
}
}
*/
private void p(String s) {
System.out.println("[ParserController] " + s);
}
private void p(String s, Throwable ex) {
p(s);
p(ex.getMessage());
ex.printStackTrace();
}
}
1.1 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParserXJspSax.java
Index: ParserXJspSax.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.apache.jasper.JasperException;
import org.apache.jasper.Constants;
import org.apache.jasper.logging.Logger;
/**
* SAX Parser to handle XJsp syntax.
* (JSP page as XML document).
*
* Any SAX2.0 parser should do.
*
* @author Pierre Delisle
*/
public class ParserXJspSax {
/*
* The SAX 'driver' class to be used for parsing.
*/
private String sax2DriverClassName;
/*
* InputSource for XML document
*/
private InputSource is;
/*
* File path that's used in parsing errors
*/
private String filePath;
/*
* The 'parsing event handler' that does the real handling
* of parse events (shared by both jsp and xjsp parsers)
*/
private ParseEventListener jspHandler;
/*
* validation mode
*/
static final private boolean validate = false;
/*
* Couple possible names for lexical reporting property name :-(
*/
static final String[] lexicalHandlerPropNames = {
"http://xml.org/sax/handlers/LexicalHandler",
"http://xml.org/sax/properties/lexical-handler",
};
//*********************************************************************
// Constructor
public ParserXJspSax(String filePath,
InputStreamReader reader,
ParseEventListener jspHandler,
String sax2DriverClassName)
{
this.filePath = filePath;
this.is = new InputSource(reader);
this.jspHandler = jspHandler;
this.sax2DriverClassName = sax2DriverClassName;
}
//*********************************************************************
// Parse
public void parse() throws JasperException {
try {
XMLReader parser =
XMLReaderFactory.createXMLReader(sax2DriverClassName);
ParserXJspSaxHandler handler =
new ParserXJspSaxHandler(filePath, jspHandler);
parser.setContentHandler(handler);
parser.setEntityResolver(handler);
parser.setDTDHandler(handler);
parser.setErrorHandler(handler);
// set properties: lexical handler
for (int i=0; i<lexicalHandlerPropNames.length; i++) {
if (setSaxProperty(parser, handler,
lexicalHandlerPropNames[i])) break;
}
// Set features: validation and namespaces
try {
parser.setFeature(
"http://xml.org/sax/features/validation", validate);
parser.setFeature(
"http://xml.org/sax/features/namespaces", false);
parser.setFeature(
"http://xml.org/sax/features/namespace-prefixes", true);
} catch (SAXNotSupportedException ex) {
throw new JasperException(
Constants.getString("jsp.parser.sax.featurenotsupported",
new Object[] {ex.getMessage()}));
} catch (SAXNotRecognizedException ex) {
throw new JasperException(
Constants.getString("jsp.parser.sax.featurenotrecognized",
new Object[] {ex.getMessage()}));
}
parser.parse(is);
} catch (IOException ex) {
throw new JasperException(ex);
} catch (SAXParseException ex) {
Mark mark =
new Mark(filePath, ex.getLineNumber(), ex.getColumnNumber());
String reason;
if (ex.getException() != null) {
reason = ex.getException().getMessage();
} else {
reason = ex.getMessage();
}
throw new ParseException(mark, reason);
} catch (SAXException ex) {
Exception ex2 = ex;
if (ex.getException() != null) ex2 = ex.getException();
System.out.println("**** ICI ***");
System.out.println(ex2.getMessage());
System.out.println(ex2.getClass().getName());
throw new JasperException(ex2);
}
}
//*********************************************************************
// Utility methods
private boolean setSaxProperty(XMLReader parser,
DefaultHandler handler,
String propName)
{
try {
parser.setProperty(propName, handler);
return true;
} catch (SAXNotSupportedException ex) {
Constants.message("jsp.parser.sax.propertynotsupported",
new Object[] {ex.getMessage()},
Logger.WARNING);
return false;
} catch (SAXNotRecognizedException ex) {
Constants.message("jsp.parser.sax.propertynotrecognized",
new Object[] {ex.getMessage()},
Logger.WARNING);
return false;
}
}
/* NOT COMPILED
private void printException(SAXParseException ex) {
System.out.println("SAXParseException");
System.out.println("Public ID: " + ex.getPublicId());
System.out.println("System ID: " + ex.getSystemId());
System.out.println("line " + ex.getLineNumber() +
", col " + ex.getColumnNumber());
ex.printStackTrace(System.out);
}
void p(String s) {
System.out.println("[ParserXJspSax] " + s);
}
*/
}
1.1 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParserXJspSaxHandler.java
Index: ParserXJspSaxHandler.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
//@@@ have specific imports
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import javax.servlet.jsp.tagext.TagInfo;
import org.xml.sax.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.*;
import org.apache.jasper.*;
/**
* The SAX (2.0) parser event handler.
*
* @author Pierre Delisle
*
* @@@ TODO
* - make sure validation is in sync with Parser (jsp syntax)
* - fix the node.validate()
*/
class ParserXJspSaxHandler
extends DefaultHandler implements LexicalHandler
{
/*
* JSP handler on which we piggyback to generate parse data
*/
private ParseEventListener jspHandler;
/*
* Tells whether we are in a DTD
*/
private boolean inDtd;
/*
* Tells whether we are in CDATA
*/
private boolean inCdata;
/*
* Tells whether we are in Entity
*/
private boolean inEntity;
/*
* parsing stack
*/
private Stack stack;
/*
* Locator for sax parse events
*/
private Locator locator;
/*
* File path that's used in parsing errors
*/
private String filePath;
//*********************************************************************
// Constructor
public ParserXJspSaxHandler(String filePath,
ParseEventListener jspHandler)
throws JasperException
{
this.filePath = filePath;
this.jspHandler = jspHandler;
stack = new Stack();
inEntity = false;
inDtd = false;
inCdata = false;
}
//*********************************************************************
// Interface ContentHandler methods
public void setDocumentLocator(Locator locator) {
//p("\n*** setDocumentLocator");
this.locator = locator;
}
public void startDocument() throws SAXException {
//p("\n*** startDocument");
}
public void endDocument() throws SAXException {
//p("\n*** endDocument");
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
//p("\n*** startPrefixMapping");
//p("prefix = " + prefix);
//p("uri = " + uri);
//p("BEWARE: Nothing done for this content.");
}
public void endPrefixMapping(String prefix)
throws SAXException
{
//p("\n*** endPrefixMapping");
//p("prefix = " + prefix);
//p("BEWARE: Nothing done for this content.");
}
public void characters(char[] ch, int start, int length)
throws SAXException
{
// @@@ have startMark computed from stopMark
Mark stopMark = new Mark(filePath, locator.getLineNumber(),
locator.getColumnNumber());
//p("\n*** characters");
//printLocation();
//p("|" + String.valueOf(ch, start, length) + "|");
Node node = (Node)stack.peek();
if (node.isRoot()) {
// template data in <jsp:root>.
//p("these chars are added directly in jsp:root");
try {
jspHandler.handleCharData(stopMark, stopMark,
makeCharArray(ch, start, length));
} catch (Exception ex) {
throw new SAXException(ex);
}
} else {
// characters added to the body content of the element
// at the top of the stack
//p("these chars are added to node " + node.rawName + " in stack");
node.addText(ch, start, length);
}
}
public void ignorableWhitespace(char[] ch,
int start,
int length)
throws SAXException
{
//p("\n*** ignorableWhitespace");
//printLocation();
//p("|" + String.valueOf(ch, start, length) + "|");
//p("BEWARE: Nothing done for this content.");
}
public void skippedEntity(String name)
throws SAXException
{
//p("\n*** skippedEntity");
//p("name = " + name);
//p("BEWARE: Nothing done for this content.");
}
public void processingInstruction(String target, String data)
throws SAXException
{
//p("\n*** processingInstruction");
//p("target = " + target);
//p("data = " + data);
//p("BEWARE: Nothing done for this content.");
}
public void startElement(String namespaceURI, String localName,
String rawName, Attributes attrs)
throws SAXException
{
//p("\n*** startElement: " + rawName);
//printLocation();
//p("namespaceURI: " + namespaceURI);
//p("localName: " + localName);
//p("rawName: " + rawName);
//p("attrs: " + attrs.toString());
String name = rawName;
Mark start = new Mark(filePath, locator.getLineNumber(),
locator.getColumnNumber());
Node node = new Node(rawName, new AttributesImpl(attrs), start);
if (name.equals("jsp:params")) {
// don't have it pushed on the stack...
// this is a noop...
return;
}
// Simply push the new 'node' on the stack, and it will be
// processed on the 'endElement' event.
stack.push(node);
// Those elements allow more 'parsed elements' in them.
// They are therefore handled both at the start and at the
// end.
try {
if (name.equals("jsp:root")) {
jspHandler.handleRootBegin(attrsToHashtable(node.attrs));
} else if (name.equals("jsp:useBean")) {
jspHandler.handleBean(
node.start, node.start, attrsToHashtable(node.attrs));
} else if (name.length()<4 || !name.substring(0,4).equals("jsp:")) {
// custom tag
processCustomTagBegin();
}
} catch (Exception ex) {
throw new SAXException(ex);
}
}
public void endElement(String namespaceURI, String localName,
String rawName)
throws SAXException
{
//p("\n*** endElement: " + rawName);
//printLocation();
//p("namespaceURI: " + namespaceURI);
//p("localName: " + localName);
//p("rawName: " + rawName);
//p("attrs: " + attrs.toString());
Mark stop = new Mark(filePath, locator.getLineNumber(),
locator.getColumnNumber());
String name = rawName;
Node node = (Node)stack.pop();
//p(node);
try {
if (name.equals("jsp:root")) {
jspHandler.handleRootEnd();
} else if (name.equals("jsp:directive.include")) {
node.validate(true, false);
jspHandler.handleDirective(
"include", node.start, stop,
attrsToHashtable(node.attrs));
} else if (name.equals("jsp:directive.page")) {
node.validate(true, false);
jspHandler.handleDirective(
"page", node.start, stop,
attrsToHashtable(node.attrs));
} else if (name.equals("jsp:directive.taglib")) {
node.validate(true, false);
jspHandler.handleDirective(
"taglib", node.start, stop,
attrsToHashtable(node.attrs));
} else if (name.equals("jsp:declaration")) {
node.validate(false, true);
jspHandler.handleDeclaration(
node.start, stop, null, node.getText());
} else if (name.equals("jsp:expression")) {
node.validate(false, true);
jspHandler.handleExpression(
node.start, stop, null, node.getText());
} else if (name.equals("jsp:scriptlet")) {
node.validate(false, true);
jspHandler.handleScriptlet(
node.start, stop, null, node.getText());
} else if (name.equals("jsp:param")) {
node.validate(true, false);
// push the node back, it will be needed by the container node
stack.push(node);
} else if (name.equals("jsp:fallback")) {
node.validate(false, true);
// push the node back, it will be needed by the container node
stack.push(node);
} else if (name.equals("jsp:include")) {
Hashtable params = null;
if (!node.rawName.equals("jsp:include")) {
// handle params
stack.push(node);
params = popParams();
node = (Node)stack.pop();
}
node.validate(true, true); //@@@
jspHandler.handleInclude(
node.start, stop, attrsToHashtable(node.attrs), params);
} else if (name.equals("jsp:forward")) {
Hashtable params = null;
if (!node.rawName.equals("jsp:forward")) {
// handle params
stack.push(node);
params = popParams();
node = (Node)stack.pop();
}
node.validate(true, true);
jspHandler.handleForward(
node.start, stop, attrsToHashtable(node.attrs), params);
} else if (name.equals("jsp:useBean")) {
node.validate(true, true); // @@@
jspHandler.handleBeanEnd(
node.start, stop, attrsToHashtable(node.attrs));
} else if (name.equals("jsp:getProperty")) {
node.validate(true, true); // @@@
jspHandler.handleGetProperty(
node.start, stop, attrsToHashtable(node.attrs));
} else if (name.equals("jsp:setProperty")) {
node.validate(true, true); // @@@
jspHandler.handleSetProperty(
node.start, stop, attrsToHashtable(node.attrs));
} else if (name.equals("jsp:plugin")) {
//@@@ test jsp parser to see if fallback can come first?
Hashtable params = null;
String fallback = null;
if (node.rawName.equals("jsp:fallback")) {
// handle fallback
fallback = String.valueOf(node.getText());
node = (Node)stack.pop();
}
if (!node.rawName.equals("jsp:plugin")) {
// handle params
stack.push(node);
params = popParams();
node = (Node)stack.pop();
}
node.validate(true, true);
//p(node);
jspHandler.handlePlugin(
node.start, stop, attrsToHashtable(node.attrs), params, fallback);
} else {
// Ought to be a custom tag
//p("should be nodetag");
//p(node);
//p("class is: " + node.getClass().getName());
processCustomTagEnd((NodeTag)node, stop);
}
} catch (Exception ex) {
ex.printStackTrace();
throw new SAXException(ex);
}
}
private void processCustomTagBegin()
throws ParseException, JasperException
{
Node node = (Node)stack.pop();
String tag = node.rawName;
int i = tag.indexOf(':');
if (i == -1) throw new ParseException("unknown tag: " + tag);
String prefix = tag.substring(0, i);
String shortTagName = tag.substring(i+1);
TagLibraries libraries = jspHandler.getTagLibraries();
if (!libraries.isUserDefinedTag(prefix, shortTagName)) {
throw new ParseException(node.start, "invalid tag: " + node.rawName);
}
if (shortTagName == null) {
throw new ParseException(node.start, "Nothing after the :");
}
TagLibraryInfo tli = libraries.getTagLibInfo(prefix);
TagInfo ti = tli.getTag(shortTagName);
if (ti == null) {
throw new ParseException(node.start, "Unable to locate TagInfo for "+tag);
}
node = new NodeTag(node, prefix, shortTagName, tli, ti);
stack.push(node);
jspHandler.handleTagBegin(node.start, node.start,
attrsToHashtable(node.attrs),
prefix, shortTagName, tli, ti);
}
private void processCustomTagEnd(NodeTag node, Mark stop)
throws ParseException, JasperException {
String bc = node.ti.getBodyContent();
if (node.getText() != null && bc.equalsIgnoreCase(TagInfo.BODY_CONTENT_EMPTY)) {
throw new ParseException(node.start, "Body is supposed to be empty for "
+ node.rawName);
}
jspHandler.handleTagEnd(node.start, stop, node.prefix,
node.shortTagName, attrsToHashtable(node.attrs),
node.tli, node.ti);
}
//*********************************************************************
// Interface LexicalHandler methods
public void startDTD(String name, String publicId, String systemId)
throws SAXException
{
//p("\n*** startDTD");
//p("BEWARE: Nothing done for this content.");
}
public void endDTD() throws SAXException {
inDtd = false;
//p("\n*** endDTD");
//p("BEWARE: Nothing done for this content.");
}
public void startEntity(String name)
throws SAXException
{
//p("\n*** startEntity");
//p("name: " + name);
//p("BEWARE: Nothing done for this content.");
}
public void endEntity(String name)
throws SAXException
{
//p("\n*** endEntity");
//p("name: " + name);
//p("BEWARE: Nothing done for this content.");
}
public void startCDATA() throws SAXException {
//p("\n*** startCDATA");
inCdata = true;
}
public void endCDATA() throws SAXException {
//p("\n*** endCDATA");
inCdata = false;
}
public void comment(char[] ch, int start, int length)
throws SAXException
{
//p("\n*** comment");
//printLocation();
//p("|" + String.valueOf(ch, start, length) + "|");
//p("BEWARE: Nothing done for this content.");
/*
String commentText = new String(ch, start, end);
if ((!inDtd) && (!commentText.equals(""))) {
if (stack.empty()) {
document.addComment(
new Comment(commentText));
} else {
((Element)stack.peek()).addChild(
new Comment(commentText));
}
}
*/
}
//*********************************************************************
// Interface ErrorHandler methods
public void fatalError(SAXParseException ex)
throws SAXException
{
printException("FATAL", ex);
throw ex;
}
public void error(SAXParseException ex)
throws SAXException
{
printException("ERROR", ex);
throw ex;
}
public void warning(SAXParseException ex)
throws SAXException
{
printException("WARNING", ex);
}
//*********************************************************************
// DTD Handler
public void notationDecl(java.lang.String name,
java.lang.String publicId,
java.lang.String systemId)
throws SAXException
{
//p("\n*** notationDecl");
//p("name = " + name);
//p("publicId = " + publicId);
//p("systemId = " + systemId);
//p("BEWARE: Nothing done for this content.");
}
public void unparsedEntityDecl(java.lang.String name,
java.lang.String publicId,
java.lang.String systemId,
java.lang.String notationName)
throws SAXException
{
//p("\n*** unparsedEntityDecl");
//p("name = " + name);
//p("publicId = " + publicId);
//p("systemId = " + systemId);
//p("notationName = " + notationName);
//p("BEWARE: Nothing done for this content.");
}
//*********************************************************************
// EntityResolver
static final String JSP_PUBLIC_ID1 =
"-//Sun Microsystems Inc.//DTD JavaServer Pages Version 1.1//EN";
static final String JSP_PUBLIC_ID2 =
"-//Sun Microsystems Inc.//DTD JavaServer Pages Version 1.2//EN";
static final String JSP_SYSTEM_ID =
"http://java.sun.com/products/jsp/dtd/jspcore_1_2.dtd";
static final String JSP_SYSTEM_ID_INTERNAL =
"/org/apache/jasper/resources/jsp12.dtd";
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException
{
//p("\n*** resolveEntity");
//p("publicId: " + publicId);
//p("systemId: " + systemId);
if (publicId.equals(JSP_PUBLIC_ID1) ||
publicId.equals(JSP_PUBLIC_ID2)) {
InputStream is =
this.getClass().getResourceAsStream(JSP_SYSTEM_ID_INTERNAL);
//p("attempt to returning " + JSP_SYSTEM_ID_INTERNAL);
InputSource isrc = new InputSource(is);
//p("success on returning " + JSP_SYSTEM_ID_INTERNAL);
return isrc;
} else {
System.out.println("ERROR: publicID does not match: " + publicId);
return null;
}
}
//*********************************************************************
// class Node
private class Node {
String rawName;
Attributes attrs;
Mark start;
boolean isRoot;
StringBuffer text = null;
Node(Node node) {
this(node.rawName, node.attrs, node.start);
}
Node(String rawName, Attributes attrs, Mark start) {
this.rawName = rawName;
this.attrs = attrs;
this.start = start;
isRoot = rawName.equals("jsp:root");
}
void addText(char[] chars, int start, int length) {
if (text == null) text = new StringBuffer();
text.append(chars, start, length);
}
char[] getText() {
return text == null
? null
: text.toString().toCharArray();
}
boolean isRoot() {
return isRoot;
}
void validate(boolean canHaveAttributes,
boolean canHaveText)
throws SAXException
{
if (!canHaveAttributes && attrs.getLength()!=0) {
throw new SAXException("VALIDATE ERROR: " +
rawName + " cannot have attributes.");
}
if (!canHaveText && text != null) {
throw new SAXException("VALIDATE ERROR: " +
rawName + " cannot have text.");
}
}
public void display() {
p("NODE: " + rawName);
for (int i=0; i<attrs.getLength(); i++) {
p("attrs[" + i + "] " + attrs.getQName(i) + " = " +
attrs.getValue(i));
}
}
}
//*********************************************************************
// class NodeTag
private class NodeTag extends Node {
String prefix;
String shortTagName;
TagLibraryInfo tli;
TagInfo ti;
NodeTag(Node node, String prefix, String shortTagName,
TagLibraryInfo tli, TagInfo ti)
{
super(node);
this.prefix = prefix;
this.shortTagName = shortTagName;
this.tli = tli;
this.ti = ti;
}
}
//*********************************************************************
// Utility methods
/**
* <p>
* Trim the right spacing off of a <code>String</code>.
* </p>
*
* @param orig <code>String</code> to rtrim.
* @return <code>String</code> - orig with no right spaces
*/
private String rtrim(String orig) {
int len = orig.length();
int st = 0;
int off = 0;
char[] val = orig.toCharArray();
while ((st < len) && (val[off + len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < orig.length()))
? orig.substring(st, len) : orig;
}
/**
* <p>
* Trim the left spacing off of a <code>String</code>.
* </p>
*
* @param orig <code>String</code> to rtrim.
* @return <code>String</code> - orig with no left spaces
*/
private String ltrim(String orig) {
int len = orig.length();
int st = 0;
int off = 0;
char[] val = orig.toCharArray();
while ((st < len) && (val[off + st] <= ' ')) {
st++;
}
return ((st > 0) || (len < orig.length()))
? orig.substring(st, len) : orig;
}
private void printException(String level, SAXParseException ex) {
p("\n*** SAXParseException: " + level);
p("Public ID: " + ex.getPublicId());
p("System ID: " + ex.getSystemId());
p("line " + ex.getLineNumber() +
", col " + ex.getColumnNumber());
ex.printStackTrace(System.out);
}
private Hashtable attrsToHashtable(Attributes attrs) {
int len = attrs.getLength();
Hashtable table = new Hashtable(len);
for (int i=0; i<len; i++) {
table.put(attrs.getQName(i), attrs.getValue(i));
}
return table;
}
private char[] makeCharArray(char[] buf, int offset, int len) {
char[] ret = new char[len];
for (int i=0,j=offset; i<len; i++,j++) {
ret[i] = buf[j];
}
return ret;
}
private Hashtable popParams() throws ParseException {
// @@@ code duplicated with JspParseEventListener
Hashtable params = new Hashtable();
Node node;
while ((node = (Node)stack.peek()).rawName.equals("jsp:param")) {
node = (Node)stack.pop();
//p("popped this param node");
//p(node);
String name = node.attrs.getValue("name");
String value = node.attrs.getValue("value");
if (name == null) {
throw new ParseException(node.start, Constants.getString("jsp.error.param.noname"));
}
if (value == null) {
throw new ParseException(node.start, Constants.getString("jsp.error.param.novalue"));
}
// Put that new binding into the params hashtable:
String oldval[] = (String[])params.get(name);
if (oldval == null) {
String newval[] = new String[1];
newval[0] = value;
params.put(name, newval);
} else {
String newval[] = new String[oldval.length+1];
System.arraycopy(oldval, 0, newval, 0, oldval.length);
newval[oldval.length] = value;
params.put(name, newval);
}
}
return params;
}
private void printLocation() {
p("--- (" + locator.getSystemId() + ", " +
locator.getPublicId() + ") (" +
locator.getLineNumber() + ", " +
locator.getColumnNumber() + ")");
}
void p(String s) {
//System.out.println("[ParserXJspSaxHandler] " + s);
System.out.println(s);
}
void p(Node node) {
node.display();
}
}
1.1 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/XmlOutputter.java
Index: XmlOutputter.java
===================================================================
/*
* $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/XmlOutputter.java,v 1.1 2000/09/19 19:19:21 pierred Exp $
* $Revision: 1.1 $
* $Date: 2000/09/19 19:19:21 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import javax.servlet.jsp.tagext.PageInfo;
/**
* Class responsible for generating the XML stream representing
* the JSP translation unit being compiled.
*
* @author Pierre Delisle
*/
public class XmlOutputter {
/*
* XML data is appended to the stream as we parse and process
* the JSP translation unit
*/
private StringBuffer sb;
/*
* The root attributes of all the <jsp:root> tags encountered
* in the translation unit
*/
private Hashtable rootAttrs;
//*********************************************************************
// Constructor
XmlOutputter() {
sb = new StringBuffer();
rootAttrs = new Hashtable();
}
//*********************************************************************
// update methods to the XML stream
/**
* A translation unit (JSP source file and any files included via
* the include directive) may encounter multiple <jsp:root>
* tags. This method cumulates all attributes for the
* <jsp:root> tag.
*/
void addRootAttrs(Hashtable attrs) {
Enumeration enum = attrs.keys();
while (enum.hasMoreElements()) {
Object name = enum.nextElement();
Object value = attrs.get(name);
rootAttrs.put(name, value);
}
}
/**
* Append the cdata to the XML stream.
*/
void append(char[] text) {
sb.append("<![CDATA[\n");
sb.append(text);
sb.append("]]>\n");
}
/**
* Append the start tag along with its attributes to the
* XML stream.
*/
void append(String tag, Hashtable attrs) {
append(tag, attrs, sb);
}
/**
* Append the start tag along with its attributes to the
* specific XML stream.
* [StringBuffer is an argument so we can reuse the method
* to generate the "header" in a different stream. The header
* can only be generated once we've processed all parts
* of the translation unit]
*/
void append(String tag, Hashtable attrs, StringBuffer buff) {
buff.append("<").append(tag);
if (attrs == null) {
buff.append(">");
} else {
buff.append("\n");
Enumeration enum = attrs.keys();
while (enum.hasMoreElements()) {
String name = (String)enum.nextElement();
String value = (String)attrs.get(name);
buff.append(" ").append(name).append("=\"");
buff.append(value).append("\"\n");
}
buff.append(">\n");
}
}
/**
* Append the start tag along with its attributes and body
* to the XML stream.
*/
void append(String tag, Hashtable attrs, char[] text) {
append(tag, attrs);
append(text);
sb.append("</").append(tag).append(">\n");
}
/**
* Append the end tag to the xml stream.
*/
void append(String tag) {
sb.append("</").append(tag).append(">");
}
//*********************************************************************
// Outputting the XML stream
private static final String PROLOG =
"<!DOCTYPE jsp:root\n PUBLIC \"-//Sun Microsystems Inc.//DTD JavaServer Pages Version 1.1//EN\"\n \"http://java.sun.com/products/jsp/dtd/jspcore_1_2.dtd\">\n";
PageInfo getPageInfo() {
StringBuffer buff = new StringBuffer();
buff.append(PROLOG);
append("jsp:root", rootAttrs, buff);
buff.append(sb.toString());
InputStream is =
new ByteArrayInputStream(buff.toString().getBytes());
PageInfo pageInfo = new PageInfoImpl(is);
return pageInfo;
}
}
1.1 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/PageInfoImpl.java
Index: PageInfoImpl.java
===================================================================
/*
* $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/PageInfoImpl.java,v 1.1 2000/09/19 19:19:21 pierred Exp $
* $Revision: 1.1 $
* $Date: 2000/09/19 19:19:21 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.io.InputStream;
import javax.servlet.jsp.tagext.PageInfo;
/**
* Implementation of abstract class javax.servlet.jsp.tagext.PageInfo.
*
* @author Pierre Delisle
*/
public class PageInfoImpl extends PageInfo {
/**
* The XML input stream representing the JSP translation unit.
*/
private InputStream is;
//*********************************************************************
// Constructor
public PageInfoImpl(InputStream is) {
this.is = is;
}
//*********************************************************************
// PageInfo methods
public InputStream getInputStream() {
return is;
}
}