costin 01/05/04 13:03:35 Added: proposals/jasper34/generator/org/apache/jasper34/generator11 CompileException.java Constants.java Generator.java GeneratorBase.java JspParseEventListener.java ServletWriter.java TagLibraryInfoImpl.java Log: Common classes for the code generator. Missing: Compiler ( need a bit more work on extracting the generator and abstracting the mangler and javac ). This is just the first step ( separating by functionality ), interfaces will change for sure. Revision Changes Path 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/CompileException.java Index: CompileException.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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import org.apache.jasper34.core.*; import org.apache.jasper34.parser11.*; /** * Class for parser exceptions. * * @author Petr Jiricka */ public class CompileException extends JasperException { public CompileException(Mark m, String reason) { super(m + " " + reason); } public CompileException(String reason) { super(reason); } } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/Constants.java Index: Constants.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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import java.util.ResourceBundle; import java.util.MissingResourceException; import java.text.MessageFormat; // import org.apache.tomcat.util.log.Log; // import org.apache.tomcat.util.res.StringManager; /** * Some constants and other global data that are used by the compiler * and the runtime. * * @author Anil K. Vijendran * @author Harish Prabandham */ public class Constants { public static final String TAGMANAGER_CONTEXT_ATTRIBUTE_NAME = "org.apache.jasper.runtime.TagPoolManager"; public static String JSP_RUNTIME_PACKAGE = "org.apache.jasper34.runtime11"; /** * The base class of the generated servlets. */ public static String JSP_SERVLET_BASE = JSP_RUNTIME_PACKAGE+ ".HttpJspBase"; /** * _jspService is the name of the method that is called by * HttpJspBase.service(). This is where most of the code generated * from JSPs go. */ public static final String SERVICE_METHOD_NAME = "_jspService"; /** * Default servlet content type. */ public static final String SERVLET_CONTENT_TYPE = "text/html"; /** * These classes/packages are automatically imported by the * generated code. * * FIXME: Need to trim this to what is there in PR2 and verify * with all our generators -akv. */ public static final String[] STANDARD_IMPORTS = { "javax.servlet.*", "javax.servlet.http.*", "javax.servlet.jsp.*", // This one is not in spec, but a lot of tests depend on it. // The code is fixed to use explicit deps, when we test // the watchdog tests we can remove this "javax.servlet.jsp.tagext.*" }; // "javax.servlet.jsp.tagext.*", // "java.io.PrintWriter", "java.io.IOException", "java.io.FileInputStream", // "java.io.ObjectInputStream", "java.util.Vector", // "org.apache.jasper.runtime.*", "java.beans.*", // "org.apache.jasper.JasperException" // }; /** * ServletContext attribute for classpath. This is tomcat specific. * Other servlet engines can choose to have this attribute if they * want to have this JSP engine running on them. */ public static final String SERVLET_CLASSPATH = "org.apache.tomcat.jsp_classpath"; /** * ServletContext attribute for classpath. This is tomcat specific. * Other servlet engines can choose to have this attribute if they * want to have this JSP engine running on them. */ public static final String SERVLET_CLASS_LOADER = "org.apache.tomcat.classloader"; /** * Default size of the JSP buffer. */ public static final int K = 1024; public static final int DEFAULT_BUFFER_SIZE = 8*K; /** * The query parameter that causes the JSP engine to just * pregenerated the servlet but not invoke it. */ public static final String PRECOMPILE = "jsp_precompile"; /** * Servlet context and request attributes that the JSP engine * uses. */ public static final String INC_REQUEST_URI = "javax.servlet.include.request_uri"; public static final String INC_SERVLET_PATH = "javax.servlet.include.servlet_path"; public static final String TMP_DIR = "javax.servlet.context.tempdir"; /** * ProtectionDomain to use for JspLoader defineClass() for current * Context when using a SecurityManager. */ public static final String ATTRIB_JSP_ProtectionDomain = "tomcat.context.jsp.protection_domain"; /** * A token which is embedded in file names of the generated * servlet. */ public static final String JSP_TOKEN = "_jsp_"; /** * ID and location of the DTD for tag library descriptors. */ public static final String TAGLIB_DTD_PUBLIC_ID = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"; public static final String TAGLIB_DTD_RESOURCE = "/org/apache/jasper/resources/web-jsptaglib_1_1.dtd"; /** * ID and location of the DTD for web-app deployment descriptors. */ public static final String WEBAPP_DTD_PUBLIC_ID = "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"; public static final String WEBAPP_DTD_RESOURCE = "/org/apache/jasper/resources/web.dtd"; /** * Default URLs to download the pluging for Netscape and IE. */ public static final String NS_PLUGIN_URL = "http://java.sun.com/products/plugin/"; public static final String IE_PLUGIN_URL = "http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0"; } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/Generator.java Index: Generator.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/Generator.java,v 1.1 2001/05/04 20:03:34 costin Exp $ * $Revision: 1.1 $ * $Date: 2001/05/04 20:03:34 $ * * ==================================================================== * * 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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import org.apache.jasper34.core.*; /** * Interface that all generators implement. * * @author Anil K. Vijendran */ public interface Generator { void generate (ServletWriter out, Class phase) throws JasperException; boolean generateCoordinates(Class phase); void init(JspCompilationContext ctxt) throws JasperException; } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/GeneratorBase.java Index: GeneratorBase.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/GeneratorBase.java,v 1.1 2001/05/04 20:03:34 costin Exp $ * $Revision: 1.1 $ * $Date: 2001/05/04 20:03:34 $ * * ==================================================================== * * 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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import org.apache.jasper34.core.*; /** * Helpful abstract base class that generators can extend. * * @author Anil K. Vijendran */ public abstract class GeneratorBase implements Generator { protected JspCompilationContext ctxt; public void init(JspCompilationContext ctxt) throws JasperException { this.ctxt = ctxt; } public boolean generateCoordinates(Class phase) { return true; } } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/JspParseEventListener.java Index: JspParseEventListener.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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import java.util.Hashtable; import java.util.Stack; import java.util.Vector; import java.util.Enumeration; import java.util.StringTokenizer; import java.io.IOException; import java.io.FileNotFoundException; import java.io.File; import java.io.ObjectOutputStream; import java.io.FileOutputStream; import java.net.URL; import java.net.MalformedURLException; import javax.servlet.jsp.tagext.TagInfo; import javax.servlet.jsp.tagext.TagLibraryInfo; import org.apache.jasper34.core.*; import org.apache.jasper34.parser11.*; import org.apache.jasper34.generator11.generators.*; import org.apache.jasper34.generator11.util.*; import org.apache.jasper34.generator11.phase.*; //import org.apache.tomcat.util.log.*; /** * JSP code generator "backend". * * @author Anil K. Vijendran */ public class JspParseEventListener implements ParseEventListener { //extends BaseJspListener { private static CommentGenerator commentGenerator = new JakartaCommentGenerator(); JspCompilationContext ctxt; String jspServletBase = Constants.JSP_SERVLET_BASE; String serviceMethodName = Constants.SERVICE_METHOD_NAME; String servletContentType = Constants.SERVLET_CONTENT_TYPE; String extendsClass = ""; Vector interfaces = new Vector(); Vector imports = new Vector(); String error = ""; boolean genSessionVariable = true; boolean singleThreaded = false; boolean autoFlush = true; Vector generators = new Vector(); BeanRepository beanInfo; int bufferSize = Constants.DEFAULT_BUFFER_SIZE; // a set of boolean variables to check if there are multiple attr-val // pairs for jsp directive. boolean languageDir = false, extendsDir = false, sessionDir = false; boolean bufferDir = false, threadsafeDir = false, errorpageDir = false; boolean iserrorpageDir = false, infoDir = false, autoFlushDir = false; boolean contentTypeDir = false; /* support for large files */ int stringId = 0; Vector vector = new Vector(); String dataFile; TagLibraries libraries; // Variables shared by all TagBeginGenerator and TagEndGenerator instances // to keep track of nested tags and variable names private Stack tagHandlerStack; private Hashtable tagVarNumbers; // This variable keeps track of tag pools. We only need // one tag pool per tag reuse scope. private Vector tagPools = new Vector(); protected JspReader reader; protected ServletWriter writer; final void addGenerator(Generator gen) throws JasperException { gen.init(ctxt); generators.addElement(gen); } public static void setCommentGenerator(CommentGenerator generator) { if ( null == commentGenerator) { throw new IllegalArgumentException("null == generator"); } commentGenerator = generator; } /* * Package private since I want everyone to come in through * org.apache.jasper.compiler.Main. */ public JspParseEventListener(JspCompilationContext ctxt, JspReader reader, ServletWriter writer) { // this.reader = ctxt.getReader(); // this.writer = ctxt.getWriter(); this.reader=reader; this.writer=writer; this.ctxt = ctxt; this.beanInfo = new BeanRepository(ctxt.getClassLoader()); this.libraries = new TagLibraries(ctxt, ctxt.getClassLoader()); // FIXME: Is this good enough? (I'm just taking the easy way out - akv) if (ctxt.getOptions().getLargeFile()) dataFile = ctxt.getOutputDir() + File.separatorChar + ctxt.getServletPackageName() + "_" + ctxt.getServletClassName() + ".dat"; } public JspCompilationContext getCompilationContext() { return ctxt; } public void setTemplateInfo(Mark start, Mark stop) { } public void beginPageProcessing() throws JasperException { for(int i = 0; i < Constants.STANDARD_IMPORTS.length; i++) imports.addElement(Constants.STANDARD_IMPORTS[i]); } public void endPageProcessing() throws JasperException { generateHeader(); writer.println(); generateAll(ServiceMethodPhase.class); writer.println(); generateFooter(); if (ctxt.getOptions().getLargeFile()) try { ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(dataFile)); /* * Serialize an array of char[]'s instead of an * array of String's because there is a limitation * on the size of Strings that can be serialized. */ char[][] tempCharArray = new char[vector.size()][]; vector.copyInto(tempCharArray); o.writeObject(tempCharArray); o.close(); writer.close(); } catch (IOException ex) { throw new JasperException(ctxt.getString( "jsp.error.data.file.write"), ex); } ctxt.setContentType(servletContentType); } private Stack getTagHandlerStack() { if (tagHandlerStack == null) { tagHandlerStack = new Stack(); } return tagHandlerStack; } private Hashtable getTagVarNumbers() { if (tagVarNumbers == null) { tagVarNumbers = new Hashtable(); } return tagVarNumbers; } private void generateAll(Class phase) throws JasperException { for(int i = 0; i < generators.size(); i++) { Generator gen = (Generator) generators.elementAt(i); if (phase.isInstance(gen)) { gen.generate(writer, phase); } } } private void generateHeader() throws JasperException { String servletPackageName = ctxt.getServletPackageName(); String servletClassName = ctxt.getServletClassName(); // First the package org.apache.jasper34.generator11; if (! "".equals(servletPackageName) && servletPackageName != null) { writer.println("package org.apache.jasper34.generator11;"); writer.println(); } Enumeration e = imports.elements(); while (e.hasMoreElements()) writer.println("import "+(String) e.nextElement()+";"); writer.println(); generateAll(FileDeclarationPhase.class); writer.println(); writer.print("public class "+servletClassName+ " extends "); writer.print(extendsClass.equals("") ? jspServletBase : extendsClass); if (singleThreaded) interfaces.addElement("SingleThreadModel"); if (interfaces.size() != 0) { writer.println(); writer.println(" implements "); for(int i = 0; i < interfaces.size() - 1; i++) writer.println(" "+interfaces.elementAt(i)+","); writer.println(" "+interfaces.elementAt(interfaces.size()-1)); } writer.println(" {"); writer.pushIndent(); writer.println(); generateAll(ClassDeclarationPhase.class); writer.println(); writer.println("static {"); writer.pushIndent(); generateAll(StaticInitializerPhase.class); writer.popIndent(); writer.println("}"); writer.println("public "+servletClassName+"( ) {"); writer.println("}"); writer.println(); writer.println("private boolean _jspx_inited = false;"); writer.println(); writer.println("public final synchronized void _jspx_init() throws org.apache.jasper.JasperException {"); writer.pushIndent(); writer.println("if (! _jspx_inited) {"); writer.pushIndent(); generateAll(InitMethodPhase.class); writer.println("_jspx_inited = true;"); writer.popIndent(); writer.println("}"); writer.popIndent(); writer.println("}"); writer.println(); writer.println("public void "+serviceMethodName+"("+ "HttpServletRequest request, "+ "HttpServletResponse response)"); writer.println(" throws java.io.IOException, ServletException {"); writer.pushIndent(); writer.println(); writer.println("JspFactory _jspxFactory = null;"); writer.println("PageContext pageContext = null;"); if (genSessionVariable) writer.println("HttpSession session = null;"); if (ctxt.isErrorPage()) writer.println("Throwable exception = (Throwable) request.getAttribute(\"javax.servlet.jsp.jspException\");"); writer.println("ServletContext application = null;"); writer.println("ServletConfig config = null;"); writer.println("JspWriter out = null;"); writer.println("Object page = this;"); writer.println("String _value = null;"); writer.println("try {"); writer.pushIndent(); writer.println("try {"); writer.pushIndent(); writer.println(); writer.println("_jspx_init();"); writer.println("_jspxFactory = JspFactory.getDefaultFactory();"); if (this.contentTypeDir == true) writer.println("response.setContentType(" + writer.quoteString(servletContentType) + ");"); else writer.println("response.setContentType(\"" + servletContentType + ";charset=8859_1\");"); writer.println("pageContext = _jspxFactory.getPageContext(this, request, response,\n" + "\t\t\t" + writer.quoteString(error) + ", " + genSessionVariable + ", " + bufferSize + ", " + autoFlush + ");"); writer.println(); writer.println("application = pageContext.getServletContext();"); writer.println("config = pageContext.getServletConfig();"); if (genSessionVariable) writer.println("session = pageContext.getSession();"); writer.println("out = pageContext.getOut();"); } private void generateFooter() throws JasperException { writer.popIndent(); //writer.println("} catch (Throwable t) {"); writer.println("} catch (Exception ex) {"); writer.pushIndent(); writer.println("if (out != null && out.getBufferSize() != 0)"); writer.pushIndent(); writer.println("out.clearBuffer();"); writer.popIndent(); writer.println("if (pageContext != null) pageContext.handlePageException(ex);"); writer.popIndent(); writer.println("} catch (Error error) {"); writer.pushIndent(); writer.println("throw error;"); writer.popIndent(); writer.println("} catch (Throwable throwable) {"); writer.pushIndent(); writer.println("throw new ServletException(throwable);"); writer.popIndent(); writer.println("}"); writer.popIndent(); writer.println("} finally {"); writer.pushIndent(); /* Do stuff here for finally actions... */ //writer.println("out.close();"); // Use flush buffer ( which just empty JspWriterImpl buffer ) // instead of commiting the response. writer.println("if (out instanceof " + Constants.JSP_RUNTIME_PACKAGE + ".JspWriterImpl) { "); writer.println(" ((" + Constants.JSP_RUNTIME_PACKAGE + ".JspWriterImpl)out).flushBuffer();"); writer.println("}"); writer.println("if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);"); writer.popIndent(); writer.println("}"); // Close the service method: writer.popIndent(); writer.println("}"); // Close the class definition: writer.popIndent(); writer.println("}"); } public void handleComment(Mark start, Mark stop) throws JasperException { ctxt.debug("jsp.message.htmlcomment", new Object[] { reader.getChars(start, stop) }); } interface PageDirectiveHandler { void handlePageDirectiveAttribute(JspParseEventListener listener, String value, Mark start, Mark stop) throws JasperException; } static final class PageDirectiveHandlerInfo { String attribute; PageDirectiveHandler handler; PageDirectiveHandlerInfo(String attribute, PageDirectiveHandler handler) { this.attribute = attribute; this.handler = handler; } } static final String languageStr = "language"; static final String extendsStr = "extends"; static final String importStr = "import"; static final String sessionStr = "session"; static final String bufferStr = "buffer"; static final String autoFlushStr = "autoFlush"; static final String isThreadSafeStr = "isThreadSafe"; static final String infoStr = "info"; static final String errorPageStr = "errorPage"; static final String isErrorPageStr = "isErrorPage"; static final String contentTypeStr = "contentType"; PageDirectiveHandlerInfo[] pdhis = new PageDirectiveHandlerInfo[] { new PageDirectiveHandlerInfo(languageStr, new LanguageHandler()), new PageDirectiveHandlerInfo(extendsStr, new ExtendsHandler()), new PageDirectiveHandlerInfo(importStr, new ImportsHandler()), new PageDirectiveHandlerInfo(sessionStr, new SessionHandler()), new PageDirectiveHandlerInfo(bufferStr, new BufferHandler()), new PageDirectiveHandlerInfo(autoFlushStr, new AutoFlushHandler()), new PageDirectiveHandlerInfo(isThreadSafeStr, new IsThreadSafeHandler()), new PageDirectiveHandlerInfo(infoStr, new InfoHandler()), new PageDirectiveHandlerInfo(isErrorPageStr, new IsErrorPageHandler()), new PageDirectiveHandlerInfo(contentTypeStr, new ContentTypeHandler()), new PageDirectiveHandlerInfo(errorPageStr, new ErrorPageHandler()) }; // FIXME: Need to further refine these abstractions by moving the code // to handle duplicate directive instance checks to outside. static final class ContentTypeHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String contentType, Mark start, Mark stop) throws JasperException { if (listener.contentTypeDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.contenttypes")); listener.contentTypeDir = true; if (contentType == null) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.contenttype")); listener.servletContentType = contentType; } } static final class SessionHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String session, Mark start, Mark stop) throws JasperException { if (listener.sessionDir == true) throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.multiple.session")); listener.sessionDir = true; if (session == null) throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.invalid.session")); if (session.equalsIgnoreCase("true")) listener.genSessionVariable = true; else if (session.equalsIgnoreCase("false")) listener.genSessionVariable = false; else throw new CompileException(start, "Invalid value for session"); } } static final class BufferHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String buffer, Mark start, Mark stop) throws JasperException { if (listener.bufferDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.buffer")); listener.bufferDir = true; if (buffer != null) { if (buffer.equalsIgnoreCase("none")) listener.bufferSize = 0; else { Integer i = null; try { int ind = buffer.indexOf("k"); String num; if (ind == -1) num = buffer; else num = buffer.substring(0, ind); i = new Integer(num); } catch (NumberFormatException n) { throw new CompileException(start, listener.getCompilationContext().getString( "jsp.error.page.invalid.buffer")); } listener.bufferSize = i.intValue()*1024; } } else throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.buffer")); } } static final class AutoFlushHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String autoflush, Mark start, Mark stop) throws JasperException { if (listener.autoFlushDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.autoflush")); listener.autoFlushDir = true; if (autoflush == null) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.autoflush")); if (autoflush.equalsIgnoreCase("true")) listener.autoFlush = true; else if (autoflush.equalsIgnoreCase("false")) listener.autoFlush = false; else throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.autoflush")); } } static final class IsThreadSafeHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String threadsafe, Mark start, Mark stop) throws JasperException { if (listener.threadsafeDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.threadsafe")); listener.threadsafeDir = true; if (threadsafe == null) throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.invalid.threadsafe")); if (threadsafe.equalsIgnoreCase("true")) listener.singleThreaded = false; else if (threadsafe.equalsIgnoreCase("false")) listener.singleThreaded = true; else throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.invalid.threadsafe")); } } static final class InfoHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String info, Mark start, Mark stop) throws JasperException { if (listener.infoDir == true) throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.multiple.info")); listener.infoDir = true; if (info == null) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.info")); GeneratorWrapper gen = listener. new GeneratorWrapper(new InfoGenerator(info), start, stop); listener.addGenerator(gen); } } static final class IsErrorPageHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String iserrorpage, Mark start, Mark stop) throws JasperException { if (listener.iserrorpageDir == true) throw new CompileException (start, listener.getCompilationContext().getString("jsp.error.page.multiple.iserrorpage")); listener.iserrorpageDir = true; if (iserrorpage == null) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.iserrorpage")); if (iserrorpage.equalsIgnoreCase("true")) listener.ctxt.setErrorPage(true); else if (iserrorpage.equalsIgnoreCase("false")) listener.ctxt.setErrorPage(false); else throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.invalid.iserrorpage")); } } static final class ErrorPageHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String errorpage, Mark start, Mark stop) throws JasperException { if (listener.errorpageDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.errorpage")); listener.errorpageDir = true; if (errorpage != null) listener.error = errorpage; } } static final class LanguageHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String language, Mark start, Mark stop) throws JasperException { if (listener.languageDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.language")); listener.languageDir = true; if (language != null) if (!language.equalsIgnoreCase("java")) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.nomapping.language")+language); } } static final class ImportsHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String importPkgs, Mark start, Mark stop) throws JasperException { if (importPkgs != null) { StringTokenizer tokenizer = new StringTokenizer(importPkgs, ","); while (tokenizer.hasMoreTokens()) listener.imports.addElement(tokenizer.nextToken()); } } } static final class ExtendsHandler implements PageDirectiveHandler { public void handlePageDirectiveAttribute(JspParseEventListener listener, String extendsClzz, Mark start, Mark stop) throws JasperException { if (listener.extendsDir == true) throw new CompileException(start, listener.getCompilationContext().getString("jsp.error.page.multiple.extends")); listener.extendsDir = true; if (extendsClzz != null) { listener.extendsClass = extendsClzz; /* * If page superclass is top level class (i.e. not in a pkg) * explicitly import it. If this is not done, the compiler * will assume the extended class is in the same pkg as * the generated servlet. */ if (extendsClzz.indexOf(".") == -1) { listener.imports.addElement(extendsClzz); } } } } public void handleDirective(String directive, Mark start, Mark stop, Hashtable attrs) throws JasperException { ctxt.debug("jsp.message.handling_directive", new Object[] { directive, attrs }); if (directive.equals("page")) { Enumeration e = attrs.keys(); String attr; while (e.hasMoreElements()) { attr = (String) e.nextElement(); for(int i = 0; i < pdhis.length; i++) { PageDirectiveHandlerInfo pdhi = pdhis[i]; if (attr.equals(pdhi.attribute)) { String value = (String) attrs.get(pdhi.attribute); pdhi.handler.handlePageDirectiveAttribute(this, value, start, stop); } } } } // Do some validations... if (bufferSize == 0 && autoFlush == false) throw new CompileException(start, ctxt.getString( "jsp.error.page.bad_b_and_a_combo")); if (directive.equals("taglib")) { String uri = (String) attrs.get("uri"); String prefix = (String) attrs.get("prefix"); try { TagLibraryInfo tl = new TagLibraryInfoImpl(ctxt, prefix, uri); libraries.addTagLibrary(prefix, tl); } catch (Exception ex) { Object[] args = new Object[] { uri, ex.getMessage() }; throw new CompileException(start, ctxt.getString("jsp.error.badtaglib", args)); } } if (directive.equals("include")) { String file = (String) attrs.get("file"); if (file == null) throw new CompileException(start, ctxt.getString("jsp.error.include.missing.file")); // jsp.error.include.bad.file needs taking care of here?? try { reader.pushFile(file); } catch (FileNotFoundException fnfe) { throw new CompileException(start, ctxt.getString("jsp.error.include.bad.file")); } } } class GeneratorWrapper implements Generator, ClassDeclarationPhase, FileDeclarationPhase, ServiceMethodPhase, InitMethodPhase, StaticInitializerPhase { Generator generator; Mark start, stop; GeneratorWrapper(Generator generator, Mark start, Mark stop) { this.generator = generator; this.start = start; this.stop = stop; } /* * This is really a no-op. */ public boolean generateCoordinates(Class phase) { return generator.generateCoordinates(phase); } public void init(JspCompilationContext ctxt) throws JasperException { generator.init(ctxt); } public void generate(ServletWriter out, Class phase) throws JasperException { if (phase.isInstance(generator)) { boolean genCoords = generator.generateCoordinates(phase); if (genCoords) { commentGenerator.generateStartComment (generator, out, start, stop); } generator.generate(out, phase); if (genCoords) { commentGenerator.generateEndComment (generator, out, start, stop); } } } } public void handleDeclaration(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new DeclarationGenerator(reader.getChars( start, stop)), start, stop); addGenerator(gen); } public void handleScriptlet(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new ScriptletGenerator(reader.getChars( start, stop)), start, stop); addGenerator(gen); } public void handleExpression(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new ExpressionGenerator(reader.getChars( start, stop)), start, stop); addGenerator(gen); } public void handleBean(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new BeanGenerator(ctxt, start, attrs, beanInfo, genSessionVariable), start, stop); addGenerator(gen); } public void handleBeanEnd(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new BeanEndGenerator(), start, stop); // End the block started by useBean body. addGenerator(gen); } public void handleGetProperty(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new GetPropertyGenerator(start, stop, attrs, beanInfo), start, stop); addGenerator(gen); } public void handleSetProperty(Mark start, Mark stop, Hashtable attrs) throws JasperException { Generator gen = new GeneratorWrapper(new SetPropertyGenerator(ctxt, start, stop, attrs, beanInfo), start, stop); addGenerator(gen); } public void handlePlugin(Mark start, Mark stop, Hashtable attrs, Hashtable param, String fallback) throws JasperException { ctxt.debug("jsp.message.handling_plugin", new Object[] { attrs }); Generator gen = new GeneratorWrapper (new PluginGenerator (ctxt, start, attrs, param, fallback), start, stop); addGenerator (gen); } public void handleForward(Mark start, Mark stop, Hashtable attrs, Hashtable param) throws JasperException { Generator gen = new GeneratorWrapper(new ForwardGenerator(ctxt, start, attrs, param), start, stop); addGenerator(gen); } public void handleInclude(Mark start, Mark stop, Hashtable attrs, Hashtable param) throws JasperException { Generator gen = new GeneratorWrapper(new IncludeGenerator(ctxt,start, attrs, param), start, stop); addGenerator(gen); } public void handleCharData(Mark start, Mark stop, char[] chars) throws JasperException { GeneratorBase cdg; if (ctxt.getOptions().getLargeFile()) cdg = new StoredCharDataGenerator(vector, dataFile, stringId++, chars); else if(ctxt.getOptions().getMappedFile()) cdg = new MappedCharDataGenerator(chars); else cdg = new CharDataGenerator(chars); Generator gen = new GeneratorWrapper(cdg, start, stop); addGenerator(gen); } public void handleTagBegin(Mark start, Mark stop, Hashtable attrs, String prefix, String shortTagName, TagLibraryInfo tli, TagInfo ti) throws JasperException { TagBeginGenerator tbg = new TagBeginGenerator(ctxt, start, prefix, shortTagName, attrs, tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers()); Generator gen = new GeneratorWrapper(tbg, start, stop); addGenerator(gen); // If this is the first tag, then generate code to store reference // to tag pool manager. if (tagPools.size() == 0) { addGenerator(new TagPoolManagerGenerator()); } // if we haven't added a tag pool generator for this tag, then add one String tagPoolVarName = TagPoolGenerator.getPoolName(tli, ti, attrs); if (! tagPools.contains(tagPoolVarName)) { tagPools.add(tagPoolVarName); TagPoolGenerator tpg = new TagPoolGenerator(prefix, shortTagName, attrs, tli, ti); gen = new GeneratorWrapper(tpg, start, stop); addGenerator(gen); } } public void handleTagEnd(Mark start, Mark stop, String prefix, String shortTagName, Hashtable attrs, TagLibraryInfo tli, TagInfo ti) throws JasperException { TagEndGenerator teg = new TagEndGenerator(prefix, shortTagName, attrs, tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers()); Generator gen = new GeneratorWrapper(teg, start, stop); addGenerator(gen); } public TagLibraries getTagLibraries() { return libraries; } } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/ServletWriter.java Index: ServletWriter.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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import org.apache.jasper34.core.*; import org.apache.jasper34.parser11.*; import java.io.PrintWriter; import java.io.BufferedReader; import java.io.StringReader; import java.io.IOException; //import org.apache.jasper34.generator11.parse.Mark; /** * This is what is used to generate servlets. * * @author Anil K. Vijendran */ public class ServletWriter { public static int TAB_WIDTH = 4; public static String SPACES = " "; // Current indent level: int indent = 0; // The sink writer: PrintWriter writer; public ServletWriter(PrintWriter writer) { this.writer = writer; } public void close() throws IOException { writer.close(); } public void pushIndent() { if ((indent += TAB_WIDTH) > SPACES.length()) indent = SPACES.length(); } public void popIndent() { if ((indent -= TAB_WIDTH) <= 0 ) indent = 0; } /** * Print a standard comment for echo outputed chunk. * @param start The starting position of the JSP chunk being processed. * @param stop The ending position of the JSP chunk being processed. */ public void printComment(Mark start, Mark stop, char[] chars) { if (start != null && stop != null) { println("// from="+start); println("// to="+stop); } if (chars != null) for(int i = 0; i < chars.length;) { indent(); print("// "); while (chars[i] != '\n' && i < chars.length) writer.print(chars[i++]); } } /** * Quote the given string to make it appear in a chunk of java code. * @param s The string to quote. * @return The quoted string. */ public String quoteString(String s) { // Turn null string into quoted empty strings: if ( s == null ) return "null"; // Hard work: if ( s.indexOf('"') < 0 && s.indexOf('\\') < 0 && s.indexOf ('\n') < 0 && s.indexOf ('\r') < 0) return "\""+s+"\""; StringBuffer sb = new StringBuffer(); int len = s.length(); sb.append('"'); for (int i = 0 ; i < len ; i++) { char ch = s.charAt(i); if ( ch == '\\' && i+1 < len) { sb.append('\\'); sb.append('\\'); sb.append(s.charAt(++i)); } else if ( ch == '"' ) { sb.append('\\'); sb.append('"'); } else if (ch == '\n') { sb.append ("\\n"); }else if (ch == '\r') { sb.append ("\\r"); }else { sb.append(ch); } } sb.append('"'); return sb.toString(); } public void println(String line) { writer.println(SPACES.substring(0, indent)+line); } public void println() { writer.println(""); } public void indent() { writer.print(SPACES.substring(0, indent)); } public void print(String s) { writer.print(s); } public void printMultiLn(String multiline) { // Try to be smart (i.e. indent properly) at generating the code: BufferedReader reader = new BufferedReader(new StringReader(multiline)); try { for (String line = null ; (line = reader.readLine()) != null ; ) // println(SPACES.substring(0, indent)+line); println(line); } catch (IOException ex) { // Unlikely to happen, since we're acting on strings } } } 1.1 jakarta-tomcat/proposals/jasper34/generator/org/apache/jasper34/generator11/TagLibraryInfoImpl.java Index: TagLibraryInfoImpl.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 [EMAIL PROTECTED] * * 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.jasper34.generator11; import java.net.URL; import java.util.zip.ZipInputStream; import java.util.zip.ZipEntry; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.io.IOException; import java.io.File; import java.io.FileNotFoundException; import java.util.Vector; import java.util.Hashtable; import javax.servlet.jsp.tagext.TagLibraryInfo; import javax.servlet.jsp.tagext.TagInfo; import javax.servlet.jsp.tagext.TagAttributeInfo; import javax.servlet.jsp.tagext.TagExtraInfo; import org.w3c.dom.*; import org.xml.sax.*; import org.apache.jasper34.core.*; import org.apache.jasper34.parser11.*; import org.apache.jasper34.generator11.util.*; // import org.apache.jasper.JasperException; // import org.apache.jasper.Constants; //import org.apache.jasper.runtime.JspLoader; //import org.apache.tomcat.util.log.*; /** * Implementation of the TagLibraryInfo class from the JSP spec. * * @author Anil K. Vijendran * @author Mandar Raje */ public class TagLibraryInfoImpl extends TagLibraryInfo { static private final String TLD = "META-INF/taglib.tld"; static private final String WEBAPP_INF = "/WEB-INF/web.xml"; Document tld; Hashtable jarEntries; JspCompilationContext ctxt; private final void print(String name, String value, PrintWriter w) { if (value != null) { w.print(name+" = {\n\t"); w.print(value); w.print("\n}\n"); } } public String toString() { StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); print("tlibversion", tlibversion, out); print("jspversion", jspversion, out); print("shortname", shortname, out); print("urn", urn, out); print("info", info, out); print("uri", uri, out); for(int i = 0; i < tags.length; i++) out.println(tags[i].toString()); return sw.toString(); } // XXX FIXME // resolveRelativeUri and/or getResourceAsStream don't seem to properly // handle relative paths when dealing when home and getDocBase are set // the following is a workaround until these problems are resolved. private InputStream getResourceAsStream(String uri) throws FileNotFoundException { if (uri.indexOf(":") > 0) { // may be fully qualified (Windows) or may be a URL. Let // getResourceAsStream deal with it. return ctxt.getResourceAsStream(uri); } else { // assume it translates to a real file, and use getRealPath String real = ctxt.getRealPath(uri); return (real == null) ? null : new FileInputStream(real); } } public TagLibraryInfoImpl(JspCompilationContext ctxt, String prefix, String uriIn) throws IOException, JasperException { super(prefix, uriIn); this.ctxt = ctxt; ZipInputStream zin; InputStream in = null; URL url = null; boolean relativeURL = false; this.uri = uriIn; // Parse web.xml. InputStream is = getResourceAsStream(WEBAPP_INF); if (is != null) { Document webtld = JspParseUtil.parseXMLDoc(is, Constants.WEBAPP_DTD_RESOURCE, Constants.WEBAPP_DTD_PUBLIC_ID); NodeList nList = webtld.getElementsByTagName("taglib"); if (nList.getLength() != 0) { for(int i = 0; i < nList.getLength(); i++) { String tagLoc = null; boolean match = false; Element e = (Element) nList.item(i); // Assume only one entry for location and uri. NodeList uriList = e.getElementsByTagName("taglib-uri"); Element uriElem = (Element) uriList.item(0); Text t = (Text) uriElem.getFirstChild(); if (t != null) { String tmpUri = t.getData(); if (tmpUri != null) { tmpUri = tmpUri.trim(); if (tmpUri.equals(uriIn)) { match = true; NodeList locList = e.getElementsByTagName ("taglib-location"); Element locElem = (Element) locList.item(0); Text tl = (Text) locElem.getFirstChild(); if (tl != null) { tagLoc = tl.getData(); if (tagLoc != null) tagLoc = tagLoc.trim(); } } } } if (match == true && tagLoc != null) { this.uri = tagLoc; // If this is a relative path, then it has to be // relative to where web.xml is. // I'm taking the simple way out. Since web.xml // has to be directly under WEB-INF, I'm making // an absolute URI out of it by prepending WEB-INF if (!uri.startsWith("/") && isRelativeURI(uri)) uri = "/WEB-INF/"+uri; } } } } // Try to resolve URI relative to the current JSP page if (!uri.startsWith("/") && isRelativeURI(uri)) uri = ctxt.resolveRelativeUri(uri); if (!uri.endsWith("jar")) { in = getResourceAsStream(uri); if (in == null) throw new JasperException(ctxt.getString("jsp.error.tld_not_found", new Object[] {uri})); // Now parse the tld. parseTLD(in); } // FIXME Take this stuff out when taglib changes are thoroughly tested. // 2000.11.15 commented out the 'copy to work dir' section, // which I believe is what this FIXME comment referred to. (pierred) if (uri.endsWith("jar")) { if (!isRelativeURI(uri)) { url = new URL(uri); in = url.openStream(); } else { relativeURL = true; in = getResourceAsStream(uri); } zin = new ZipInputStream(in); this.jarEntries = new Hashtable(); this.ctxt = ctxt; /* NOT COMPILED // First copy this file into our work directory! { File jspFile = new File(ctxt.getJspFile()); String parent = jspFile.getParent(); String jarFileName = ctxt.getOutputDir(); if (parent != null) { jarFileName = jarFileName + File.separatorChar + parent; } File jspDir = new File(jarFileName); jspDir.mkdirs(); if (relativeURL) jarFileName = jarFileName+File.separatorChar+new File(uri).getName(); else jarFileName = jarFileName+File.separatorChar+ new File(url.getFile()).getName(); Constants.message("jsp.message.copyinguri", new Object[] { uri, jarFileName }, Log.DEBUG); if (relativeURL) copy(getResourceAsStream(uri), jarFileName); else copy(url.openStream(), jarFileName); ctxt.addJar(jarFileName); } */ // END NOT COMPILED boolean tldFound = false; ZipEntry entry; while ((entry = zin.getNextEntry()) != null) { if (entry.getName().equals(TLD)) { /******* * This hack is necessary because XML reads until the end * of an inputstream -- does not use available() * -- and closes the inputstream when it can't * read no more. */ // BEGIN HACK ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b; while (zin.available() != 0) { b = zin.read(); if (b == -1) break; baos.write(b); } baos.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); // END HACK tldFound = true; parseTLD(bais); } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b; while (zin.available() != 0) { b = zin.read(); if (b == -1) break; baos.write(b); } baos.close(); jarEntries.put(entry.getName(), baos.toByteArray()); } zin.closeEntry(); } if (!tldFound) throw new JasperException(ctxt.getString("jsp.error.tld_not_found", new Object[] { TLD } )); } // Take this out (END of if(endsWith("jar"))) } /** Returns true if the given URI is relative in this web application, false if it is an internet URI. */ private boolean isRelativeURI(String uri) { return (uri.indexOf(':') == -1); } private void parseTLD(InputStream in) throws JasperException { tld = JspParseUtil.parseXMLDoc(in, Constants.TAGLIB_DTD_RESOURCE, Constants.TAGLIB_DTD_PUBLIC_ID); Vector tagVector = new Vector(); NodeList list = tld.getElementsByTagName("taglib"); if (list.getLength() != 1) throw new JasperException(ctxt.getString("jsp.error.more.than.one.taglib")); Element elem = (Element) list.item(0); list = elem.getChildNodes(); for(int i = 0; i < list.getLength(); i++) { Node tmp = list.item(i); if (! (tmp instanceof Element)) continue; Element e = (Element) tmp; String tname = e.getTagName(); if (tname.equals("tlibversion")) { Text t = (Text) e.getFirstChild(); if (t != null) this.tlibversion = t.getData().trim(); } else if (tname.equals("jspversion")) { Text t = (Text) e.getFirstChild(); if (t != null) this.jspversion = t.getData().trim(); } else if (tname.equals("shortname")) { Text t = (Text) e.getFirstChild(); if (t != null) this.shortname = t.getData().trim(); } else if (tname.equals("uri")) { Text t = (Text) e.getFirstChild(); if (t != null) this.urn = t.getData().trim(); } else if (tname.equals("info")) { Text t = (Text) e.getFirstChild(); if (t != null) this.info = t.getData().trim(); } else if (tname.equals("tag")) tagVector.addElement(createTagInfo(e)); else ctxt.log("jsp.warning.unknown.element.in.TLD", new Object[] { e.getTagName() } ); } this.tags = new TagInfo[tagVector.size()]; tagVector.copyInto (this.tags); } private TagInfo createTagInfo(Element elem) throws JasperException { String name = null, tagclass = null, teiclass = null; String bodycontent = "JSP"; // Default body content is JSP String info = null; Vector attributeVector = new Vector(); NodeList list = elem.getChildNodes(); for(int i = 0; i < list.getLength(); i++) { Node tmp = list.item(i); if (! (tmp instanceof Element)) continue; Element e = (Element) tmp; String tname = e.getTagName(); if (tname.equals("name")) { Text t = (Text) e.getFirstChild(); if (t != null) name = t.getData().trim(); } else if (tname.equals("tagclass")) { Text t = (Text) e.getFirstChild(); if (t != null) tagclass = t.getData().trim(); } else if (tname.equals("teiclass")) { Text t = (Text) e.getFirstChild(); if (t != null) teiclass = t.getData().trim(); } else if (tname.equals("bodycontent")) { Text t = (Text) e.getFirstChild(); if (t != null) bodycontent = t.getData().trim(); } else if (tname.equals("info")) { Text t = (Text) e.getFirstChild(); if (t != null) info = t.getData().trim(); } else if (tname.equals("attribute")) attributeVector.addElement(createAttribute(e)); else ctxt.log("jsp.warning.unknown.element.in.tag", new Object[] { e.getTagName() }); } TagAttributeInfo[] tagAttributeInfo = new TagAttributeInfo[attributeVector.size()]; attributeVector.copyInto (tagAttributeInfo); TagExtraInfo tei = null; if (teiclass != null && !teiclass.equals("")) try { Class teiClass = ctxt.getClassLoader().loadClass(teiclass); tei = (TagExtraInfo) teiClass.newInstance(); } catch (ClassNotFoundException cex) { ctxt.log("jsp.warning.teiclass.is.null", new Object[] { teiclass, cex.getMessage() }); } catch (IllegalAccessException iae) { ctxt.log("jsp.warning.teiclass.is.null", new Object[] { teiclass, iae.getMessage() }); } catch (InstantiationException ie) { ctxt.log("jsp.warning.teiclass.is.null", new Object[] { teiclass, ie.getMessage() }); } TagInfo taginfo = new TagInfo(name, tagclass, bodycontent, info, this, tei, tagAttributeInfo); return taginfo; } TagAttributeInfo createAttribute(Element elem) { String name = null; boolean required = false, rtexprvalue = false, reqTime = false; String type = null; NodeList list = elem.getChildNodes(); for(int i = 0; i < list.getLength(); i++) { Node tmp = list.item(i); if (! (tmp instanceof Element)) continue; Element e = (Element) tmp; String tname = e.getTagName(); if (tname.equals("name")) { Text t = (Text) e.getFirstChild(); if (t != null) name = t.getData().trim(); } else if (tname.equals("required")) { Text t = (Text) e.getFirstChild(); if (t != null) { required = Boolean.valueOf(t.getData().trim()).booleanValue(); if( t.getData().equalsIgnoreCase("yes") ) required = true; } } else if (tname.equals("rtexprvalue")) { Text t = (Text) e.getFirstChild(); if (t != null) { rtexprvalue = Boolean.valueOf(t.getData().trim()).booleanValue(); if( t.getData().equalsIgnoreCase("yes") ) rtexprvalue = true; } } else if (tname.equals("type")) { Text t = (Text) e.getFirstChild(); if (t != null) type = t.getData().trim(); } else ctxt.log("jsp.warning.unknown.element.in.attribute", new Object[] { e.getTagName() }); } // return new TagAttributeInfo(name, required, rtexprvalue, type); return new TagAttributeInfo(name, required, type, rtexprvalue); } static void copy(InputStream in, String fileName) throws IOException, FileNotFoundException { byte[] buf = new byte[1024]; FileOutputStream out = new FileOutputStream(fileName); int nRead; while ((nRead = in.read(buf, 0, buf.length)) != -1) out.write(buf, 0, nRead); } }