0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.jsp.java;
0031:
0032: import com.caucho.config.types.Signature;
0033: import com.caucho.java.CompileClassNotFound;
0034: import com.caucho.java.LineMap;
0035: import com.caucho.java.LineMapWriter;
0036: import com.caucho.jsp.*;
0037: import com.caucho.jsp.cfg.TldFunction;
0038: import com.caucho.jsp.el.JspELParser;
0039: import com.caucho.loader.DynamicClassLoader;
0040: import com.caucho.log.Log;
0041: import com.caucho.make.ClassDependency;
0042: import com.caucho.server.util.CauchoSystem;
0043: import com.caucho.util.IntMap;
0044: import com.caucho.util.L10N;
0045: import com.caucho.i18n.*;
0046: import com.caucho.vfs.*;
0047: import com.caucho.xml.QName;
0048: import com.caucho.xpath.NamespaceContext;
0049: import com.caucho.xpath.XPath;
0050: import com.caucho.xpath.XPathParseException;
0051:
0052: import javax.el.ELContext;
0053: import javax.servlet.jsp.el.ELException;
0054: import javax.servlet.jsp.tagext.PageData;
0055: import javax.servlet.jsp.tagext.Tag;
0056: import javax.servlet.jsp.tagext.TagInfo;
0057: import javax.servlet.jsp.tagext.TagLibraryValidator;
0058: import javax.servlet.jsp.tagext.ValidationMessage;
0059: import java.io.IOException;
0060: import java.lang.reflect.Array;
0061: import java.lang.reflect.Method;
0062: import java.math.BigDecimal;
0063: import java.math.BigInteger;
0064: import java.util.ArrayList;
0065: import java.util.HashMap;
0066: import java.util.HashSet;
0067: import java.util.Iterator;
0068: import java.util.logging.Level;
0069: import java.util.logging.Logger;
0070:
0071: /**
0072: * Generates JSP code. JavaGenerator, JavaScriptGenerator, and
0073: * StaticGenerator specialize the JspGenerator for language-specific
0074: * requirements.
0075: *
0076: * <p>JspParser parses the JSP file into an XML-DOM tree. JspGenerator
0077: * generates code from that tree.
0078: */
0079: public class JavaJspGenerator extends JspGenerator {
0080: static final L10N L = new L10N(JavaJspGenerator.class);
0081: static final Logger log = Log.open(JavaJspGenerator.class);
0082:
0083: static final String IE_CLSID = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
0084: 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";
0085: static final String NS_URL = "http://java.sun.com/products/plugin/";
0086:
0087: static HashMap<String, Class> _primitiveClasses;
0088: static HashMap<String, String> _primitives;
0089:
0090: protected JspNode _rootNode;
0091:
0092: protected ParseState _parseState;
0093:
0094: /*
0095: * Variables storing the JSP directives.
0096: */
0097: protected boolean _ideHack = false;
0098:
0099: /*
0100: * Variables controlling caching
0101: * isUncacheable overrides isCacheable.
0102: */
0103: protected boolean _isCacheable;
0104: protected boolean _isUncacheable;
0105: protected ArrayList<Depend> _cacheDepends = new ArrayList<Depend>();
0106:
0107: // dependencies for the source file itself
0108: protected ArrayList<PersistentDependency> _depends = new ArrayList<PersistentDependency>();
0109:
0110: long _lastModified; // XXX: obsolete?
0111:
0112: protected TagInstance _topTag;
0113: protected int _tagId;
0114:
0115: // XXX: needed in combination with XTP
0116: boolean _alwaysModified;
0117:
0118: protected ParseTagManager _tagManager;
0119:
0120: protected JspPageConfig _config = new JspPageConfig();
0121:
0122: protected String _fullClassName;
0123: protected String _className;
0124: private HashMap<String, Class> _classes;
0125: private ClassLoader _parentLoader;
0126:
0127: private HashSet<String> _declaredVariables = new HashSet<String>();
0128:
0129: private String _filename;
0130:
0131: private final JspGenELContext _elContext;
0132:
0133: private HashMap<String, Method> _elFunctionMap = new HashMap<String, Method>();
0134:
0135: private ArrayList<Taglib> _tagLibraryList = new ArrayList<Taglib>();
0136:
0137: private ArrayList<String> _tagFileClassList = new ArrayList<String>();
0138:
0139: private PageData _pageData;
0140:
0141: protected IntMap _strings = new IntMap();
0142:
0143: private ArrayList<String> _exprList = new ArrayList<String>();
0144:
0145: private ArrayList<ValueExpr> _valueExprList = new ArrayList<ValueExpr>();
0146:
0147: private ArrayList<MethodExpr> _methodExprList = new ArrayList<MethodExpr>();
0148:
0149: private ArrayList<com.caucho.xpath.Expr> _xpathExprList = new ArrayList<com.caucho.xpath.Expr>();
0150:
0151: private ArrayList<JspFragmentNode> _fragmentList = new ArrayList<JspFragmentNode>();
0152:
0153: private String _workPath;
0154: private String _sourceName;
0155: protected String _pkg;
0156: private int _uniqueId = 0;
0157: private int _jspId = 1;
0158:
0159: private boolean _hasReleaseTag;
0160: private boolean _hasBundle = false;
0161: private boolean _hasBundlePrefix = false;
0162: private boolean _requireSource = false;
0163:
0164: private boolean _isOmitXmlDeclaration = false;
0165:
0166: private String _doctypeSystem;
0167: private String _doctypePublic;
0168: private String _doctypeRootElement;
0169:
0170: private boolean _isJsfPrologueInit;
0171:
0172: private boolean _isStatic = false;
0173:
0174: protected ArrayList<JspDeclaration> _declarations = new ArrayList<JspDeclaration>();
0175:
0176: public JavaJspGenerator(ParseTagManager tagManager) {
0177: _elContext = new JspGenELContext(this );
0178:
0179: _tagManager = tagManager;
0180:
0181: _topTag = new TagInstance(tagManager);
0182: }
0183:
0184: public TagInstance getRootTag() {
0185: return _topTag;
0186: }
0187:
0188: protected void setParseState(ParseState parseState) {
0189: _parseState = parseState;
0190: }
0191:
0192: public ParseState getParseState() {
0193: return _parseState;
0194: }
0195:
0196: public void setPageConfig(JspPageConfig pageConfig) {
0197: _config = pageConfig;
0198: }
0199:
0200: void setStaticEncoding(boolean staticEncoding) {
0201: _config.setStaticEncoding(staticEncoding);
0202: }
0203:
0204: void setRequireSource(boolean requireSource) {
0205: _requireSource = requireSource;
0206: }
0207:
0208: void setIdeHack(boolean ideHack) {
0209: _ideHack = ideHack;
0210: }
0211:
0212: String getPackagePrefix() {
0213: return "";
0214: }
0215:
0216: Path getAppDir() {
0217: return _jspCompiler.getAppDir();
0218: }
0219:
0220: /**
0221: * Returns true for XML.
0222: */
0223: boolean isXml() {
0224: // jsp/0362
0225: return _parseState.isXml();
0226: }
0227:
0228: /**
0229: * Returns true if the XML declaration should be set.
0230: */
0231: boolean isOmitXmlDeclaration() {
0232: return _isOmitXmlDeclaration;
0233: }
0234:
0235: /**
0236: * Returns true if the XML declaration should be set.
0237: */
0238: void setOmitXmlDeclaration(boolean omitXml) {
0239: _isOmitXmlDeclaration = omitXml;
0240: }
0241:
0242: /**
0243: * Sets the dtd system name
0244: */
0245: void setDoctypeSystem(String doctypeSystem) {
0246: _doctypeSystem = doctypeSystem;
0247: }
0248:
0249: /**
0250: * Gets the dtd system name
0251: */
0252: String getDoctypeSystem() {
0253: return _doctypeSystem;
0254: }
0255:
0256: /**
0257: * Sets the dtd public name
0258: */
0259: void setDoctypePublic(String doctypePublic) {
0260: _doctypePublic = doctypePublic;
0261: }
0262:
0263: /**
0264: * Gets the dtd public name
0265: */
0266: String getDoctypePublic() {
0267: return _doctypePublic;
0268: }
0269:
0270: /**
0271: * Gets the dtd root element name
0272: */
0273: void setDoctypeRootElement(String doctypeRootElement) {
0274: _doctypeRootElement = doctypeRootElement;
0275: }
0276:
0277: /**
0278: * Gets the dtd root element name
0279: */
0280: String getDoctypeRootElement() {
0281: return _doctypeRootElement;
0282: }
0283:
0284: /**
0285: * Returns the character encoding.
0286: */
0287: String getCharacterEncoding() {
0288: return _parseState.getCharEncoding();
0289: }
0290:
0291: Path getClassDir() {
0292: return _jspCompiler.getClassDir();
0293: }
0294:
0295: /**
0296: * Sets the root JSP node.
0297: */
0298: public void setRootNode(JspNode node) {
0299: _rootNode = node;
0300: }
0301:
0302: public JspPageConfig getConfig() {
0303: return _config;
0304: }
0305:
0306: public boolean isTag() {
0307: return false;
0308: }
0309:
0310: public void init() {
0311: _isOmitXmlDeclaration = !isXml();
0312: }
0313:
0314: public boolean hasScripting() {
0315: return _rootNode.hasScripting();
0316: }
0317:
0318: public boolean isJsfPrologueInit() {
0319: return _isJsfPrologueInit;
0320: }
0321:
0322: public void setJsfPrologueInit(boolean isInit) {
0323: _isJsfPrologueInit = isInit;
0324: }
0325:
0326: /**
0327: * Adds a taglib.
0328: */
0329: public void addTaglib(String prefix, String uri)
0330: throws JspParseException {
0331: addTaglib(prefix, uri, false);
0332: }
0333:
0334: /**
0335: * Adds a taglib.
0336: */
0337: public void addOptionalTaglib(String prefix, String uri)
0338: throws JspParseException {
0339: addTaglib(prefix, uri, true);
0340: }
0341:
0342: /**
0343: * Adds a taglib.
0344: */
0345: public Taglib addTaglib(String prefix, String uri,
0346: boolean isOptional) throws JspParseException {
0347: if (log.isLoggable(Level.FINEST))
0348: log.finest("taglib prefix=" + prefix + " uri:" + uri);
0349:
0350: Taglib taglib;
0351:
0352: try {
0353: taglib = _tagManager.addTaglib(prefix, uri);
0354: } catch (JspParseException e) {
0355: if (isOptional) {
0356: log.log(Level.FINE, e.toString(), e);
0357: return null;
0358: }
0359:
0360: throw e;
0361: }
0362:
0363: if (taglib == null && isOptional
0364: && !uri.startsWith("urn:jsptld:")
0365: && !uri.startsWith("urn:jsptagdir:"))
0366: return null;
0367:
0368: if (taglib == null) {
0369: throw error(L
0370: .l(
0371: "'{0}' has no matching taglib-uri. Taglibs specified with an absolute URI must either be:\n"
0372: + "1) specified in the web.xml\n"
0373: + "2) defined in a jar's .tld in META-INF\n"
0374: + "3) defined in a .tld in WEB-INF\n"
0375: + "4) predefined by Resin", uri));
0376: }
0377:
0378: taglib = addLibrary(taglib);
0379: ArrayList<TldFunction> functions = taglib.getFunctionList();
0380:
0381: for (int i = 0; i < functions.size(); i++) {
0382: TldFunction function = functions.get(i);
0383:
0384: String name = taglib.getPrefixString() + ":"
0385: + function.getName();
0386:
0387: _elFunctionMap.put(name, function.getMethod());
0388: }
0389:
0390: return taglib;
0391: }
0392:
0393: void addTagFileClass(String cl) {
0394: if ("com.caucho.jsp.java.JspTagFileSupport".equals(cl))
0395: throw new IllegalStateException();
0396:
0397: if (!_tagFileClassList.contains(cl))
0398: _tagFileClassList.add(cl);
0399: }
0400:
0401: private Taglib addLibrary(Taglib taglib) throws JspParseException {
0402: for (int i = 0; i < _tagLibraryList.size(); i++) {
0403: Taglib oldTaglib = _tagLibraryList.get(i);
0404:
0405: if (oldTaglib.getURI().equals(taglib.getURI()))
0406: return oldTaglib;
0407: }
0408:
0409: /*
0410: // taglib = taglib.copy();
0411:
0412: for (int i = 0; i < _tagLibraryList.size(); i++) {
0413: Taglib oldTaglib = _tagLibraryList.get(i);
0414:
0415: oldTaglib.addTaglib(taglib);
0416: taglib.addTaglib(oldTaglib);
0417: }
0418: */
0419:
0420: _tagLibraryList.add(taglib);
0421:
0422: return taglib;
0423: }
0424:
0425: Method resolveFunction(String prefix, String localName) {
0426: if (prefix.equals(""))
0427: return _elFunctionMap.get(localName);
0428: else
0429: return _elFunctionMap.get(prefix + ':' + localName);
0430: }
0431:
0432: /**
0433: * Adds a taglib.
0434: */
0435: public void addTaglibDir(String prefix, String tagdir)
0436: throws JspParseException {
0437: Taglib taglib = _tagManager.addTaglibDir(prefix, tagdir);
0438:
0439: ArrayList<TldFunction> functions = taglib.getFunctionList();
0440:
0441: for (int i = 0; i < functions.size(); i++) {
0442: TldFunction function = functions.get(i);
0443:
0444: String name = taglib.getPrefixString() + ":"
0445: + function.getName();
0446:
0447: _elFunctionMap.put(name, function.getMethod());
0448: }
0449: }
0450:
0451: /**
0452: * Returns true if the JSP compilation has produced a static file.
0453: */
0454: public boolean isStatic() {
0455: return _isStatic;
0456: }
0457:
0458: /**
0459: * Returns the page's XML view.
0460: */
0461: public PageData getPageData() throws IOException {
0462: if (_pageData != null)
0463: return _pageData;
0464:
0465: TempStream ts = new TempStream();
0466:
0467: ts.openWrite();
0468: WriteStream ws = new WriteStream(ts);
0469: ws.setEncoding("UTF-8");
0470:
0471: _rootNode.printXml(ws);
0472:
0473: ws.close();
0474:
0475: if (log.isLoggable(Level.FINER)) {
0476: StringBuilder sb = new StringBuilder();
0477: ReadStream is = ts.openReadAndSaveBuffer();
0478: int ch;
0479: while ((ch = is.readChar()) >= 0) {
0480: sb.append((char) ch);
0481: }
0482: is.close();
0483:
0484: log.finer("JSP[" + _fullClassName + "] " + sb);
0485: }
0486:
0487: _pageData = new QPageData(ts);
0488:
0489: return _pageData;
0490: }
0491:
0492: public ELContext getELContext() {
0493: return _elContext;
0494: }
0495:
0496: /**
0497: * Validates the JSP page.
0498: */
0499: public void validate() throws Exception {
0500: for (int i = 0; i < _tagLibraryList.size(); i++) {
0501: Taglib taglib = _tagLibraryList.get(i);
0502: TagLibraryValidator validator = taglib.getValidator();
0503:
0504: if (validator != null) {
0505: ValidationMessage[] messages;
0506:
0507: messages = validator.validate(taglib.getPrefixString(),
0508: taglib.getURI(), getPageData());
0509:
0510: if (messages != null && messages.length > 0) {
0511: StringBuilder message = new StringBuilder();
0512: for (int j = 0; j < messages.length; j++) {
0513: if (j != 0)
0514: message.append("\n");
0515: message.append(messages[j].getMessage());
0516: }
0517:
0518: throw _rootNode.error(message.toString());
0519: }
0520: }
0521: }
0522: }
0523:
0524: /**
0525: * Generates the JSP page.
0526: */
0527: protected void generate(Path path, String className)
0528: throws Exception {
0529: init(className);
0530:
0531: if (_jspCompilerInstance == null
0532: || !_jspCompilerInstance.isGeneratedSource())
0533: addDepend(path);
0534:
0535: _cacheDepends = new ArrayList<Depend>();
0536:
0537: _tagId = 1;
0538:
0539: if (_ideHack)
0540: _config.setStaticEncoding(false);
0541:
0542: // disable static pages. No longer needed and complicates
0543: // precompilation
0544: if (isGenerateStatic()
0545: && !_parseState.getJspPropertyGroup()
0546: .getStaticPageGeneratesClass()) {
0547: generateStatic();
0548: } else {
0549: WriteStream os = openWriteStream();
0550: JspJavaWriter out = new JspJavaWriter(os, this );
0551:
0552: try {
0553: generate(out);
0554: } finally {
0555: if (os != null)
0556: os.close();
0557: }
0558: }
0559:
0560: if (_lineMap != null) {
0561: Path javaPath = getGeneratedPath();
0562: String tail = javaPath.getTail();
0563: tail = tail + ".smap";
0564: WriteStream os = javaPath.getParent().lookup(tail)
0565: .openWrite();
0566:
0567: LineMapWriter writer = new LineMapWriter(os);
0568: writer.write(_lineMap);
0569: os.close();
0570: }
0571: }
0572:
0573: public void addDepend(Path path) {
0574: addDepend(path.createDepend());
0575: }
0576:
0577: /**
0578: * Adds a dependency based on a class.
0579: */
0580: public void addDepend(Class cl) {
0581: addDepend(new ClassDependency(cl));
0582: }
0583:
0584: public void addDepend(PersistentDependency depend) {
0585: if (!_depends.contains(depend))
0586: _depends.add(depend);
0587: }
0588:
0589: public ArrayList<PersistentDependency> getDependList() {
0590: return _depends;
0591: }
0592:
0593: public boolean isStaticEncoding() {
0594: return _config.isStaticEncoding();
0595: }
0596:
0597: public boolean getRecycleTags() {
0598: return _parseState.isRecycleTags();
0599: }
0600:
0601: /**
0602: * Adds a new Java declaration to the list.
0603: */
0604: public void addDeclaration(JspDeclaration decl) {
0605: _declarations.add(decl);
0606: }
0607:
0608: /**
0609: * Sets the taglib manager.
0610: */
0611: public void setTagManager(ParseTagManager tagManager) {
0612: _tagManager = tagManager;
0613: }
0614:
0615: /**
0616: * Returns the taglib manager.
0617: */
0618: public ParseTagManager getTagManager() {
0619: return _tagManager;
0620: }
0621:
0622: protected void init(String className) {
0623: _fullClassName = className;
0624: _className = className;
0625:
0626: String prefix = getPackagePrefix();
0627: if (prefix.endsWith("."))
0628: prefix = prefix.substring(0, prefix.length() - 1);
0629:
0630: int p = className.lastIndexOf('.');
0631: if (p > 0) {
0632: _pkg = className.substring(0, p);
0633: _className = className.substring(p + 1);
0634: } else
0635: _pkg = "";
0636:
0637: if (prefix.length() > 0 && _pkg.length() > 0)
0638: _pkg = prefix + "." + _pkg;
0639: else if (prefix.length() > 0)
0640: _pkg = prefix;
0641:
0642: _workPath = _pkg.replace('.', '/');
0643:
0644: _lineMap = new LineMap(className.replace('.', '/') + ".java");
0645: }
0646:
0647: /**
0648: * True if it's a declared variable.
0649: */
0650: public boolean isDeclared(String var) {
0651: return _declaredVariables.contains(var);
0652: }
0653:
0654: /**
0655: * Adds a declared variable.
0656: */
0657: public void addDeclared(String var) {
0658: _declaredVariables.add(var);
0659: }
0660:
0661: /**
0662: * Generates the Java code.
0663: */
0664: protected void generate(JspJavaWriter out) throws Exception {
0665: out.setLineMap(_lineMap);
0666:
0667: generateClassHeader(out);
0668:
0669: generatePageHeader(out);
0670:
0671: _rootNode.generate(out);
0672:
0673: generatePageFooter(out);
0674:
0675: // _rootNode.generateDeclaration(out);
0676:
0677: generateClassFooter(out);
0678: }
0679:
0680: /**
0681: * Generates a static file.
0682: */
0683: protected void generateStatic() throws Exception {
0684: _isStatic = true;
0685:
0686: Path javaPath = getGeneratedPath();
0687: String tail = javaPath.getTail();
0688: int p = tail.indexOf('.');
0689: tail = tail.substring(0, p);
0690:
0691: Path staticPath = javaPath.getParent().lookup(tail + ".static");
0692:
0693: WriteStream os = staticPath.openWrite();
0694: //os.setEncoding(_parseState.getCharEncoding());
0695: os.setEncoding("UTF-8");
0696:
0697: try {
0698: JspJavaWriter out = new JspJavaWriter(os, this );
0699:
0700: _rootNode.generateStatic(out);
0701: } finally {
0702: os.close();
0703: }
0704:
0705: Path dependPath = javaPath.getParent().lookup(tail + ".depend");
0706: StaticPage.writeDepend(dependPath, getDependList());
0707: }
0708:
0709: /**
0710: * Generates the class header.
0711: *
0712: * @param doc the XML document representing the JSP page.
0713: */
0714: protected void generateClassHeader(JspJavaWriter out)
0715: throws IOException, JspParseException {
0716: out.println("/*");
0717: out.println(" * JSP generated by "
0718: + com.caucho.Version.FULL_VERSION);
0719: out.println(" */");
0720: out.println();
0721:
0722: if (_pkg != null && !_pkg.equals(""))
0723: out.println("package " + _pkg + ";");
0724:
0725: out.println("import javax.servlet.*;");
0726: out.println("import javax.servlet.jsp.*;");
0727: out.println("import javax.servlet.http.*;");
0728:
0729: fillSingleTaglibImports();
0730:
0731: ArrayList<String> imports = _parseState.getImportList();
0732: for (int i = 0; i < imports.size(); i++) {
0733: String name = imports.get(i);
0734: out.print("import ");
0735: out.print(name);
0736: out.println(";");
0737: }
0738: _parseState.addImport("javax.servlet.*");
0739: _parseState.addImport("javax.servlet.jsp.*");
0740: _parseState.addImport("javax.servlet.http.*");
0741: _parseState.addImport("java.lang.*");
0742: out.println();
0743:
0744: if (_parseState.getExtends() != null) {
0745: //if (extendsLocation != null)
0746: //setLocation(extendsLocation.srcFilename, extendsLocation.srcLine, 0);
0747:
0748: out.print("public class ");
0749: out.print(_className);
0750: out.print(" extends ");
0751: out.print(_parseState.getExtends().getName());
0752: out.print(" implements com.caucho.jsp.CauchoPage");
0753: if (!_parseState.isThreadSafe())
0754: out.print(", javax.servlet.SingleThreadModel");
0755: } else {
0756: out.print("public class ");
0757: out.print(_className);
0758: out.print(" extends com.caucho.jsp.JavaPage");
0759: if (!_parseState.isThreadSafe())
0760: out
0761: .print(" implements javax.servlet.SingleThreadModel");
0762: }
0763:
0764: out.println();
0765: out.println("{");
0766: out.pushDepth();
0767:
0768: out
0769: .println("private static final java.util.HashMap<String,java.lang.reflect.Method> _jsp_functionMap = new java.util.HashMap<String,java.lang.reflect.Method>();");
0770:
0771: out.println("private boolean _caucho_isDead;");
0772:
0773: String info = _parseState.getInfo();
0774: if (info != null) {
0775: out.println();
0776: out.print("public String getServletInfo() { return \"");
0777: for (int i = 0; i < info.length(); i++) {
0778: char ch = info.charAt(i);
0779: if (ch == '\\')
0780: out.print("\\\\");
0781: else if (ch == '\n')
0782: out.print("\\n");
0783: else if (ch == '\r')
0784: out.print("\\r");
0785: else if (ch == '"')
0786: out.print("\\\"");
0787: else
0788: out.print(ch);
0789: }
0790: out.println("\"; }");
0791: }
0792:
0793: for (int i = 0; i < _declarations.size(); i++) {
0794: JspDeclaration decl = _declarations.get(i);
0795:
0796: out.println();
0797: decl.generateDeclaration(out);
0798: }
0799: }
0800:
0801: /**
0802: * As a convenience, when the Tag isn't in a package, import
0803: * it automatically.
0804: */
0805: protected void fillSingleTaglibImports() throws JspParseException {
0806: /*
0807: Iterator<Taglib> iter = _taglibMap.values().iterator();
0808:
0809: while (iter.hasNext()) {
0810: Taglib taglib = iter.next();
0811:
0812: if (taglib == null)
0813: continue;
0814:
0815: ArrayList<String> singleTags = taglib.getSingleTagClassNames();
0816:
0817: for (int i = 0; i < singleTags.size(); i++) {
0818: String className = singleTags.get(i);
0819:
0820: _parseState.addImport(className);
0821: }
0822: }
0823: */
0824: }
0825:
0826: /**
0827: * Prints the _jspService header
0828: */
0829: protected void generatePageHeader(JspJavaWriter out)
0830: throws Exception {
0831: out.println("");
0832: out.println("public void");
0833: out
0834: .println("_jspService(javax.servlet.http.HttpServletRequest request,");
0835: out
0836: .println(" javax.servlet.http.HttpServletResponse response)");
0837: out
0838: .println(" throws java.io.IOException, javax.servlet.ServletException");
0839: out.println("{");
0840: out.pushDepth();
0841:
0842: // static shouldn't start up a session
0843: boolean isSession = _parseState.isSession()
0844: && !_rootNode.isStatic();
0845:
0846: if (isSession) {
0847: out
0848: .println("javax.servlet.http.HttpSession session = request.getSession(true);");
0849: }
0850: out
0851: .println("com.caucho.server.webapp.WebApp _jsp_application = _caucho_getApplication();");
0852: out
0853: .println("javax.servlet.ServletContext application = _jsp_application;");
0854:
0855: out
0856: .print("com.caucho.jsp.PageContextImpl pageContext = com.caucho.jsp.QJspFactory.allocatePageContext(");
0857: out.print("this, _jsp_application, request, response, ");
0858: if (_parseState.getErrorPage() == null)
0859: out.print("null");
0860: else
0861: out.print("\"" + _parseState.getErrorPage() + "\"");
0862: out.print(", ");
0863: if (isSession) {
0864: out.print("session");
0865: } else
0866: out.print("null");
0867: out.print(", ");
0868: out.print(_parseState.getBuffer());
0869: out.print(", ");
0870: out.print(_parseState.isAutoFlush());
0871: out.print(", ");
0872: out.print(_parseState.isPrintNullAsBlank());
0873: out.println(");");
0874: out
0875: .println("javax.servlet.jsp.JspWriter out = pageContext.getOut();");
0876: out
0877: .println("final javax.el.ELContext _jsp_env = pageContext.getELContext();");
0878: out
0879: .println("javax.servlet.ServletConfig config = getServletConfig();");
0880: out.println("javax.servlet.Servlet page = this;");
0881: if (_parseState.isErrorPage()) {
0882: out
0883: .println("java.lang.Throwable exception = ((com.caucho.jsp.PageContextImpl) pageContext).getThrowable();");
0884: }
0885:
0886: generateContentType(out);
0887:
0888: /*
0889: for (int i = 0; i < _fragmentList.size(); i++) {
0890: JspNode node = _fragmentList.get(i);
0891:
0892: if (node.isStatic())
0893: out.println("com.caucho.jsp.StaticJspFragmentSupport _jsp_frag_" + i + " = null;");
0894: else
0895: out.println("_CauchoFragment _jsp_frag_" + i + " = null;");
0896: }
0897: */
0898:
0899: _rootNode.generatePrologue(out);
0900:
0901: out.println("try {");
0902: out.pushDepth();
0903: }
0904:
0905: /**
0906: * Generates the content type of the page.
0907: */
0908: private void generateContentType(JspJavaWriter out)
0909: throws IOException {
0910: String encoding = Encoding.getMimeName(_parseState
0911: .getCharEncoding());
0912:
0913: if (encoding == null)
0914: encoding = Encoding.getMimeName(_parseState
0915: .getPageEncoding());
0916:
0917: if (encoding == null)
0918: encoding = Encoding.getMimeName(CharacterEncoding
0919: .getLocalEncoding());
0920:
0921: /*
0922: if ("ISO-8859-1".equals(encoding))
0923: encoding = null;
0924: */
0925:
0926: String contentType = _parseState.getContentType();
0927: if (contentType != null && contentType.equals("text/html"))
0928: contentType = null;
0929:
0930: out.print("response.setContentType(\"");
0931: if (contentType == null)
0932: out.print("text/html");
0933: else {
0934: out.printJavaString(contentType);
0935: }
0936: out.println("\");");
0937:
0938: if (encoding == null && isXml())
0939: encoding = "UTF-8";
0940:
0941: if (encoding == null) {
0942: // server/1204
0943: } else if (contentType == null
0944: || contentType.indexOf("charset") < 0) {
0945: out.print("response.setCharacterEncoding(\"");
0946: if (encoding != null)
0947: out.printJavaString(encoding);
0948: else
0949: out.printJavaString("iso-8859-1");
0950: out.println("\");");
0951: }
0952:
0953: if (encoding != null)
0954: out.println("request.setCharacterEncoding(\"" + encoding
0955: + "\");");
0956: }
0957:
0958: private void printTry(JspJavaWriter out) throws IOException {
0959: out.println("try {");
0960: out.pushDepth();
0961: // out.println("_caucho_init_tags(pageContext, _jsp_tags);");
0962: }
0963:
0964: public int addString(String string) {
0965: int index = _strings.get(string);
0966: if (index < 0) {
0967: index = _strings.size();
0968: _strings.put(string, index);
0969: }
0970: return index;
0971: }
0972:
0973: /**
0974: * Saves a bean's class for later introspection.
0975: *
0976: * @param id the bean id
0977: * @param typeName the bean's type
0978: */
0979: public void addBeanClass(String id, String typeName)
0980: throws Exception {
0981: if (_classes == null)
0982: _classes = new HashMap<String, Class>();
0983:
0984: try {
0985: if (_primitives.get(typeName) != null)
0986: return;
0987:
0988: Class cl = getBeanClass(typeName);
0989:
0990: if (cl == null)
0991: throw error(L.l("Can't find class '{0}'", typeName));
0992:
0993: _classes.put(id, cl);
0994: } catch (CompileClassNotFound e) {
0995: log.log(Level.WARNING, e.toString(), e);
0996:
0997: throw error(L.l("Can't find class '{0}'\n{1}", typeName, e
0998: .getMessage()));
0999: } catch (ClassNotFoundException e) {
1000: log.log(Level.FINE, e.toString(), e);
1001:
1002: throw error(L.l("Can't find class '{0}'", typeName));
1003: }
1004: }
1005:
1006: /**
1007: * Loads a bean based on the class name.
1008: */
1009: public Class getBeanClass(String typeName)
1010: throws ClassNotFoundException {
1011: // Generics parameters should be removed and only the base class loaded
1012: int p = typeName.indexOf('<');
1013: if (p > 0)
1014: return getBeanClass(typeName.substring(0, p));
1015:
1016: // Arrays need to use Array.newInstance(cl, new int[]);
1017: p = typeName.indexOf('[');
1018: if (p > 0) {
1019: Class cl = getBeanClass(typeName.substring(0, p));
1020: int count = 0;
1021: for (int i = 0; i < typeName.length(); i++)
1022: if (typeName.charAt(i) == '[')
1023: count++;
1024: int[] dims = new int[count];
1025: for (int i = 0; i < count; i++)
1026: dims[i] = 1;
1027:
1028: Object obj = Array.newInstance(cl, dims);
1029:
1030: return obj.getClass();
1031: }
1032:
1033: Class cl = loadBeanClass(typeName);
1034: if (cl != null)
1035: return cl;
1036:
1037: // Inner classes need rewriting Foo.Bar -> Foo$Bar
1038: int i = typeName.lastIndexOf('.');
1039: for (; i >= 0; i = typeName.lastIndexOf('.', i - 1)) {
1040: String mainClassName = typeName.substring(0, i);
1041: Class mainClass = loadBeanClass(mainClassName);
1042:
1043: typeName = mainClassName + '$' + typeName.substring(i + 1);
1044:
1045: if (mainClass != null)
1046: return getBeanClass(typeName);
1047: }
1048:
1049: return null;
1050: }
1051:
1052: Class loadBeanClass(String typeName) {
1053: Class cl = _primitiveClasses.get(typeName);
1054:
1055: if (cl != null)
1056: return cl;
1057:
1058: try {
1059: return CauchoSystem.loadClass(typeName);
1060: } catch (CompileClassNotFound e) {
1061: log.log(Level.FINE, e.toString(), e);
1062: } catch (ClassNotFoundException e) {
1063: }
1064:
1065: // qualified names don't use the imports
1066: if (typeName.indexOf('.') >= 0)
1067: return null;
1068:
1069: ArrayList<String> imports = _parseState.getImportList();
1070: for (int i = 0; i < imports.size(); i++) {
1071: String pkg = imports.get(i);
1072: String fullName = null;
1073:
1074: if (pkg.endsWith("." + typeName))
1075: fullName = pkg;
1076: else if (pkg.endsWith(".*"))
1077: fullName = pkg.substring(0, pkg.length() - 1)
1078: + typeName;
1079: else
1080: continue;
1081:
1082: try {
1083: return CauchoSystem.loadClass(fullName);
1084: } catch (CompileClassNotFound e) {
1085: log.log(Level.WARNING, e.toString(), e);
1086: } catch (ClassNotFoundException e) {
1087: }
1088: }
1089:
1090: return null;
1091: }
1092:
1093: public Class getClass(String id) {
1094: if (_classes == null)
1095: return null;
1096:
1097: return _classes.get(id);
1098: }
1099:
1100: protected void generatePageFooter(JspJavaWriter out)
1101: throws IOException {
1102: out.popDepth();
1103: out.println("} catch (java.lang.Throwable _jsp_e) {");
1104: out.println(" pageContext.handlePageException(_jsp_e);");
1105: out.println("} finally {");
1106: out.pushDepth();
1107:
1108: for (int i = 0; i < _topTag.size(); i++) {
1109: TagInstance tag = _topTag.get(i);
1110:
1111: if (tag.getTagClass() == null) {
1112: } else if (Tag.class.isAssignableFrom(tag.getTagClass())) {
1113: out.println("if (" + tag.getId() + " != null)");
1114: out.println(" " + tag.getId() + ".release();");
1115: }
1116: }
1117:
1118: if (_hasReleaseTag) {
1119: out.popDepth();
1120: out.println("} finally {");
1121: out.pushDepth();
1122: }
1123:
1124: out
1125: .println("com.caucho.jsp.QJspFactory.freePageContext(pageContext);");
1126:
1127: if (_hasReleaseTag) {
1128: out.popDepth();
1129: out.println("}");
1130: }
1131:
1132: // close finally
1133: out.popDepth();
1134: out.println("}");
1135: out.popDepth();
1136: out.println("}");
1137: }
1138:
1139: /**
1140: * Completes the generated class: closing the main method, generating
1141: * the dependencies and generating the constant strings.
1142: *
1143: * @param doc the XML document representing the JSP page.
1144: */
1145: protected void generateClassFooter(JspJavaWriter out)
1146: throws Exception {
1147: // fragments must be first because they may create others.
1148: generateFragments(out);
1149:
1150: generateDepends(out);
1151:
1152: generateExprs(out);
1153: generateXPath(out);
1154: generateConstantStrings(out);
1155:
1156: out.popDepth();
1157: out.println("}");
1158: }
1159:
1160: public int addFragment(JspFragmentNode node) {
1161: int index = _fragmentList.indexOf(node);
1162:
1163: if (index >= 0)
1164: return index;
1165:
1166: _fragmentList.add(node);
1167:
1168: return _fragmentList.size() - 1;
1169: }
1170:
1171: public JspFragmentNode getFragment(int index) {
1172: return _fragmentList.get(index);
1173: }
1174:
1175: public com.caucho.el.Expr genExpr(String value)
1176: throws JspParseException, ELException {
1177: JspELParser parser = new JspELParser(_elContext, value);
1178:
1179: return parser.parse();
1180: }
1181:
1182: /**
1183: * Adds an expression to the expression list.
1184: */
1185: public int addExpr(String expr) throws JspParseException,
1186: ELException {
1187: genExpr(expr);
1188:
1189: int index = _exprList.indexOf(expr);
1190: if (index >= 0)
1191: return index;
1192:
1193: index = _exprList.size();
1194: _exprList.add(expr);
1195:
1196: return index;
1197: }
1198:
1199: /**
1200: * Adds an expression to the expression list.
1201: */
1202: public int addValueExpr(String value, String type)
1203: throws JspParseException, ELException {
1204: JspELParser parser = new JspELParser(_elContext, value);
1205:
1206: com.caucho.el.Expr expr = parser.parse();
1207:
1208: int index = _valueExprList.indexOf(expr);
1209: if (index >= 0)
1210: return index;
1211:
1212: index = _valueExprList.size();
1213:
1214: try {
1215: if (type == null || type.equals(""))
1216: _valueExprList.add(new ValueExpr(value, expr,
1217: Object.class));
1218: else {
1219: Class cl = getBeanClass(type);
1220:
1221: if (cl == null)
1222: throw new NullPointerException(type);
1223:
1224: _valueExprList.add(new ValueExpr(value, expr, cl));
1225: }
1226: } catch (ClassNotFoundException e) {
1227: throw new ELException(e);
1228: }
1229:
1230: return index;
1231: }
1232:
1233: /**
1234: * Adds an expression to the expression list.
1235: */
1236: public int addMethodExpr(String value, String sigString)
1237: throws JspParseException, ELException {
1238: JspELParser parser = new JspELParser(_elContext, value);
1239:
1240: com.caucho.el.Expr expr = parser.parse();
1241:
1242: Class retType = void.class;
1243: Class[] args = new Class[0];
1244:
1245: try {
1246: if (sigString != null && !sigString.equals("")) {
1247: Signature sig = new Signature(sigString);
1248:
1249: String[] types = sig.getParameterTypes();
1250:
1251: args = new Class[types.length];
1252:
1253: for (int i = 0; i < types.length; i++) {
1254: args[i] = getBeanClass(types[i]);
1255: }
1256:
1257: if (sig.getReturnType() == null)
1258: throw error(L
1259: .l(
1260: "deferredMethod signature '{0}' needs a return type.",
1261: sigString));
1262:
1263: retType = getBeanClass(sig.getReturnType());
1264: }
1265: } catch (ClassNotFoundException e) {
1266: throw new ELException(e);
1267: }
1268:
1269: MethodExpr methodExpr = new MethodExpr(value, expr, args,
1270: retType);
1271:
1272: int index = _methodExprList.indexOf(methodExpr);
1273: if (index >= 0)
1274: return index;
1275:
1276: index = _methodExprList.size();
1277: _methodExprList.add(methodExpr);
1278:
1279: return index;
1280: }
1281:
1282: /**
1283: * out.Prints the expressions
1284: */
1285: private void generateExprs(JspJavaWriter out) throws IOException {
1286: for (int i = 0; i < _exprList.size(); i++) {
1287: String expr = _exprList.get(i);
1288:
1289: out
1290: .println("private static com.caucho.el.Expr _caucho_expr_"
1291: + i + ";");
1292: /*
1293: out.print(" ");
1294: expr.printCreate(out.getWriteStream());
1295: out.println(";");
1296: */
1297: }
1298:
1299: for (int i = 0; i < _valueExprList.size(); i++) {
1300: ValueExpr expr = _valueExprList.get(i);
1301:
1302: String exprType = "ObjectValueExpression";
1303:
1304: Class retType = expr.getReturnType();
1305:
1306: if (String.class.equals(retType))
1307: exprType = "StringValueExpression";
1308: else if (Byte.class.equals(retType)
1309: || byte.class.equals(retType))
1310: exprType = "ByteValueExpression";
1311: else if (Short.class.equals(retType)
1312: || short.class.equals(retType))
1313: exprType = "ShortValueExpression";
1314: else if (Integer.class.equals(retType)
1315: || int.class.equals(retType))
1316: exprType = "IntegerValueExpression";
1317: else if (Long.class.equals(retType)
1318: || long.class.equals(retType))
1319: exprType = "LongValueExpression";
1320: else if (Float.class.equals(retType)
1321: || long.class.equals(retType))
1322: exprType = "FloatValueExpression";
1323: else if (Double.class.equals(retType)
1324: || double.class.equals(retType))
1325: exprType = "DoubleValueExpression";
1326: else if (Boolean.class.equals(retType)
1327: || boolean.class.equals(retType))
1328: exprType = "BooleanValueExpression";
1329: else if (Character.class.equals(retType)
1330: || char.class.equals(retType))
1331: exprType = "CharacterValueExpression";
1332: else if (BigInteger.class.equals(retType))
1333: exprType = "BigIntegerValueExpression";
1334: else if (BigDecimal.class.equals(retType))
1335: exprType = "BigDecimalValueExpression";
1336:
1337: out
1338: .println("private static javax.el.ValueExpression _caucho_value_expr_"
1339: + i + ";");
1340: }
1341:
1342: for (int i = 0; i < _methodExprList.size(); i++) {
1343: MethodExpr expr = _methodExprList.get(i);
1344:
1345: out
1346: .println("private static javax.el.MethodExpression _caucho_method_expr_"
1347: + i + ";");
1348: }
1349: }
1350:
1351: /**
1352: * Adds an expression to the expression list.
1353: */
1354: public String addXPathExpr(String value, NamespaceContext ns)
1355: throws JspParseException, XPathParseException {
1356: return addXPathExpr(XPath.parseExpr(value, ns));
1357: }
1358:
1359: /**
1360: * Adds an expression to the expression list.
1361: */
1362: public String addXPathExpr(com.caucho.xpath.Expr expr)
1363: throws JspParseException {
1364: int index = _xpathExprList.indexOf(expr);
1365: if (index >= 0)
1366: return "_caucho_xpath_" + index;
1367:
1368: index = _xpathExprList.size();
1369: _xpathExprList.add(expr);
1370:
1371: return "_caucho_xpath_" + index;
1372: }
1373:
1374: /**
1375: * out.Prints the expressions
1376: */
1377: private void generateXPath(JspJavaWriter out) throws IOException {
1378: if (_xpathExprList.size() == 0)
1379: return;
1380:
1381: for (int i = 0; i < _xpathExprList.size(); i++) {
1382: com.caucho.xpath.Expr expr = _xpathExprList.get(i);
1383:
1384: out
1385: .println("private static com.caucho.xpath.Expr _caucho_xpath_"
1386: + i + ";");
1387: }
1388:
1389: out.println("static {");
1390: out.pushDepth();
1391: out.println("try {");
1392: out.pushDepth();
1393:
1394: for (int i = 0; i < _xpathExprList.size(); i++) {
1395: com.caucho.xpath.Expr expr = _xpathExprList.get(i);
1396:
1397: out.print("_caucho_xpath_" + i + " =");
1398: out.println(" com.caucho.xpath.XPath.parseExpr(\"" + expr
1399: + "\");");
1400: }
1401:
1402: out.popDepth();
1403: out.println("} catch (Exception e) {");
1404: out.println(" e.printStackTrace();");
1405: out.println("}");
1406: out.popDepth();
1407: out.println("}");
1408: }
1409:
1410: /**
1411: * out.Prints the fragments
1412: */
1413: private void generateFragments(JspJavaWriter out) throws Exception {
1414: boolean hasFragment = false;
1415:
1416: for (int i = 0; i < _fragmentList.size(); i++) {
1417: JspFragmentNode node = _fragmentList.get(i);
1418:
1419: if (node.isStatic()) {
1420: }
1421: /*
1422: else if (node.isValueFragment()) {
1423: node.generateValueMethod(out);
1424: }
1425: */
1426: else
1427: hasFragment = true;
1428: }
1429:
1430: if (!hasFragment)
1431: return;
1432:
1433: out
1434: .println("public static class _CauchoFragment extends com.caucho.jsp.JspFragmentSupport {");
1435: out.pushDepth();
1436: out.println("private int _frag_code;");
1437:
1438: out.println();
1439: out
1440: .println("static _CauchoFragment create(_CauchoFragment frag, int code,");
1441: out
1442: .println(" com.caucho.jsp.PageContextImpl pageContext,");
1443: out
1444: .println(" javax.servlet.jsp.tagext.JspTag parent,");
1445: out
1446: .println(" javax.servlet.jsp.tagext.JspFragment jspBody)");
1447: out.println("{");
1448: out.pushDepth();
1449: out.println("if (frag == null)");
1450: out.println(" frag = new _CauchoFragment();");
1451: out.println();
1452: out.println("frag._frag_code = code;");
1453: out.println("frag.pageContext = pageContext;");
1454: out.println("frag._jsp_env = pageContext.getELContext();");
1455: out.println("frag._jsp_parent_tag = parent;");
1456: out.println("frag._jspBody = jspBody;");
1457: out.println();
1458: out.println("return frag;");
1459: out.popDepth();
1460: out.println("}");
1461:
1462: for (int i = 0; i < _fragmentList.size(); i++) {
1463: JspFragmentNode frag = _fragmentList.get(i);
1464:
1465: if (frag.isStatic())
1466: continue;
1467:
1468: if (frag.isValueFragment())
1469: frag.generateValueMethod(out);
1470: else {
1471: out.println();
1472: out.println("private void " + frag.getFragmentName()
1473: + "(JspWriter out)");
1474: out.println(" throws Throwable");
1475: out.println("{");
1476: out.pushDepth();
1477:
1478: HashSet<String> oldDeclaredVariables = _declaredVariables;
1479: _declaredVariables = new HashSet<String>();
1480: try {
1481: frag.generatePrologueChildren(out);
1482: frag.generate(out);
1483: } finally {
1484: _declaredVariables = oldDeclaredVariables;
1485: }
1486:
1487: out.popDepth();
1488: out.println("}");
1489: }
1490: }
1491:
1492: out.println();
1493: out.println("protected void _jsp_invoke(JspWriter out)");
1494: out.println(" throws Throwable");
1495: out.println("{");
1496: out.pushDepth();
1497: out.println("switch (_frag_code) {");
1498:
1499: for (int i = 0; i < _fragmentList.size(); i++) {
1500: JspFragmentNode frag = _fragmentList.get(i);
1501:
1502: if (frag.isStatic() || frag.isValueFragment())
1503: continue;
1504:
1505: out.println("case " + i + ":");
1506: out.println(" " + frag.getFragmentName() + "(out);");
1507: out.println(" break;");
1508: }
1509:
1510: out.println("}");
1511:
1512: out.popDepth();
1513: out.println("}");
1514:
1515: out.popDepth();
1516: out.println("}");
1517: }
1518:
1519: /**
1520: * Generates the dependency methods. Since we can't assume the
1521: * underlying class is Page when the JSP page uses "extends"
1522: * each JSP page needs to generate this code.
1523: */
1524: private void generateDepends(JspJavaWriter out) throws IOException {
1525: out.println();
1526: // out.println("private com.caucho.java.LineMap _caucho_line_map;");
1527: out
1528: .println("private java.util.ArrayList _caucho_depends = new java.util.ArrayList();");
1529: if (_isCacheable && !_isUncacheable)
1530: out
1531: .println("private java.util.ArrayList _caucho_cacheDepends = new java.util.ArrayList();");
1532:
1533: out.println();
1534: out
1535: .println("public java.util.ArrayList _caucho_getDependList()");
1536: out.println("{");
1537: out.println(" return _caucho_depends;");
1538: out.println("}");
1539:
1540: out.println();
1541: out
1542: .println("public void _caucho_addDepend(com.caucho.vfs.PersistentDependency depend)");
1543: out.println("{");
1544: if (_parseState.getExtends() == null)
1545: out.println(" super._caucho_addDepend(depend);");
1546: out
1547: .println(" com.caucho.jsp.JavaPage.addDepend(_caucho_depends, depend);");
1548: out.println("}");
1549:
1550: out.println();
1551: out.println("public boolean _caucho_isModified()");
1552: out.println("{");
1553: out.pushDepth();
1554: out.println("if (_caucho_isDead)");
1555: out.println(" return true;");
1556: out
1557: .println("if (com.caucho.server.util.CauchoSystem.getVersionId() != "
1558: + CauchoSystem.getVersionId() + "L)");
1559: out.println(" return true;");
1560:
1561: ArrayList<PersistentDependency> depends;
1562: depends = new ArrayList<PersistentDependency>();
1563: depends.addAll(_parseState.getDependList());
1564:
1565: for (int i = 0; i < _depends.size(); i++) {
1566: PersistentDependency depend = _depends.get(i);
1567:
1568: if (!depends.contains(depend))
1569: depends.add(depend);
1570: }
1571:
1572: if (_alwaysModified)
1573: out.println("return true;");
1574:
1575: else if (depends.size() == 0)
1576: out.println("return false;");
1577:
1578: else {
1579: out
1580: .println("for (int i = _caucho_depends.size() - 1; i >= 0; i--) {");
1581: out.pushDepth();
1582: out.println("com.caucho.vfs.Dependency depend;");
1583: out
1584: .println("depend = (com.caucho.vfs.Dependency) _caucho_depends.get(i);");
1585: out.println("if (depend.isModified())");
1586: out.println(" return true;");
1587: out.popDepth();
1588: out.println("}");
1589: out.println("return false;");
1590: }
1591:
1592: out.popDepth();
1593: out.println("}");
1594:
1595: if (_rootNode.isStatic() && CauchoSystem.isTest())
1596: out
1597: .println("private static long _caucho_lastModified = com.caucho.util.Alarm.getCurrentTime();");
1598:
1599: out.println();
1600: out.println("public long _caucho_lastModified()");
1601: out.println("{");
1602: out.pushDepth();
1603: /*
1604: if (! _isCacheable || _isUncacheable)
1605: out.println("return 0;");
1606: else {
1607: out.println("return com.caucho.jsp.Page.calculateLastModified(_caucho_depends, _caucho_cacheDepends);");
1608: }
1609: */
1610:
1611: if (!isGenerateStatic()) {
1612: out.println("return 0;");
1613: } else if (CauchoSystem.isTest()) {
1614: out.println("return _caucho_lastModified;");
1615: } else {
1616: out.println("long lastModified = 0;");
1617:
1618: out
1619: .println("for (int i = _caucho_depends.size() - 1; i >= 0; i--) {");
1620: out.pushDepth();
1621: out.println("Object oDepend = _caucho_depends.get(i);");
1622: out
1623: .println("if (oDepend instanceof com.caucho.vfs.Depend) {");
1624: out
1625: .println(" com.caucho.vfs.Depend depend = (com.caucho.vfs.Depend) oDepend;");
1626: out
1627: .println(" if (lastModified < depend.getLastModified())");
1628: out.println(" lastModified = depend.getLastModified();");
1629: out.println("}");
1630: out.popDepth();
1631: out.println("}");
1632:
1633: out.println();
1634: out.println("return lastModified;");
1635: }
1636:
1637: out.popDepth();
1638: out.println("}");
1639:
1640: /*
1641: out.println();
1642: out.println("public com.caucho.java.LineMap _caucho_getLineMap()");
1643: out.println("{");
1644: out.pushDepth();
1645: out.println("return _caucho_line_map;");
1646: out.popDepth();
1647: out.println("}");
1648: */
1649:
1650: generateInit(out);
1651:
1652: if (_parseState.getExtends() == null && !_parseState.isTag()) {
1653: out.println();
1654: out.println("public void destroy()");
1655: out.println("{");
1656: out.pushDepth();
1657: out.println(" _caucho_isDead = true;");
1658: out.println(" super.destroy();");
1659: out.popDepth();
1660: out.println("}");
1661: }
1662:
1663: if (_parseState.getExtends() != null && !_parseState.isTag()) {
1664: out.println();
1665: out
1666: .println("public com.caucho.server.webapp.WebApp _caucho_getApplication()");
1667: out.println("{");
1668: out.pushDepth();
1669: out
1670: .println(" return (com.caucho.server.webapp.WebApp) getServletConfig().getServletContext();");
1671: out.popDepth();
1672: out.println("}");
1673: }
1674:
1675: printDependInit(out, depends);
1676: generateInject(out);
1677: }
1678:
1679: private boolean isGenerateStatic() {
1680: return (_rootNode.isStatic() && !_parseState.isTag() && _parseState
1681: .getExtends() == null);
1682: }
1683:
1684: /**
1685: * Generates the normal init.
1686: */
1687: private void generateInit(JspJavaWriter out) throws IOException {
1688: out.println();
1689: out
1690: .println("public java.util.HashMap<String,java.lang.reflect.Method> _caucho_getFunctionMap()");
1691: out.println("{");
1692: out.pushDepth();
1693:
1694: out.println("return _jsp_functionMap;");
1695:
1696: out.popDepth();
1697: out.println("}");
1698:
1699: if (isTag())
1700: out.println("static boolean _jsp_isTagInit;");
1701:
1702: if (_parseState.getExtends() == null) {
1703: out.println();
1704: out.println("public void init(ServletConfig config)");
1705: out.println(" throws ServletException");
1706: out.println("{");
1707: out.pushDepth();
1708:
1709: if (isTag()) {
1710: out.println("if (_jsp_isTagInit)");
1711: out.println(" return;");
1712: out.println("_jsp_isTagInit = true;");
1713: }
1714:
1715: out.println("com.caucho.server.webapp.WebApp webApp");
1716: out
1717: .println(" = (com.caucho.server.webapp.WebApp) config.getServletContext();");
1718:
1719: if (!isTag())
1720: out.println("super.init(config);");
1721:
1722: out
1723: .println("com.caucho.jsp.TaglibManager manager = webApp.getJspApplicationContext().getTaglibManager();");
1724:
1725: for (Taglib taglib : _tagLibraryList) {
1726: out
1727: .print("manager.addTaglibFunctions(_jsp_functionMap, \"");
1728: out.printJavaString(taglib.getPrefixString());
1729: out.print("\", \"");
1730: out.printJavaString(taglib.getURI());
1731: out.println("\");");
1732: }
1733:
1734: if (!isTag())
1735: out
1736: .println("com.caucho.jsp.PageContextImpl pageContext = new com.caucho.jsp.PageContextImpl(webApp, this);");
1737: else
1738: out
1739: .println("com.caucho.jsp.PageContextImpl pageContext = new com.caucho.jsp.PageContextImpl(webApp, _caucho_getFunctionMap());");
1740:
1741: for (int i = 0; i < _exprList.size(); i++) {
1742: String expr = _exprList.get(i);
1743:
1744: out
1745: .print("_caucho_expr_"
1746: + i
1747: + " = com.caucho.jsp.JspUtil.createExpr(pageContext.getELContext(), \"");
1748: out.printJavaString(expr);
1749: out.println("\");");
1750: }
1751:
1752: for (int i = 0; i < _valueExprList.size(); i++) {
1753: ValueExpr expr = _valueExprList.get(i);
1754:
1755: out
1756: .print("_caucho_value_expr_"
1757: + i
1758: + " = com.caucho.jsp.JspUtil.createValueExpression(pageContext.getELContext(), ");
1759: out.printClass(expr.getReturnType());
1760: out.print(".class, \"");
1761: out.printJavaString(expr.getExpressionString());
1762: out.println("\");");
1763: }
1764:
1765: for (int i = 0; i < _methodExprList.size(); i++) {
1766: MethodExpr expr = _methodExprList.get(i);
1767:
1768: out
1769: .print("_caucho_method_expr_"
1770: + i
1771: + " = com.caucho.jsp.JspUtil.createMethodExpression(pageContext.getELContext(), \"");
1772: out.printJavaString(expr.getExprString());
1773: out.print("\", ");
1774: if (expr.getReturnType() != null) {
1775: out.printClass(expr.getReturnType());
1776: out.print(".class");
1777: } else
1778: out.print("String.class");
1779:
1780: out.print(", new Class[] {");
1781:
1782: Class[] args = expr.getArgs();
1783: if (args != null) {
1784: for (int j = 0; j < args.length; j++) {
1785: if (j != 0)
1786: out.print(", ");
1787:
1788: out.printClass(args[j]);
1789: out.print(".class");
1790: }
1791: }
1792:
1793: out.println("});");
1794: }
1795:
1796: for (String tagClass : _tagFileClassList) {
1797: out.println("new " + tagClass + "().init(config);");
1798: }
1799:
1800: out.popDepth();
1801: out.println("}");
1802: }
1803: }
1804:
1805: /**
1806: * Prints the initialization methods to track dependencies.
1807: */
1808: private void printDependInit(JspJavaWriter out,
1809: ArrayList<PersistentDependency> depends) throws IOException {
1810: out.println();
1811: out.println("public void init(com.caucho.vfs.Path appDir)");
1812: out.println(" throws javax.servlet.ServletException");
1813: out.println("{");
1814: out.pushDepth();
1815:
1816: if (_ideHack) {
1817: out.println("_jsp_init_strings();");
1818: }
1819:
1820: out
1821: .println("com.caucho.vfs.Path resinHome = com.caucho.server.util.CauchoSystem.getResinHome();");
1822: out
1823: .println("com.caucho.vfs.MergePath mergePath = new com.caucho.vfs.MergePath();");
1824: out.println("mergePath.addMergePath(appDir);");
1825: out.println("mergePath.addMergePath(resinHome);");
1826: out.println("com.caucho.loader.DynamicClassLoader loader;");
1827: out
1828: .println("loader = (com.caucho.loader.DynamicClassLoader) getClass().getClassLoader();");
1829: out
1830: .println("String resourcePath = loader.getResourcePathSpecificFirst();");
1831: out.println("mergePath.addClassPath(resourcePath);");
1832:
1833: MergePath classPath = new MergePath();
1834: classPath.addClassPath();
1835:
1836: /* XXX: the order shouldn't matter in this situation
1837: ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
1838: if (classLoader instanceof DynamicClassLoader) {
1839: DynamicClassLoader loader = (DynamicClassLoader) classLoader;
1840:
1841: String resourcePath = loader.getResourcePathSpecificFirst();
1842: classPath.addClassPath(resourcePath);
1843: }
1844: */
1845:
1846: String srcName = _filename;
1847: if (srcName == null)
1848: srcName = "foo";
1849:
1850: out.println("com.caucho.vfs.Depend depend;");
1851:
1852: Path appDir = getAppDir();
1853: for (int i = 0; i < depends.size(); i++) {
1854: PersistentDependency dependency = depends.get(i);
1855:
1856: if (dependency instanceof Depend) {
1857: Depend depend = (Depend) dependency;
1858:
1859: if (depend.getPath().isDirectory())
1860: continue;
1861:
1862: out.print("depend = new com.caucho.vfs.Depend(");
1863: printPathDir(out, depend, depend.getPath()
1864: .getFullPath(), appDir, classPath);
1865: out.println(", " + depend.getDigest() + "L, "
1866: + _requireSource + ");");
1867: out
1868: .println("com.caucho.jsp.JavaPage.addDepend(_caucho_depends, depend);");
1869: } else {
1870: out
1871: .print("com.caucho.jsp.JavaPage.addDepend(_caucho_depends, ");
1872: out.print(dependency.getJavaCreateString());
1873: out.println(");");
1874: }
1875: }
1876:
1877: if (_isCacheable && !_isUncacheable) {
1878: for (int i = 0; i < _cacheDepends.size(); i++) {
1879: Depend depend = _cacheDepends.get(i);
1880:
1881: if (depend.getPath().isDirectory())
1882: continue;
1883:
1884: out.print("depend = new com.caucho.vfs.Depend(");
1885: printPathDir(out, depend, depend.getPath()
1886: .getFullPath(), appDir, classPath);
1887: out.println(", \"" + depend.getDigest() + "\", "
1888: + _requireSource + ");");
1889: out
1890: .println("_caucho_cacheDepends.add((Object) depend);");
1891: }
1892: }
1893: out.popDepth();
1894: out.println("}");
1895: }
1896:
1897: /**
1898: * Prints an expression to lookup the path directory
1899: */
1900: private void printPathDir(JspJavaWriter out, Depend depend,
1901: String path, Path appDir, MergePath classPath)
1902: throws IOException {
1903: String resinHome = CauchoSystem.getResinHome().getFullPath();
1904:
1905: String prefix = getAppDir().getFullPath();
1906:
1907: if (prefix.length() > 1 && !prefix.endsWith("/"))
1908: prefix = prefix + "/";
1909:
1910: if (path.startsWith(prefix)) {
1911: path = path.substring(prefix.length());
1912: Path appPathTest = appDir.lookup(path);
1913:
1914: if (appPathTest.getCrc64() == depend.getPath().getCrc64()) {
1915: out.print("appDir.lookup(\"");
1916: out.printJavaString(path);
1917: out.print("\")");
1918: return;
1919: }
1920: }
1921:
1922: ArrayList<Path> classPathList = classPath.getMergePaths();
1923:
1924: for (int i = 0; i < classPathList.size(); i++) {
1925: Path dir = classPathList.get(i);
1926: prefix = dir.getFullPath();
1927:
1928: if (!prefix.endsWith("/"))
1929: prefix = prefix + "/";
1930:
1931: if (path.startsWith(prefix)) {
1932: String tail = path.substring(prefix.length());
1933:
1934: if (tail.startsWith("/"))
1935: tail = tail.substring(1);
1936:
1937: Path cpPath = appDir.lookup("classpath:" + tail);
1938:
1939: if (depend.getPath().getCrc64() == cpPath.getCrc64()) {
1940: out.print("appDir.lookup(\"classpath:");
1941: out.printJavaString(tail);
1942: out.print("\")");
1943: return;
1944: } else {
1945: out.print("appDir.lookup(\"");
1946: out.printJavaString(depend.getPath().getURL());
1947: out.print("\")");
1948: return;
1949: }
1950: }
1951: }
1952:
1953: if (path.startsWith(resinHome + "/")) {
1954: path = path.substring(resinHome.length() + 1);
1955: out.print("mergePath.lookup(\"");
1956: out.printJavaString(path);
1957: out.print("\")");
1958: }
1959: /* XXX: why? This messes up tests like server/0526
1960: else if (path.startsWith("/")) {
1961: out.print("mergePath.lookup(\"file:");
1962: out.printJavaString(path);
1963: out.print("\")");
1964: }
1965: */
1966: /*
1967: else if (classPath.lookup("./" + path).canRead()) {
1968: out.print("mergePath.lookup(\"./");
1969: out.printJavaString(path);
1970: out.print("\")");
1971: }
1972: */
1973: else {
1974: out.print("mergePath.lookup(\"");
1975: out.printJavaString(depend.getPath().getURL());
1976: out.print("\")");
1977: }
1978: }
1979:
1980: /**
1981: * Prints the tag injection.
1982: */
1983: private void generateInject(JspJavaWriter out) throws IOException {
1984: if (_topTag == null || !_topTag.hasChildren())
1985: return;
1986:
1987: Iterator<TagInstance> iter = _topTag.iterator();
1988: while (iter.hasNext()) {
1989: TagInstance tag = iter.next();
1990:
1991: if (tag != null)
1992: generateTagInjectDecl(out, tag);
1993: }
1994:
1995: out.println();
1996: out.println("static {");
1997: out.pushDepth();
1998: out.println("try {");
1999: out.pushDepth();
2000:
2001: iter = _topTag.iterator();
2002: while (iter.hasNext()) {
2003: TagInstance tag = iter.next();
2004:
2005: if (tag != null)
2006: generateTagInject(out, tag);
2007: }
2008:
2009: out.popDepth();
2010: out.println("} catch (Exception e) {");
2011: out.println(" e.printStackTrace();");
2012: out.println(" throw new RuntimeException(e);");
2013: out.println("}");
2014:
2015: out.popDepth();
2016: out.println("}");
2017: }
2018:
2019: /**
2020: * Prints the tag injection.
2021: */
2022: private void generateTagInjectDecl(JspJavaWriter out,
2023: TagInstance tag) throws IOException {
2024: if (tag.getAnalyzedTag() != null
2025: && tag.getAnalyzedTag().getHasInjection()) {
2026: out
2027: .println("private static com.caucho.config.j2ee.InjectProgram _jsp_inject_"
2028: + tag.getId() + ";");
2029: }
2030:
2031: Iterator<TagInstance> iter = tag.iterator();
2032: while (iter.hasNext()) {
2033: TagInstance child = iter.next();
2034:
2035: generateTagInjectDecl(out, child);
2036: }
2037: }
2038:
2039: /**
2040: * Prints the tag injection.
2041: */
2042: private void generateTagInject(JspJavaWriter out, TagInstance tag)
2043: throws IOException {
2044: if (tag.getAnalyzedTag() != null
2045: && tag.getAnalyzedTag().getHasInjection()) {
2046: out.print("_jsp_inject_" + tag.getId() + " = ");
2047: out
2048: .println("com.caucho.config.j2ee.InjectIntrospector.introspectProgram("
2049: + tag.getTagClass().getName() + ".class);");
2050: }
2051:
2052: Iterator<TagInstance> iter = tag.iterator();
2053: while (iter.hasNext()) {
2054: TagInstance child = iter.next();
2055:
2056: generateTagInject(out, child);
2057: }
2058: }
2059:
2060: private void generateConstantStrings(JspJavaWriter out)
2061: throws IOException {
2062: if (_strings.size() == 0)
2063: return;
2064:
2065: out.println();
2066: Iterator iter = _strings.iterator();
2067: while (iter.hasNext()) {
2068: Object key = iter.next();
2069: int j = _strings.get(key);
2070:
2071: if (_ideHack)
2072: out.println("private final char []_jsp_string" + j
2073: + ";");
2074: else
2075: out.println("private final static char []_jsp_string"
2076: + j + ";");
2077: }
2078:
2079: if (_ideHack) {
2080: out.println("private void _jsp_init_strings() {");
2081: out.pushDepth();
2082: } else {
2083: out.println("static {");
2084: out.pushDepth();
2085: }
2086:
2087: String enc = out.getWriteStream().getJavaEncoding();
2088: if (enc == null || enc.equals("ISO8859_1"))
2089: enc = null;
2090:
2091: if (_config.isStaticEncoding() && enc != null) {
2092: out.println("try {");
2093: out.pushDepth();
2094: }
2095:
2096: iter = _strings.iterator();
2097: while (iter.hasNext()) {
2098: String text = (String) iter.next();
2099: int j = _strings.get(text);
2100:
2101: out.print("_jsp_string" + j + " = \"");
2102:
2103: for (int i = 0; i < text.length(); i++) {
2104: char ch = text.charAt(i);
2105: switch (ch) {
2106: case '\n':
2107: out.print("\\n");
2108: break;
2109: case '\r':
2110: out.print("\\r");
2111: break;
2112: case '"':
2113: out.print("\\\"");
2114: break;
2115: case '\\':
2116: out.print("\\\\");
2117: break;
2118: default:
2119: out.print(ch);
2120: }
2121: }
2122:
2123: out.println("\".toCharArray();");
2124: }
2125: if (_config.isStaticEncoding() && enc != null) {
2126: out.popDepth();
2127: out
2128: .println("} catch (java.io.UnsupportedEncodingException e) {");
2129: out.println(" e.printStackTrace();");
2130: out.println("}");
2131: }
2132: out.popDepth();
2133: out.println("}");
2134: }
2135:
2136: /**
2137: * Opens a write stream to the *.java file we're generating.
2138: *
2139: * @param path work directory path
2140: *
2141: * @return the write stream
2142: */
2143: WriteStream openWriteStream() throws IOException {
2144: Path javaPath = getGeneratedPath();
2145:
2146: WriteStream os = javaPath.openWrite();
2147:
2148: os.setEncoding("JAVA");
2149:
2150: return os;
2151: }
2152:
2153: Path getGeneratedPath() throws IOException {
2154: String name = _pkg + "." + _className;
2155:
2156: Path dir = getJspCompiler().getClassDir().lookup(_workPath);
2157: Path javaPath = dir.lookup(_className + ".java");
2158:
2159: try {
2160: javaPath.getParent().mkdirs();
2161: } catch (Exception e) {
2162: log.log(Level.WARNING, e.toString(), e);
2163: }
2164:
2165: return javaPath;
2166: }
2167:
2168: public int uniqueId() {
2169: return _uniqueId++;
2170: }
2171:
2172: public int generateJspId() {
2173: return _jspId++;
2174: }
2175:
2176: protected void addImport(String name) {
2177: }
2178:
2179: boolean hasTags() {
2180: // size() == 1 is the jsp: tags.
2181: return _tagManager.hasTags();
2182: }
2183:
2184: /**
2185: * Returns the tag with the given qname.
2186: */
2187: public TagInfo getTag(QName qname) throws JspParseException {
2188: return _tagManager.getTag(qname);
2189: }
2190:
2191: /**
2192: * Returns the tag with the given qname.
2193: */
2194: public Class getTagClass(QName qname) throws Exception {
2195: return _tagManager.getTagClass(qname);
2196: }
2197:
2198: public Taglib addTaglib(QName qname) throws JspParseException {
2199: return _tagManager.addTaglib(qname);
2200: }
2201:
2202: public String getSourceLines(Path source, int errorLine) {
2203: if (source == null || errorLine < 1)
2204: return "";
2205:
2206: boolean hasLine = false;
2207: StringBuilder sb = new StringBuilder("\n\n");
2208:
2209: ReadStream is = null;
2210: try {
2211: is = source.openRead();
2212: is.setEncoding(_parseState.getPageEncoding());
2213:
2214: int line = 0;
2215: String text;
2216: while ((text = is.readLine()) != null) {
2217: line++;
2218:
2219: if (errorLine - 2 <= line && line <= errorLine + 2) {
2220: sb.append(line);
2221: sb.append(": ");
2222: sb.append(text);
2223: sb.append("\n");
2224: hasLine = true;
2225: }
2226: }
2227: } catch (IOException e) {
2228: log.log(Level.FINER, e.toString(), e);
2229: } finally {
2230: is.close();
2231: }
2232:
2233: if (hasLine)
2234: return sb.toString();
2235: else
2236: return "";
2237: }
2238:
2239: public JspParseException error(String message) {
2240: JspParseException e = new JspParseException(message);
2241: e.setErrorPage(_parseState.getErrorPage());
2242:
2243: return e;
2244: }
2245:
2246: public JspParseException error(Exception e) {
2247: JspParseException exn = new JspParseException(e);
2248:
2249: exn.setErrorPage(_parseState.getErrorPage());
2250:
2251: return exn;
2252: }
2253:
2254: static class MethodExpr {
2255: private String _exprString;
2256: com.caucho.el.Expr _expr;
2257: Class[] _args;
2258: Class _retType;
2259:
2260: MethodExpr(String exprString, com.caucho.el.Expr expr,
2261: Class[] args, Class retType) {
2262: _exprString = exprString;
2263: _expr = expr;
2264: _args = args;
2265: _retType = retType;
2266: }
2267:
2268: String getExprString() {
2269: return _exprString;
2270: }
2271:
2272: com.caucho.el.Expr getExpr() {
2273: return _expr;
2274: }
2275:
2276: Class[] getArgs() {
2277: return _args;
2278: }
2279:
2280: Class getReturnType() {
2281: return _retType;
2282: }
2283: }
2284:
2285: static class ValueExpr {
2286: private String _exprString;
2287: com.caucho.el.Expr _expr;
2288: Class _retType;
2289:
2290: ValueExpr(String exprString, com.caucho.el.Expr expr,
2291: Class retType) {
2292: _exprString = exprString;
2293: _expr = expr;
2294: _retType = retType;
2295: }
2296:
2297: String getExpressionString() {
2298: return _exprString;
2299: }
2300:
2301: com.caucho.el.Expr getExpr() {
2302: return _expr;
2303: }
2304:
2305: Class getReturnType() {
2306: return _retType;
2307: }
2308: }
2309:
2310: static {
2311: _primitives = new HashMap<String, String>();
2312: _primitives.put("boolean", "boolean");
2313: _primitives.put("byte", "byte");
2314: _primitives.put("short", "short");
2315: _primitives.put("char", "char");
2316: _primitives.put("int", "int");
2317: _primitives.put("long", "long");
2318: _primitives.put("float", "float");
2319: _primitives.put("double", "double");
2320:
2321: _primitiveClasses = new HashMap<String, Class>();
2322: _primitiveClasses.put("boolean", boolean.class);
2323: _primitiveClasses.put("byte", byte.class);
2324: _primitiveClasses.put("short", short.class);
2325: _primitiveClasses.put("char", char.class);
2326: _primitiveClasses.put("int", int.class);
2327: _primitiveClasses.put("long", long.class);
2328: _primitiveClasses.put("float", float.class);
2329: _primitiveClasses.put("double", double.class);
2330: }
2331: }
|