com.caucho.jsp.java.JavaJspGenerator Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jsp.java;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELContext;
import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.tagext.PageData;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagLibraryValidator;
import javax.servlet.jsp.tagext.ValidationMessage;
import com.caucho.VersionFactory;
import com.caucho.config.types.Signature;
import com.caucho.el.Expr;
import com.caucho.java.CompileClassNotFound;
import com.caucho.java.LineMap;
import com.caucho.java.LineMapWriter;
import com.caucho.jsp.JspGenerator;
import com.caucho.jsp.JspPageConfig;
import com.caucho.jsp.JspParseException;
import com.caucho.jsp.ParseState;
import com.caucho.jsp.ParseTagManager;
import com.caucho.jsp.QPageData;
import com.caucho.jsp.StaticPage;
import com.caucho.jsp.TagInstance;
import com.caucho.jsp.Taglib;
import com.caucho.jsp.cfg.TldFunction;
import com.caucho.jsp.el.JspELParser;
import com.caucho.make.ClassDependency;
import com.caucho.server.util.CauchoSystem;
import com.caucho.util.IntMap;
import com.caucho.util.L10N;
import com.caucho.vfs.Depend;
import com.caucho.vfs.Encoding;
import com.caucho.vfs.MergePath;
import com.caucho.vfs.Path;
import com.caucho.vfs.PersistentDependency;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.TempStream;
import com.caucho.vfs.WriteStream;
import com.caucho.xml.QName;
import com.caucho.xpath.NamespaceContext;
import com.caucho.xpath.XPath;
import com.caucho.xpath.XPathParseException;
/**
* Generates JSP code. JavaGenerator, JavaScriptGenerator, and
* StaticGenerator specialize the JspGenerator for language-specific
* requirements.
*
* JspParser parses the JSP file into an XML-DOM tree. JspGenerator
* generates code from that tree.
*/
public class JavaJspGenerator extends JspGenerator {
private static final L10N L = new L10N(JavaJspGenerator.class);
private static final Logger log
= Logger.getLogger(JavaJspGenerator.class.getName());
static final String IE_CLSID = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
static final String IE_URL = "http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0";
static final String NS_URL = "http://java.sun.com/products/plugin/";
static HashMap> _primitiveClasses;
static HashMap _primitives;
protected JspNode _rootNode;
protected ParseState _parseState;
/*
* Variables storing the JSP directives.
*/
protected boolean _ideHack = false;
/*
* Variables controlling caching
* isUncacheable overrides isCacheable.
*/
protected boolean _isCacheable;
protected boolean _isUncacheable;
protected ArrayList _cacheDepends = new ArrayList();
// dependencies for the source file itself
protected ArrayList _depends
= new ArrayList();
long _lastModified; // XXX: obsolete?
protected TagInstance _topTag;
protected int _tagId;
// XXX: needed in combination with XTP
boolean _alwaysModified;
protected ParseTagManager _tagManager;
protected JspPageConfig _config = new JspPageConfig();
protected String _fullClassName;
protected String _className;
private HashMap> _classes;
private HashSet _declaredVariables = new HashSet();
private String _filename;
private final JspGenELContext _elContext;
private HashMap _elFunctionMap = new HashMap();
private ArrayList _tagLibraryList
= new ArrayList();
private ArrayList _tagFileClassList
= new ArrayList();
private PageData _pageData;
protected IntMap _strings = new IntMap();
private ArrayList _exprList
= new ArrayList();
private ArrayList _valueExprList
= new ArrayList();
private ArrayList _methodExprList
= new ArrayList();
private ArrayList _xpathExprList
= new ArrayList();
private ArrayList _fragmentList
= new ArrayList();
private String _workPath;
protected String _pkg;
private int _uniqueId = 0;
private int _jspId = 1;
private boolean _requireSource = false;
private boolean _isOmitXmlDeclaration = false;
private String _doctypeSystem;
private String _doctypePublic;
private String _doctypeRootElement;
private boolean _isJsfPrologueInit;
private boolean _isStatic = false;
protected ArrayList _declarations =
new ArrayList();
public JavaJspGenerator(ParseTagManager tagManager)
{
_elContext = new JspGenELContext(this);
_tagManager = tagManager;
_topTag = new TagInstance(tagManager);
}
public TagInstance getRootTag()
{
return _topTag;
}
protected void setParseState(ParseState parseState)
{
_parseState = parseState;
}
public ParseState getParseState()
{
return _parseState;
}
public void setPageConfig(JspPageConfig pageConfig)
{
_config = pageConfig;
}
void setStaticEncoding(boolean staticEncoding)
{
_config.setStaticEncoding(staticEncoding);
}
void setRequireSource(boolean requireSource)
{
_requireSource = requireSource;
}
void setIdeHack(boolean ideHack)
{
_ideHack = ideHack;
}
String getPackagePrefix()
{
return "";
}
Path getAppDir()
{
return _jspCompiler.getAppDir();
}
/**
* Returns true for XML.
*/
boolean isXml()
{
// jsp/0362
return _parseState.isXml();
}
/**
* Returns true if the XML declaration should be set.
*/
boolean isOmitXmlDeclaration()
{
return _isOmitXmlDeclaration;
}
/**
* Returns true if the XML declaration should be set.
*/
void setOmitXmlDeclaration(boolean omitXml)
{
_isOmitXmlDeclaration = omitXml;
}
/**
* Sets the dtd system name
*/
void setDoctypeSystem(String doctypeSystem)
{
_doctypeSystem = doctypeSystem;
}
/**
* Gets the dtd system name
*/
String getDoctypeSystem()
{
return _doctypeSystem;
}
/**
* Sets the dtd public name
*/
void setDoctypePublic(String doctypePublic)
{
_doctypePublic = doctypePublic;
}
/**
* Gets the dtd public name
*/
String getDoctypePublic()
{
return _doctypePublic;
}
/**
* Gets the dtd root element name
*/
void setDoctypeRootElement(String doctypeRootElement)
{
_doctypeRootElement = doctypeRootElement;
}
/**
* Gets the dtd root element name
*/
String getDoctypeRootElement()
{
return _doctypeRootElement;
}
/**
* Returns the character encoding.
*/
String getCharacterEncoding()
{
return _parseState.getCharEncoding();
}
Path getClassDir()
{
return _jspCompiler.getClassDir();
}
/**
* Sets the root JSP node.
*/
public void setRootNode(JspNode node)
{
_rootNode = node;
}
public JspPageConfig getConfig()
{
return _config;
}
public boolean isTag()
{
return false;
}
public void init()
{
_isOmitXmlDeclaration = ! isXml();
}
public boolean hasScripting()
{
return _rootNode.hasScripting();
}
public boolean isJsfPrologueInit()
{
return _isJsfPrologueInit;
}
public void setJsfPrologueInit(boolean isInit)
{
_isJsfPrologueInit = isInit;
}
/**
* Adds a taglib.
*/
public void addTaglib(String prefix, String uri)
throws JspParseException
{
addTaglib(prefix, uri, false);
}
/**
* True for a pre jsp21 tag
*/
public boolean isPre21()
{
return _parseState.getJspVersion().compareTo("2.1") < 0;
}
public boolean isPrototype()
{
return _parseState.isPrototype();
}
/**
* Adds a taglib.
*/
public void addOptionalTaglib(String prefix, String uri)
throws JspParseException
{
addTaglib(prefix, uri, true);
}
/**
* Adds a taglib.
*/
public Taglib addTaglib(String prefix, String uri, boolean isOptional)
throws JspParseException
{
if (log.isLoggable(Level.FINEST))
log.finest("taglib prefix=" + prefix + " uri:" + uri);
Taglib taglib;
try {
taglib = _tagManager.addTaglib(prefix, uri);
} catch (JspParseException e) {
if (isOptional) {
log.log(Level.FINE, e.toString(), e);
return null;
}
throw e;
}
if (taglib == null && isOptional &&
! uri.startsWith("urn:jsptld:") && ! uri.startsWith("urn:jsptagdir:"))
return null;
if (taglib == null) {
throw error(L.l("'{0}' has no matching taglib-uri. Taglibs specified with an absolute URI must either be:\n"
+ "1) specified in the web.xml\n"
+ "2) defined in a jar's .tld in META-INF\n"
+ "3) defined in a .tld in WEB-INF\n"
+ "4) predefined by Resin",
uri));
}
taglib = addLibrary(taglib);
ArrayList functions = taglib.getFunctionList();
for (int i = 0; i < functions.size(); i++) {
TldFunction function = functions.get(i);
String name = taglib.getPrefixString() + ":" + function.getName();
_elFunctionMap.put(name, function.getMethod());
}
return taglib;
}
void addTagFileClass(String cl)
{
if ("com.caucho.jsp.java.JspTagFileSupport".equals(cl))
throw new IllegalStateException();
if (! _tagFileClassList.contains(cl))
_tagFileClassList.add(cl);
}
private Taglib addLibrary(Taglib taglib)
throws JspParseException
{
for (int i = 0; i < _tagLibraryList.size(); i++) {
Taglib oldTaglib = _tagLibraryList.get(i);
if (oldTaglib.getURI().equals(taglib.getURI()))
return oldTaglib;
}
/*
// taglib = taglib.copy();
for (int i = 0; i < _tagLibraryList.size(); i++) {
Taglib oldTaglib = _tagLibraryList.get(i);
oldTaglib.addTaglib(taglib);
taglib.addTaglib(oldTaglib);
}
*/
_tagLibraryList.add(taglib);
return taglib;
}
Method resolveFunction(String prefix, String localName)
{
if (prefix.equals(""))
return _elFunctionMap.get(localName);
else
return _elFunctionMap.get(prefix + ':' + localName);
}
/**
* Adds a taglib.
*/
public void addTaglibDir(String prefix, String tagdir)
throws JspParseException
{
Taglib taglib = _tagManager.addTaglibDir(prefix, tagdir);
ArrayList functions = taglib.getFunctionList();
for (int i = 0; i < functions.size(); i++) {
TldFunction function = functions.get(i);
String name = taglib.getPrefixString() + ":" + function.getName();
_elFunctionMap.put(name, function.getMethod());
}
}
/**
* Returns true if the JSP compilation has produced a static file.
*/
public boolean isStatic()
{
return _isStatic;
}
/**
* Returns the page's XML view.
*/
public PageData getPageData()
throws IOException
{
if (_pageData != null)
return _pageData;
TempStream ts = new TempStream();
ts.openWrite();
WriteStream ws = new WriteStream(ts);
ws.setEncoding("UTF-8");
_rootNode.printXml(ws);
ws.close();
if (log.isLoggable(Level.FINER)) {
StringBuilder sb = new StringBuilder();
ReadStream is = ts.openReadAndSaveBuffer();
int ch;
while ((ch = is.readChar()) >= 0) {
sb.append((char) ch);
}
is.close();
log.finer("JSP[" + _fullClassName + "] " + sb);
}
_pageData = new QPageData(ts);
return _pageData;
}
public ELContext getELContext()
{
return _elContext;
}
/**
* Validates the JSP page.
*/
public void validate()
throws Exception
{
for (int i = 0; i < _tagLibraryList.size(); i++) {
Taglib taglib = _tagLibraryList.get(i);
TagLibraryValidator validator = taglib.getValidator();
if (validator != null) {
ValidationMessage []messages;
messages = validator.validate(taglib.getPrefixString(),
taglib.getURI(),
getPageData());
if (messages != null && messages.length > 0) {
StringBuilder message = new StringBuilder();
for (int j = 0; j < messages.length; j++) {
if (j != 0)
message.append("\n");
message.append(messages[j].getMessage());
}
// TCK: needs to be commented out for TCK
if (log.isLoggable(Level.FINE)) {
InputStream is = getPageData().getInputStream();
StringBuilder sb = new StringBuilder();
int ch;
while ((ch = is.read()) >= 0)
sb.append((char) ch);
throw _rootNode.error(message.toString() + "\n\n" + sb);
}
else
throw _rootNode.error(message.toString());
}
}
}
}
/**
* Generates the JSP page.
*/
@Override
protected void generate(Path path, String className)
throws Exception
{
init(className);
if (_jspCompilerInstance == null ||
! _jspCompilerInstance.isGeneratedSource())
addDepend(path);
_cacheDepends = new ArrayList();
_tagId = 1;
if (_ideHack)
_config.setStaticEncoding(false);
// disable static pages. No longer needed and complicates
// precompilation
if (isGenerateStatic()
&& ! _parseState.getJspPropertyGroup().getStaticPageGeneratesClass()) {
generateStatic();
}
else {
WriteStream os = openWriteStream();
JspJavaWriter out = new JspJavaWriter(os, this);
try {
generate(out);
} finally {
if (os != null)
os.close();
}
}
if (_lineMap != null) {
Path javaPath = getGeneratedPath();
String tail = javaPath.getTail();
tail = tail + ".smap";
WriteStream os = javaPath.getParent().lookup(tail).openWrite();
LineMapWriter writer = new LineMapWriter(os);
writer.write(_lineMap);
os.close();
}
}
public void addDepend(Path path)
{
addDepend(path.createDepend());
}
/**
* Adds a dependency based on a class.
*/
public void addDepend(Class> cl)
{
addDepend(new ClassDependency(cl));
}
public void addDepend(PersistentDependency depend)
{
if (! _depends.contains(depend))
_depends.add(depend);
}
public ArrayList getDependList()
{
return _depends;
}
public boolean isStaticEncoding()
{
return _config.isStaticEncoding();
}
public boolean getRecycleTags()
{
return _parseState.isRecycleTags();
}
/**
* Adds a new Java declaration to the list.
*/
public void addDeclaration(JspDeclaration decl)
{
_declarations.add(decl);
}
/**
* Sets the taglib manager.
*/
public void setTagManager(ParseTagManager tagManager)
{
_tagManager = tagManager;
}
/**
* Returns the taglib manager.
*/
public ParseTagManager getTagManager()
{
return _tagManager;
}
protected void init(String className)
{
_fullClassName = className;
_className = className;
String prefix = getPackagePrefix();
if (prefix.endsWith("."))
prefix = prefix.substring(0, prefix.length() - 1);
int p = className.lastIndexOf('.');
if (p > 0) {
_pkg = className.substring(0, p);
_className = className.substring(p + 1);
}
else
_pkg = "";
if (prefix.length() > 0 && _pkg.length() > 0)
_pkg = prefix + "." + _pkg;
else if (prefix.length() > 0)
_pkg = prefix;
_workPath = _pkg.replace('.', '/');
_lineMap = new LineMap(className.replace('.', '/') + ".java");
}
/**
* True if it's a declared variable.
*/
public boolean isDeclared(String var)
{
return _declaredVariables.contains(var);
}
/**
* Adds a declared variable.
*/
public void addDeclared(String var)
{
_declaredVariables.add(var);
}
/**
* Generates the Java code.
*/
protected void generate(JspJavaWriter out)
throws Exception
{
out.setLineMap(_lineMap);
generateClassHeader(out);
generatePageHeader(out);
_rootNode.generate(out);
generatePageFooter(out);
// _rootNode.generateDeclaration(out);
generateClassFooter(out);
}
/**
* Generates a static file.
*/
protected void generateStatic()
throws Exception
{
_isStatic = true;
Path javaPath = getGeneratedPath();
String tail = javaPath.getTail();
int p = tail.indexOf('.');
tail = tail.substring(0, p);
Path staticPath = javaPath.getParent().lookup(tail + ".static");
WriteStream os = staticPath.openWrite();
//os.setEncoding(_parseState.getCharEncoding());
os.setEncoding("UTF-8");
try {
JspJavaWriter out = new JspJavaWriter(os, this);
_rootNode.generateStatic(out);
} finally {
os.close();
}
Path dependPath = javaPath.getParent().lookup(tail + ".depend");
StaticPage.writeDepend(dependPath, getDependList());
}
/**
* Generates the class header.
*
* @param doc the XML document representing the JSP page.
*/
protected void generateClassHeader(JspJavaWriter out)
throws IOException, JspParseException
{
out.println("/*");
out.println(" * JSP generated by " + VersionFactory.getFullVersion());
out.println(" */" );
out.println();
if (_pkg != null && ! _pkg.equals(""))
out.println("package " + _pkg + ";");
out.println("import javax.servlet.*;");
out.println("import javax.servlet.jsp.*;");
out.println("import javax.servlet.http.*;");
fillSingleTaglibImports();
ArrayList imports = _parseState.getImportList();
for (int i = 0; i < imports.size(); i++) {
String name = imports.get(i);
out.print("import ");
out.print(name);
out.println(";");
}
_parseState.addImport("javax.servlet.*");
_parseState.addImport("javax.servlet.jsp.*");
_parseState.addImport("javax.servlet.http.*");
_parseState.addImport("java.lang.*");
out.println();
if (_parseState.getExtends() != null) {
//if (extendsLocation != null)
//setLocation(extendsLocation.srcFilename, extendsLocation.srcLine, 0);
out.print("public class ");
out.print(_className);
out.print(" extends ");
out.print(_parseState.getExtends().getName());
out.print(" implements com.caucho.jsp.CauchoPage");
if (! _parseState.isThreadSafe())
out.print(", javax.servlet.SingleThreadModel");
} else {
out.print("public class ");
out.print(_className);
out.print(" extends com.caucho.jsp.JavaPage");
if (! _parseState.isThreadSafe())
out.print(" implements javax.servlet.SingleThreadModel");
}
out.println();
out.println("{");
out.pushDepth();
out.println("private static final java.util.HashMap _jsp_functionMap = new java.util.HashMap();");
out.println("private boolean _caucho_isDead;");
out.println("private boolean _caucho_isNotModified;");
out.println("private com.caucho.jsp.PageManager _jsp_pageManager;");
//out.println("private com.caucho.util.FreeList _jsp_freeState = new com.caucho.util.FreeList(8);");
String info = _parseState.getInfo();
if (info != null) {
out.println();
out.print("public String getServletInfo() { return \"");
for (int i = 0; i < info.length(); i++) {
char ch = info.charAt(i);
if (ch == '\\')
out.print("\\\\");
else if (ch == '\n')
out.print("\\n");
else if (ch == '\r')
out.print("\\r");
else if (ch == '"')
out.print("\\\"");
else
out.print(ch);
}
out.println("\"; }");
}
for (int i = 0; i < _declarations.size(); i++) {
JspDeclaration decl = _declarations.get(i);
out.println();
decl.generateDeclaration(out);
}
}
/**
* As a convenience, when the Tag isn't in a package, import
* it automatically.
*/
protected void fillSingleTaglibImports()
throws JspParseException
{
/*
Iterator iter = _taglibMap.values().iterator();
while (iter.hasNext()) {
Taglib taglib = iter.next();
if (taglib == null)
continue;
ArrayList singleTags = taglib.getSingleTagClassNames();
for (int i = 0; i < singleTags.size(); i++) {
String className = singleTags.get(i);
_parseState.addImport(className);
}
}
*/
}
/**
* Prints the _jspService header
*/
protected void generatePageHeader(JspJavaWriter out) throws Exception
{
out.println("");
out.println("public void");
out.println("_jspService(javax.servlet.http.HttpServletRequest request,");
out.println(" javax.servlet.http.HttpServletResponse response)");
out.println(" throws java.io.IOException, javax.servlet.ServletException");
out.println("{");
out.pushDepth();
// static shouldn't start up a session
boolean isSession = _parseState.isSession() && ! _rootNode.isStatic();
if (isSession) {
out.println("javax.servlet.http.HttpSession session = request.getSession(true);");
}
out.println("com.caucho.server.webapp.WebApp _jsp_application = _caucho_getApplication();");
out.print("com.caucho.jsp.PageContextImpl pageContext = _jsp_pageManager.allocatePageContext(");
out.print("this, _jsp_application, request, response, ");
if (_parseState.getErrorPage() == null)
out.print("null");
else
out.print("\"" + _parseState.getErrorPage() + "\"");
out.print(", ");
if (isSession) {
out.print("session");
}
else
out.print("null");
out.print(", ");
out.print(_parseState.getBuffer());
out.print(", ");
out.print(_parseState.isAutoFlush());
out.print(", ");
out.print(_parseState.isPrintNullAsBlank());
out.println(");");
out.println();
if (_rootNode.hasCustomTag()) {
out.println("TagState _jsp_state = new TagState();");
// out.println("TagState _jsp_state = _jsp_freeState.allocate();");
//out.println("if (_jsp_state == null)");
//out.println(" _jsp_state = new TagState();");
}
else
out.println("TagState _jsp_state = null;");
out.println();
out.println("try {");
out.pushDepth();
if (isSession)
out.println("_jspService(request, response, pageContext, _jsp_application, session, _jsp_state);");
else
out.println("_jspService(request, response, pageContext, _jsp_application, _jsp_state);");
out.popDepth();
out.println("} catch (java.lang.Throwable _jsp_e) {");
out.println(" pageContext.handlePageException(_jsp_e);");
out.println("} finally {");
out.pushDepth();
if (_rootNode.hasCustomTag()) {
//out.println("if (! _jsp_freeState.free(_jsp_state))");
out.println("_jsp_state.release();");
}
out.println("_jsp_pageManager.freePageContext(pageContext);");
// close finally
out.popDepth();
out.println("}");
out.popDepth();
out.println("}");
// impl
out.println("");
out.println("private void");
out.println("_jspService(javax.servlet.http.HttpServletRequest request,");
out.println(" javax.servlet.http.HttpServletResponse response,");
out.println(" com.caucho.jsp.PageContextImpl pageContext,");
out.println(" javax.servlet.ServletContext application,");
if (isSession) {
out.println(" javax.servlet.http.HttpSession session,");
}
out.println(" TagState _jsp_state)");
out.println(" throws Throwable");
out.println("{");
out.pushDepth();
out.println("javax.servlet.jsp.JspWriter out = pageContext.getOut();");
out.println("final javax.el.ELContext _jsp_env = pageContext.getELContext();");
out.println("javax.servlet.ServletConfig config = getServletConfig();");
out.println("javax.servlet.Servlet page = this;");
if (_parseState.isErrorPage()) {
out.println("java.lang.Throwable exception = ((com.caucho.jsp.PageContextImpl) pageContext).getThrowable();");
}
out.println("javax.servlet.jsp.tagext.JspTag _jsp_parent_tag = null;");
out.println("com.caucho.jsp.PageContextImpl _jsp_parentContext = pageContext;");
generateContentType(out);
_rootNode.generatePrologue(out);
out.println();
}
/**
* Generates the content type of the page.
*/
private void generateContentType(JspJavaWriter out)
throws IOException
{
String encoding = Encoding.getMimeName(_parseState.getCharEncoding());
if (encoding == null && isXml())
encoding = "UTF-8";
if (encoding == null && _parseState.getJspPropertyGroup() != null)
encoding = _parseState.getJspPropertyGroup().getCharacterEncoding();
if (encoding == null)
encoding = Encoding.getMimeName(_parseState.getPageEncoding());
// jsp/1co7
/*
if (encoding == null)
encoding = Encoding.getMimeName(CharacterEncoding.getLocalEncoding());
*/
/*
if ("ISO-8859-1".equals(encoding))
encoding = null;
*/
String contentType = _parseState.getContentType();
out.print("response.setContentType(\"");
if (contentType != null)
out.printJavaString(contentType);
else if (isXml())
out.print("text/xml");
else
out.print("text/html");
out.println("\");");
if (contentType != null && contentType.equals("text/html"))
contentType = null;
if (encoding == null) {
// server/1204
}
else if (contentType == null || contentType.indexOf("charset") < 0) {
out.print("response.setCharacterEncoding(\"");
if (encoding != null)
out.printJavaString(encoding);
else
out.printJavaString("iso-8859-1");
out.println("\");");
}
// jsp/1e0k, #4007
/*
if (encoding != null) {
out.println("String _caucho_request_character_encoding = request.getCharacterEncoding();");
out.println("if (_caucho_request_character_encoding == null || \"\".equals(_caucho_request_character_encoding))");
out.pushDepth();
out.println("request.setCharacterEncoding(\"" + encoding + "\");");
out.popDepth();
}
*/
}
public int addString(String string)
{
int index = _strings.get(string);
if (index < 0) {
index = _strings.size();
_strings.put(string, index);
}
return index;
}
/**
* Saves a bean's class for later introspection.
*
* @param id the bean id
* @param typeName the bean's type
*/
public void addBeanClass(String id, String typeName)
throws Exception
{
if (_classes == null)
_classes = new HashMap>();
try {
if (_primitives.get(typeName) != null)
return;
Class> cl = getBeanClass(typeName);
if (cl == null)
throw error(L.l("Can't find class '{0}'",
typeName));
_classes.put(id, cl);
} catch (CompileClassNotFound e) {
log.log(Level.WARNING, e.toString(), e);
throw error(L.l("Can't find class '{0}'\n{1}",
typeName, e.getMessage()));
} catch (ClassNotFoundException e) {
log.log(Level.FINE, e.toString(), e);
throw error(L.l("Can't find class '{0}'", typeName));
}
}
/**
* Loads a bean based on the class name.
*/
public Class> getBeanClass(String typeName)
throws ClassNotFoundException
{
// Generics parameters should be removed and only the base class loaded
int p = typeName.indexOf('<');
if (p > 0)
return getBeanClass(typeName.substring(0, p));
// Arrays need to use Array.newInstance(cl, new int[]);
p = typeName.indexOf('[');
if (p > 0) {
Class> cl = getBeanClass(typeName.substring(0, p));
int count = 0;
for (int i = 0; i < typeName.length(); i++)
if (typeName.charAt(i) == '[')
count++;
int []dims = new int[count];
for (int i = 0; i < count; i++)
dims[i] = 1;
Object obj = Array.newInstance(cl, dims);
return obj.getClass();
}
Class> cl = loadBeanClass(typeName);
if (cl != null)
return cl;
// Inner classes need rewriting Foo.Bar -> Foo$Bar
int i = typeName.lastIndexOf('.');
for (; i >= 0; i = typeName.lastIndexOf('.', i - 1)) {
String mainClassName = typeName.substring(0, i);
Class> mainClass = loadBeanClass(mainClassName);
typeName = mainClassName + '$' + typeName.substring(i + 1);
if (mainClass != null)
return getBeanClass(typeName);
}
return null;
}
Class> loadBeanClass(String typeName)
{
Class> cl = _primitiveClasses.get(typeName);
if (cl != null)
return cl;
try {
return CauchoSystem.loadClass(typeName);
} catch (CompileClassNotFound e) {
log.log(Level.FINE, e.toString(), e);
} catch (ClassNotFoundException e) {
}
// qualified names don't use the imports
if (typeName.indexOf('.') >= 0)
return null;
ArrayList imports = _parseState.getImportList();
for (int i = 0; i < imports.size(); i++) {
String pkg = imports.get(i);
String fullName = null;
if (pkg.endsWith("." + typeName))
fullName = pkg;
else if (pkg.endsWith(".*"))
fullName = pkg.substring(0, pkg.length() - 1) + typeName;
else
continue;
try {
return CauchoSystem.loadClass(fullName);
} catch (CompileClassNotFound e) {
log.log(Level.WARNING, e.toString(), e);
} catch (ClassNotFoundException e) {
}
}
return null;
}
public Class> getClass(String id)
{
if (_classes == null)
return null;
return _classes.get(id);
}
protected void generatePageFooter(JspJavaWriter out) throws IOException
{
out.popDepth();
out.println("}");
}
/**
* Completes the generated class: closing the main method, generating
* the dependencies and generating the constant strings.
*
* @param doc the XML document representing the JSP page.
*/
protected void generateClassFooter(JspJavaWriter out) throws Exception
{
// fragments must be first because they may create others.
generateFragments(out);
generateDepends(out);
generateTags(out);
_rootNode.generateClassEpilogue(out);
//generateTags may still add to _value(Expr|Method)List
generateInit(out);
generateExprs(out);
generateXPath(out);
generateConstantStrings(out);
out.popDepth();
out.println("}");
}
public int addFragment(JspFragmentNode node)
{
int index = _fragmentList.indexOf(node);
if (index >= 0)
return index;
_fragmentList.add(node);
return _fragmentList.size() - 1;
}
public JspFragmentNode getFragment(int index)
{
return _fragmentList.get(index);
}
public com.caucho.el.Expr genExpr(String value)
throws JspParseException, ELException
{
JspELParser parser = new JspELParser(_elContext, value);
return parser.parse();
}
/**
* Adds an expression to the expression list.
*/
public int addExpr(String expr)
throws JspParseException, ELException
{
genExpr(expr);
int index = _exprList.indexOf(expr);
if (index >= 0)
return index;
index = _exprList.size();
_exprList.add(expr);
return index;
}
/**
* Adds an expression to the expression list.
*/
public int addValueExpr(String value, String type)
throws JspParseException, ELException
{
JspELParser parser = new JspELParser(_elContext, value);
com.caucho.el.Expr expr = parser.parse();
int index = _valueExprList.indexOf(expr);
if (index >= 0)
return index;
index = _valueExprList.size();
try {
if (type == null || type.equals(""))
_valueExprList.add(new ValueExpr(value, expr, Object.class));
else {
Class> cl = getBeanClass(type);
if (cl == null)
throw new NullPointerException(type);
_valueExprList.add(new ValueExpr(value, expr, cl));
}
} catch (ClassNotFoundException e) {
throw new ELException(e);
}
return index;
}
/**
* Adds an expression to the expression list.
*/
public int addMethodExpr(String value, String sigString)
throws JspParseException, ELException
{
JspELParser parser = new JspELParser(_elContext, value);
com.caucho.el.Expr expr = parser.parse();
Class> retType = void.class;
Class> []args = new Class[0];
try {
if (sigString != null && ! sigString.equals("")) {
Signature sig = new Signature(sigString);
String []types = sig.getParameterTypes();
args = new Class[types.length];
for (int i = 0; i < types.length; i++) {
args[i] = getBeanClass(types[i]);
}
if (sig.getReturnType() == null)
throw error(L.l("deferredMethod signature '{0}' needs a return type.",
sigString));
retType = getBeanClass(sig.getReturnType());
}
} catch (ClassNotFoundException e) {
throw new ELException(e);
}
MethodExpr methodExpr = new MethodExpr(value, expr, args, retType);
if (expr.isLiteralText()) {
if (void.class.equals(retType)) {
// jsp/18v3
throw error(L.l("deferredMethod with string literal '{0}' cannot return void '{1}'",
value, sigString));
}
Object testValue = expr.getValue(null);
try {
Expr.coerceToType(testValue, retType);
} catch (Exception e) {
// jsp/18v4 (tck)
throw error(L.l("string literal '{0}' can't return type '{1}'",
value, sigString));
}
}
int index = _methodExprList.indexOf(methodExpr);
if (index >= 0)
return index;
index = _methodExprList.size();
_methodExprList.add(methodExpr);
return index;
}
/**
* out.Prints the expressions
*/
private void generateExprs(JspJavaWriter out) throws IOException
{
for (int i = 0; i < _exprList.size(); i++) {
// String expr = _exprList.get(i);
out.println("private static com.caucho.el.Expr _caucho_expr_" + i + ";");
/*
out.print(" ");
expr.printCreate(out.getWriteStream());
out.println(";");
*/
}
for (int i = 0; i < _valueExprList.size(); i++) {
/*
ValueExpr expr = _valueExprList.get(i);
String exprType = "ObjectValueExpression";
Class> retType = expr.getReturnType();
if (String.class.equals(retType))
exprType = "StringValueExpression";
else if (Byte.class.equals(retType)
|| byte.class.equals(retType))
exprType = "ByteValueExpression";
else if (Short.class.equals(retType)
|| short.class.equals(retType))
exprType = "ShortValueExpression";
else if (Integer.class.equals(retType)
|| int.class.equals(retType))
exprType = "IntegerValueExpression";
else if (Long.class.equals(retType)
|| long.class.equals(retType))
exprType = "LongValueExpression";
else if (Float.class.equals(retType)
|| long.class.equals(retType))
exprType = "FloatValueExpression";
else if (Double.class.equals(retType)
|| double.class.equals(retType))
exprType = "DoubleValueExpression";
else if (Boolean.class.equals(retType)
|| boolean.class.equals(retType))
exprType = "BooleanValueExpression";
else if (Character.class.equals(retType)
|| char.class.equals(retType))
exprType = "CharacterValueExpression";
else if (BigInteger.class.equals(retType))
exprType = "BigIntegerValueExpression";
else if (BigDecimal.class.equals(retType))
exprType = "BigDecimalValueExpression";
*/
out.println("private static javax.el.ValueExpression _caucho_value_expr_" + i + ";");
}
for (int i = 0; i < _methodExprList.size(); i++) {
out.println("private static javax.el.MethodExpression _caucho_method_expr_" + i + ";");
}
}
/**
* Adds an expression to the expression list.
*/
public String addXPathExpr(String value, NamespaceContext ns)
throws JspParseException, XPathParseException
{
return addXPathExpr(XPath.parseExpr(value, ns));
}
/**
* Adds an expression to the expression list.
*/
public String addXPathExpr(com.caucho.xpath.Expr expr)
throws JspParseException
{
int index = _xpathExprList.indexOf(expr);
if (index >= 0)
return "_caucho_xpath_" + index;
index = _xpathExprList.size();
_xpathExprList.add(expr);
return "_caucho_xpath_" + index;
}
/**
* out.Prints the expressions
*/
private void generateXPath(JspJavaWriter out) throws IOException
{
if (_xpathExprList.size() == 0)
return;
for (int i = 0; i < _xpathExprList.size(); i++) {
out.println("private static com.caucho.xpath.Expr _caucho_xpath_" + i + ";");
}
out.println("static {");
out.pushDepth();
out.println("try {");
out.pushDepth();
for (int i = 0; i < _xpathExprList.size(); i++) {
com.caucho.xpath.Expr expr = _xpathExprList.get(i);
out.print("_caucho_xpath_" + i + " =");
out.println(" com.caucho.xpath.XPath.parseExpr(\"" + expr + "\");");
}
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" e.printStackTrace();");
out.println("}");
out.popDepth();
out.println("}");
}
/**
* out.Prints the fragments
*/
private void generateTags(JspJavaWriter out) throws Exception
{
out.println();
out.println("final static class TagState {");
out.pushDepth();
_rootNode.generateTagState(out);
for (JspFragmentNode frag : _fragmentList) {
frag.generateTagState(out);
}
out.println();
out.println("void release()");
out.println("{");
out.pushDepth();
_rootNode.generateTagRelease(out);
for (JspFragmentNode frag : _fragmentList) {
frag.generateTagRelease(out);
}
/*
for (int i = 0; i < _topTag.size(); i++) {
TagInstance tag = _topTag.get(i);
if (tag.getTagClass() == null) {
}
else if (Tag.class.isAssignableFrom(tag.getTagClass())) {
out.println("if (" + tag.getId() + " != null)");
out.println(" " + tag.getId() + ".release();");
}
}
*/
out.popDepth();
out.println("}"); // release
out.popDepth();
out.println("}"); // TagState
}
/**
* out.Prints the fragments
*/
private void generateFragments(JspJavaWriter out) throws Exception
{
boolean hasFragment = false;
/*
for (int i = 0; i < _fragmentList.size(); i++) {
JspFragmentNode node = _fragmentList.get(i);
if (node.isStatic()) {
}
else
hasFragment = true;
}
if (! hasFragment)
return;
*/
Collections.sort(_fragmentList, new FragmentComparator());
for (int i = 0; i < _fragmentList.size(); i++) {
JspFragmentNode frag = _fragmentList.get(i);
if (frag.isValueFragment()) {
// jsp/1cje
frag.generateValueMethod(out);
}
else {
generateNonValueFragment(out, frag, frag.getFragmentCode());
}
}
}
private void generateNonValueFragment(JspJavaWriter out,
JspFragmentNode frag,
int id)
throws Exception
{
out.println();
out.println("_CauchoFragment_" + id + " createFragment_" + id + "(_CauchoFragment_" + id + " frag,");
out.println(" javax.servlet.jsp.JspContext _jsp_parentContext,");
out.println(" com.caucho.jsp.PageContextImpl pageContext,");
out.println(" javax.servlet.jsp.tagext.JspTag parent,");
out.println(" javax.servlet.jsp.tagext.JspFragment jspBody,");
out.println(" TagState _jsp_state,");
out.println(" com.caucho.jsp.PageManager _jsp_pageManager)");
out.println("{");
out.pushDepth();
out.println("if (frag == null) {");
out.println(" frag = new _CauchoFragment_" + id + "(_jsp_parentContext,");
out.println(" pageContext, parent, jspBody, _jsp_state,");
out.println(" _jsp_pageManager);");
out.println("}");
out.println();
out.println();
out.println("return frag;");
out.popDepth();
out.println("}");
out.println("public class _CauchoFragment_" + id + " extends com.caucho.jsp.JspFragmentSupport {");
out.pushDepth();
// out.println("private int _frag_code;");
out.println("private TagState _jsp_state;");
out.println("_CauchoFragment_" + id + "(");
out.println(" javax.servlet.jsp.JspContext _jsp_parentContext,");
out.println(" com.caucho.jsp.PageContextImpl pageContext,");
out.println(" javax.servlet.jsp.tagext.JspTag parent,");
out.println(" javax.servlet.jsp.tagext.JspFragment jspBody,");
out.println(" TagState _jsp_state,");
out.println(" com.caucho.jsp.PageManager _jsp_pageManager)");
out.println("{");
out.pushDepth();
// out.println("this._frag_code = code;");
out.println("this._jsp_parentContext = _jsp_parentContext;");
out.println("this.pageContext = pageContext;");
out.println("this._jsp_env = pageContext.getELContext();");
out.println("this._jsp_parent_tag = parent;");
out.println("this._jspBody = jspBody;");
out.println("this._jsp_state = _jsp_state;");
out.println("this._jsp_pageManager = _jsp_pageManager;");
out.popDepth();
out.println("}");
generateNonValueFragment(out, frag);
// frag.generateValueMethod(out);
/*
out.println();
out.println("protected void _jsp_invoke(JspWriter out)");
out.println(" throws Throwable");
out.println("{");
out.pushDepth();
out.popDepth();
out.println("}");
*/
out.popDepth();
out.println("}");
}
private void generateNonValueFragment(JspJavaWriter out,
JspFragmentNode frag)
throws Exception
{
out.println();
// out.println("private void " + frag.getFragmentName() + "(JspWriter out)");
out.println("protected void _jsp_invoke(JspWriter out)");
out.println(" throws Throwable");
out.println("{");
out.pushDepth();
HashSet oldDeclaredVariables = _declaredVariables;
_declaredVariables = new HashSet();
try {
if (frag.hasScripting()) {
generateScriptingVariables(out);
}
frag.generatePrologueChildren(out);
frag.generate(out);
} finally {
_declaredVariables = oldDeclaredVariables;
}
out.popDepth();
out.println("}");
}
private void generateScriptingVariables(JspJavaWriter out) throws IOException
{
// jsp/103j
out.println("HttpServletRequest request = this.pageContext.getRequest();");
out.println("HttpServletResponse response = this.pageContext.getResponse();");
out.println("ServletContext application = this.pageContext.getApplication();");
out.println("PageContext jspContext = this.pageContext;");
}
/**
* Generates the dependency methods. Since we can't assume the
* underlying class is Page when the JSP page uses "extends"
* each JSP page needs to generate this code.
*/
private void generateDepends(JspJavaWriter out) throws IOException
{
out.println();
// out.println("private com.caucho.java.LineMap _caucho_line_map;");
out.println("private com.caucho.make.DependencyContainer _caucho_depends");
out.println(" = new com.caucho.make.DependencyContainer();");
if (_isCacheable && ! _isUncacheable)
out.println("private java.util.ArrayList _caucho_cacheDepends = new java.util.ArrayList();");
out.println();
out.println("public java.util.ArrayList _caucho_getDependList()");
out.println("{");
out.println(" return _caucho_depends.getDependencies();");
out.println("}");
out.println();
out.println("public void _caucho_addDepend(com.caucho.vfs.PersistentDependency depend)");
out.println("{");
out.pushDepth();
if (_parseState.getExtends() == null)
out.println("super._caucho_addDepend(depend);");
// out.println(" com.caucho.jsp.JavaPage.addDepend(_caucho_depends, depend);");
out.println("_caucho_depends.add(depend);");
out.popDepth();
out.println("}");
out.println();
// out.println("@Override");
out.println("protected void _caucho_setNeverModified(boolean isNotModified)");
out.println("{");
// out.println(" super._caucho_setNeverModified(isNotModified);");
out.println(" _caucho_isNotModified = true;");
out.println("}");
out.println();
out.println("public boolean _caucho_isModified()");
out.println("{");
out.pushDepth();
out.println("if (_caucho_isDead)");
out.println(" return true;");
out.println();
out.println("if (_caucho_isNotModified)");
out.println(" return false;");
out.println();
out.println("if (com.caucho.server.util.CauchoSystem.getVersionId() != " +
CauchoSystem.getVersionId() + "L)");
out.println(" return true;");
out.println();
ArrayList depends;
depends = new ArrayList();
depends.addAll(_parseState.getDependList());
for (int i = 0; i < _depends.size(); i++) {
PersistentDependency depend = _depends.get(i);
if (! depends.contains(depend))
depends.add(depend);
}
if (_alwaysModified)
out.println("return true;");
else if (depends.size() == 0)
out.println("return false;");
else {
out.println("return _caucho_depends.isModified();");
/*
out.println("for (int i = _caucho_depends.size() - 1; i >= 0; i--) {");
out.pushDepth();
out.println("com.caucho.vfs.Dependency depend;");
out.println("depend = (com.caucho.vfs.Dependency) _caucho_depends.get(i);");
out.println("if (depend.isModified()) {");
out.println(" return true;");
out.println("}");
out.popDepth();
out.println("}");
out.println("return false;");
*/
}
out.popDepth();
out.println("}");
if (_rootNode.isStatic() && CauchoSystem.isTest())
out.println("private static long _caucho_lastModified = com.caucho.util.CurrentTime.getCurrentTime();");
out.println();
out.println("public long _caucho_lastModified()");
out.println("{");
out.pushDepth();
/*
if (! _isCacheable || _isUncacheable)
out.println("return 0;");
else {
out.println("return com.caucho.jsp.Page.calculateLastModified(_caucho_depends, _caucho_cacheDepends);");
}
*/
if (! isGenerateStatic()) {
out.println("return 0;");
}
else if (CauchoSystem.isTest()) {
out.println("return _caucho_lastModified;");
}
else {
out.println("long lastModified = 0;");
/*
out.println("for (int i = _caucho_depends.size() - 1; i >= 0; i--) {");
out.pushDepth();
out.println("Object oDepend = _caucho_depends.get(i);");
out.println("if (oDepend instanceof com.caucho.vfs.Depend) {");
out.println(" com.caucho.vfs.Depend depend = (com.caucho.vfs.Depend) oDepend;");
out.println(" if (lastModified < depend.getLastModified())");
out.println(" lastModified = depend.getLastModified();");
out.println("}");
out.popDepth();
out.println("}");
*/
out.println();
out.println("return lastModified;");
}
out.popDepth();
out.println("}");
/*
out.println();
out.println("public com.caucho.java.LineMap _caucho_getLineMap()");
out.println("{");
out.pushDepth();
out.println("return _caucho_line_map;");
out.popDepth();
out.println("}");
*/
if (_parseState.getExtends() == null && ! _parseState.isTag()) {
out.println();
out.println("public void destroy()");
out.println("{");
out.pushDepth();
out.println(" _caucho_isDead = true;");
out.println(" super.destroy();");
out.println("TagState tagState;");
//out.println("while ((tagState = _jsp_freeState.allocate()) != null)");
//out.println(" tagState.release();");
out.popDepth();
out.println("}");
}
if (_parseState.getExtends() != null && ! _parseState.isTag()) {
out.println();
out.println("public com.caucho.server.webapp.WebApp _caucho_getApplication()");
out.println("{");
out.pushDepth();
out.println(" return (com.caucho.server.webapp.WebApp) getServletConfig().getServletContext();");
out.popDepth();
out.println("}");
}
printDependInit(out, depends);
generateInject(out);
}
private boolean isGenerateStatic()
{
// #2548
return false;
/*
return (_rootNode.isStatic()
&& ! _parseState.isTag()
&& _parseState.getExtends() == null);
*/
}
/**
* Generates the normal init.
*/
private void generateInit(JspJavaWriter out)
throws IOException
{
out.println();
out.println("public java.util.HashMap _caucho_getFunctionMap()");
out.println("{");
out.pushDepth();
out.println("return _jsp_functionMap;");
out.popDepth();
out.println("}");
if (isTag())
out.println("static boolean _jsp_isTagInit;");
out.println();
out.println("public void caucho_init(ServletConfig config)");
out.println("{");
out.pushDepth();
if (isTag()) {
out.println("if (_jsp_isTagInit)");
out.println(" return;");
out.println("_jsp_isTagInit = true;");
}
out.println("try {");
out.pushDepth();
out.println("com.caucho.server.webapp.WebApp webApp");
out.println(" = (com.caucho.server.webapp.WebApp) config.getServletContext();");
if (! isTag()) {
out.println("init(config);");
}
out.println("if (com.caucho.jsp.JspManager.getCheckInterval() >= 0)");
out.println(" _caucho_depends.setCheckInterval(com.caucho.jsp.JspManager.getCheckInterval());");
out.println("_jsp_pageManager = webApp.getJspApplicationContext().getPageManager();");
out.println("com.caucho.jsp.TaglibManager manager = webApp.getJspApplicationContext().getTaglibManager();");
for (Taglib taglib : _tagLibraryList) {
out.print("manager.addTaglibFunctions(_jsp_functionMap, \"");
out.printJavaString(taglib.getPrefixString());
out.print("\", \"");
out.printJavaString(taglib.getURI());
out.println("\");");
}
if (! isTag())
out.println("com.caucho.jsp.PageContextImpl pageContext = new com.caucho.jsp.InitPageContextImpl(webApp, this);");
else
out.println("com.caucho.jsp.PageContextImpl pageContext = new com.caucho.jsp.InitPageContextImpl(webApp, _caucho_getFunctionMap());");
for (int i = 0; i < _exprList.size(); i++) {
String expr = _exprList.get(i);
out.print("_caucho_expr_" + i + " = com.caucho.jsp.JspUtil.createExpr(pageContext.getELContext(), \"");
out.printJavaString(expr);
out.println("\");");
}
for (int i = 0; i < _valueExprList.size(); i++) {
ValueExpr expr = _valueExprList.get(i);
out.print("_caucho_value_expr_" + i + " = com.caucho.jsp.JspUtil.createValueExpression(pageContext.getELContext(), ");
out.printClass(expr.getReturnType());
out.print(".class, \"");
out.printJavaString(expr.getExpressionString());
out.println("\");");
}
for (int i = 0; i < _methodExprList.size(); i++) {
MethodExpr expr = _methodExprList.get(i);
out.print("_caucho_method_expr_" + i + " = com.caucho.jsp.JspUtil.createMethodExpression(pageContext.getELContext(), \"");
out.printJavaString(expr.getExprString());
out.print("\", ");
if (expr.getReturnType() != null) {
out.printClass(expr.getReturnType());
out.print(".class");
}
else
out.print("String.class");
out.print(", new Class[] {");
Class> []args = expr.getArgs();
if (args != null) {
for (int j = 0; j < args.length; j++) {
if (j != 0)
out.print(", ");
out.printClass(args[j]);
out.print(".class");
}
}
out.println("});");
}
for (String tagClass : _tagFileClassList) {
out.println("new " + tagClass + "().caucho_init(config);");
}
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" throw com.caucho.config.ConfigException.create(e);");
out.println("}");
out.popDepth();
out.println("}");
}
/**
* Prints the initialization methods to track dependencies.
*/
private void printDependInit(JspJavaWriter out,
ArrayList depends)
throws IOException
{
out.println();
out.println("public void init(com.caucho.vfs.Path appDir)");
out.println(" throws javax.servlet.ServletException");
out.println("{");
out.pushDepth();
if (_ideHack) {
out.println("_jsp_init_strings();");
}
out.println("com.caucho.vfs.Path resinHome = com.caucho.server.util.CauchoSystem.getResinHome();");
out.println("com.caucho.vfs.MergePath mergePath = new com.caucho.vfs.MergePath();");
out.println("mergePath.addMergePath(appDir);");
out.println("mergePath.addMergePath(resinHome);");
out.println("com.caucho.loader.DynamicClassLoader loader;");
out.println("loader = (com.caucho.loader.DynamicClassLoader) getClass().getClassLoader();");
out.println("String resourcePath = loader.getResourcePathSpecificFirst();");
out.println("mergePath.addClassPath(resourcePath);");
MergePath classPath = new MergePath();
classPath.addClassPath();
/* XXX: the order shouldn't matter in this situation
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader instanceof DynamicClassLoader) {
DynamicClassLoader loader = (DynamicClassLoader) classLoader;
String resourcePath = loader.getResourcePathSpecificFirst();
classPath.addClassPath(resourcePath);
}
*/
String srcName = _filename;
if (srcName == null)
srcName = "foo";
out.println("com.caucho.vfs.Depend depend;");
Path appDir = getAppDir();
for (int i = 0; i < depends.size(); i++) {
PersistentDependency dependency = depends.get(i);
if (dependency instanceof Depend) {
Depend depend = (Depend) dependency;
if (depend.getPath().isDirectory())
continue;
out.print("depend = new com.caucho.vfs.Depend(");
printPathDir(out, depend, depend.getPath().getFullPath(),
appDir, classPath);
out.println(", " + depend.getDigest() + "L, " +
_requireSource + ");");
// out.println("com.caucho.jsp.JavaPage.addDepend(_caucho_depends, depend);");
out.println("_caucho_depends.add(depend);");
out.println("loader.addDependency(depend);");
}
else {
/*
out.print("com.caucho.jsp.JavaPage.addDepend(_caucho_depends, ");
out.print(dependency.getJavaCreateString());
out.println(");");
*/
out.print("_caucho_depends.add(");
out.print(dependency.getJavaCreateString());
out.println(");");
}
}
if (_isCacheable && ! _isUncacheable) {
for (int i = 0; i < _cacheDepends.size(); i++) {
Depend depend = _cacheDepends.get(i);
if (depend.getPath().isDirectory())
continue;
out.print("depend = new com.caucho.vfs.Depend(");
printPathDir(out, depend, depend.getPath().getFullPath(),
appDir, classPath);
out.println(", \"" + depend.getDigest() + "\", " +
_requireSource + ");");
out.println("_caucho_cacheDepends.add((Object) depend);");
}
}
out.popDepth();
out.println("}");
}
/**
* Prints an expression to lookup the path directory
*/
private void printPathDir(JspJavaWriter out, Depend depend,
String path, Path appDir, MergePath classPath)
throws IOException
{
String resinHome = CauchoSystem.getResinHome().getFullPath();
String prefix = getAppDir().getFullPath();
if (prefix.length() > 1 && ! prefix.endsWith("/"))
prefix = prefix + "/";
if (path.startsWith(prefix)) {
String subPath = path.substring(prefix.length());
Path appPathTest = appDir.lookup(subPath);
if (appPathTest.getCrc64() == depend.getPath().getCrc64()) {
out.print("appDir.lookup(\"");
out.printJavaString(subPath);
out.print("\")");
return;
}
}
ArrayList classPathList = classPath.getMergePaths();
for (int i = 0; i < classPathList.size(); i++) {
Path dir = classPathList.get(i);
prefix = dir.getFullPath();
if (! prefix.endsWith("/"))
prefix = prefix + "/";
if (prefix.equals("/"))
continue;
else if (path.startsWith(prefix)) {
String tail = path.substring(prefix.length());
if (tail.startsWith("/"))
tail = tail.substring(1);
Path cpPath = appDir.lookup("classpath:" + tail);
if (depend.getPath().getCrc64() == cpPath.getCrc64()) {
out.print("appDir.lookup(\"classpath:");
out.printJavaString(tail);
out.print("\")");
return;
}
else {
out.print("appDir.lookup(\"");
out.printJavaString(depend.getPath().getURL());
out.print("\")");
return;
}
}
}
if (path.startsWith(resinHome + "/")) {
path = path.substring(resinHome.length() + 1);
out.print("mergePath.lookup(\"");
out.printJavaString(path);
out.print("\")");
}
else {
out.print("mergePath.lookup(\"");
out.printJavaString(depend.getPath().getURL());
out.print("\")");
}
}
/**
* Prints the tag injection.
*/
private void generateInject(JspJavaWriter out) throws IOException
{
if (_topTag == null || ! _topTag.hasChildren())
return;
Iterator iter = _topTag.iterator();
while (iter.hasNext()) {
TagInstance tag = iter.next();
if (tag != null)
generateTagInjectDecl(out, tag);
}
out.println();
out.println("static {");
out.pushDepth();
out.println("try {");
out.pushDepth();
iter = _topTag.iterator();
while (iter.hasNext()) {
TagInstance tag = iter.next();
if (tag != null)
generateTagInject(out, tag);
}
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" e.printStackTrace();");
out.println(" throw new RuntimeException(e);");
out.println("}");
out.popDepth();
out.println("}");
}
/**
* Prints the tag injection.
*/
private void generateTagInjectDecl(JspJavaWriter out, TagInstance tag)
throws IOException
{
/*
if (tag.getAnalyzedTag() != null
&& tag.getAnalyzedTag().getHasInjection()) {
out.println("private static com.caucho.config.j2ee.InjectProgram _jsp_inject_" + tag.getId() + ";");
}*/
Iterator iter = tag.iterator();
while (iter.hasNext()) {
TagInstance child = iter.next();
generateTagInjectDecl(out, child);
}
}
/**
* Prints the tag injection.
*/
private void generateTagInject(JspJavaWriter out, TagInstance tag)
throws IOException
{/*
if (tag.getAnalyzedTag() != null
&& tag.getAnalyzedTag().getHasInjection()) {
out.print("_jsp_inject_" + tag.getId() + " = ");
out.println("com.caucho.config.inject.InjectManager.create().getReference("
+ tag.getTagClass().getName() + ".class);");
}*/
Iterator iter = tag.iterator();
while (iter.hasNext()) {
TagInstance child = iter.next();
generateTagInject(out, child);
}
}
private void generateConstantStrings(JspJavaWriter out)
throws IOException
{
if (_strings.size() == 0) {
return;
}
out.println();
Iterator> iter = _strings.iterator();
while (iter.hasNext()) {
Object key = iter.next();
int j = _strings.get(key);
if (_ideHack)
out.println("private final char []_jsp_string" + j + ";");
else
out.println("private final static char []_jsp_string" + j + ";");
}
if (_ideHack) {
out.println("private void _jsp_init_strings() {");
out.pushDepth();
}
else {
out.println("static {");
out.pushDepth();
}
String enc = out.getWriteStream().getJavaEncoding();
if (enc == null || enc.equals("ISO8859_1"))
enc = null;
if (_config.isStaticEncoding() && enc != null) {
out.println("try {");
out.pushDepth();
}
iter = _strings.iterator();
while (iter.hasNext()) {
String text = (String) iter.next();
int j = _strings.get(text);
out.print("_jsp_string" + j + " = \"");
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '\n':
out.print("\\n");
break;
case '\r':
out.print("\\r");
break;
case '"':
out.print("\\\"");
break;
case '\\':
out.print("\\\\");
break;
default:
out.print(ch);
}
}
out.println("\".toCharArray();");
}
if (_config.isStaticEncoding() && enc != null) {
out.popDepth();
out.println("} catch (java.io.UnsupportedEncodingException e) {");
out.println(" e.printStackTrace();");
out.println("}");
}
out.popDepth();
out.println("}");
}
/**
* Opens a write stream to the *.java file we're generating.
*
* @param path work directory path
*
* @return the write stream
*/
WriteStream openWriteStream()
throws IOException
{
Path javaPath = getGeneratedPath();
WriteStream os = javaPath.openWrite();
os.setEncoding("JAVA");
return os;
}
Path getGeneratedPath()
throws IOException
{
// String name = _pkg + "." + _className;
Path dir = getJspCompiler().getClassDir().lookup(_workPath);
Path javaPath = dir.lookup(_className + ".java");
try {
javaPath.getParent().mkdirs();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
return javaPath;
}
@Override
public int uniqueId()
{
return _uniqueId++;
}
public int generateJspId()
{
return _jspId++;
}
protected void addImport(String name)
{
}
boolean hasTags()
{
// size() == 1 is the jsp: tags.
return _tagManager.hasTags();
}
/**
* Returns the tag with the given qname.
*/
public TagInfo getTag(QName qname)
throws JspParseException
{
return _tagManager.getTag(qname);
}
/**
* Returns the tag with the given qname.
*/
public Class> getTagClass(QName qname)
throws Exception
{
return _tagManager.getTagClass(qname);
}
public Taglib addTaglib(QName qname)
throws JspParseException
{
return _tagManager.addTaglib(qname);
}
public String getSourceLines(Path source, int errorLine)
{
if (source == null || errorLine < 1)
return "";
boolean hasLine = false;
StringBuilder sb = new StringBuilder("\n\n");
ReadStream is = null;
try {
is = source.openRead();
is.setEncoding(_parseState.getPageEncoding());
int line = 0;
String text;
while ((text = is.readLine()) != null) {
line++;
if (errorLine - 2 <= line && line <= errorLine + 2) {
sb.append(line);
sb.append(": ");
sb.append(text);
sb.append("\n");
hasLine = true;
}
}
} catch (IOException e) {
log.log(Level.FINER, e.toString(), e);
} finally {
is.close();
}
if (hasLine)
return sb.toString();
else
return "";
}
public JspParseException error(String message)
{
JspParseException e = new JspParseException(message);
e.setErrorPage(_parseState.getErrorPage());
return e;
}
public JspParseException error(Exception e)
{
JspParseException exn = new JspParseException(e);
exn.setErrorPage(_parseState.getErrorPage());
return exn;
}
static class MethodExpr {
private String _exprString;
com.caucho.el.Expr _expr;
Class> []_args;
Class> _retType;
MethodExpr(String exprString,
com.caucho.el.Expr expr, Class> []args, Class> retType)
{
_exprString = exprString;
_expr = expr;
_args = args;
_retType = retType;
}
String getExprString()
{
return _exprString;
}
com.caucho.el.Expr getExpr()
{
return _expr;
}
Class> []getArgs()
{
return _args;
}
Class> getReturnType()
{
return _retType;
}
}
static class ValueExpr {
private String _exprString;
com.caucho.el.Expr _expr;
Class> _retType;
ValueExpr(String exprString, com.caucho.el.Expr expr, Class> retType)
{
_exprString = exprString;
_expr = expr;
_retType = retType;
}
String getExpressionString()
{
return _exprString;
}
com.caucho.el.Expr getExpr()
{
return _expr;
}
Class> getReturnType()
{
return _retType;
}
}
static class FragmentComparator implements Comparator {
@Override
public int compare(JspFragmentNode a, JspFragmentNode b)
{
return getDepth(a) - getDepth(b);
}
private int getDepth(JspNode node)
{
int depth = 0;
for (; node != null; node = node.getParent()) {
depth++;
}
return depth;
}
}
static {
_primitives = new HashMap();
_primitives.put("boolean", "boolean");
_primitives.put("byte", "byte");
_primitives.put("short", "short");
_primitives.put("char", "char");
_primitives.put("int", "int");
_primitives.put("long", "long");
_primitives.put("float", "float");
_primitives.put("double", "double");
_primitiveClasses = new HashMap>();
_primitiveClasses.put("boolean", boolean.class);
_primitiveClasses.put("byte", byte.class);
_primitiveClasses.put("short", short.class);
_primitiveClasses.put("char", char.class);
_primitiveClasses.put("int", int.class);
_primitiveClasses.put("long", long.class);
_primitiveClasses.put("float", float.class);
_primitiveClasses.put("double", double.class);
_primitiveClasses.put("void", void.class);
}
}