001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: */
055:
056: package com.sun.portal.providers.jsp.jasper3.jasper.compiler;
057:
058: import java.util.Hashtable;
059: import java.util.Stack;
060: import java.util.Vector;
061: import java.util.Enumeration;
062: import java.util.StringTokenizer;
063: import java.io.IOException;
064: import java.io.FileNotFoundException;
065: import java.io.File;
066: import java.io.ObjectOutputStream;
067: import java.io.FileOutputStream;
068: import java.net.URL;
069: import java.net.MalformedURLException;
070:
071: import javax.servlet.jsp.tagext.TagInfo;
072: import javax.servlet.jsp.tagext.TagLibraryInfo;
073:
074: import com.sun.portal.providers.jsp.jasper3.jasper.JasperException;
075: import com.sun.portal.providers.jsp.jasper3.jasper.Constants;
076: import com.sun.portal.providers.jsp.jasper3.jasper.JspCompilationContext;
077:
078: import com.sun.portal.providers.jsp.jasper3.tomcat.logging.Logger;
079:
080: /**
081: * JSP code generator "backend".
082: *
083: * @author Anil K. Vijendran
084: */
085: public class JspParseEventListener extends BaseJspListener {
086:
087: private static CommentGenerator commentGenerator = new JakartaCommentGenerator();
088:
089: JspCompilationContext ctxt;
090:
091: String jspServletBase = Constants.JSP_SERVLET_BASE;
092: String serviceMethodName = Constants.SERVICE_METHOD_NAME;
093: String servletContentType = Constants.SERVLET_CONTENT_TYPE;
094:
095: String extendsClass = "";
096: Vector interfaces = new Vector();
097: Vector imports = new Vector();
098:
099: String error = "";
100:
101: boolean genSessionVariable = true;
102: boolean singleThreaded = false;
103: boolean autoFlush = true;
104:
105: Vector generators = new Vector();
106:
107: BeanRepository beanInfo;
108:
109: int bufferSize = Constants.DEFAULT_BUFFER_SIZE;
110:
111: // a set of boolean variables to check if there are multiple attr-val
112: // pairs for jsp directive.
113: boolean languageDir = false, extendsDir = false,
114: sessionDir = false;
115: boolean bufferDir = false, threadsafeDir = false,
116: errorpageDir = false;
117: boolean iserrorpageDir = false, infoDir = false,
118: autoFlushDir = false;
119: boolean contentTypeDir = false;
120:
121: /* support for large files */
122: int stringId = 0;
123: Vector vector = new Vector();
124: String dataFile;
125:
126: TagLibraries libraries;
127:
128: // Variables shared by all TagBeginGenerator and TagEndGenerator instances
129: // to keep track of nested tags and variable names
130: private Stack tagHandlerStack;
131: private Hashtable tagVarNumbers;
132:
133: final void addGenerator(Generator gen) throws JasperException {
134: gen.init(ctxt);
135: generators.addElement(gen);
136: }
137:
138: public static void setCommentGenerator(CommentGenerator generator) {
139: if (null == commentGenerator) {
140: throw new IllegalArgumentException("null == generator");
141: }
142:
143: commentGenerator = generator;
144: }
145:
146: /*
147: * Package private since I want everyone to come in through
148: * com.sun.portal.providers.jsp.jasper3.jasper.compiler.Main.
149: */
150: JspParseEventListener(JspCompilationContext ctxt) {
151: super (ctxt.getReader(), ctxt.getWriter());
152: this .ctxt = ctxt;
153: this .beanInfo = new BeanRepository(ctxt.getClassLoader());
154: this .libraries = new TagLibraries(ctxt.getClassLoader());
155:
156: if (ctxt.getOptions().getLargeFile()) {
157: String javaFile = ctxt.getServletJavaFileName();
158: int suffix = javaFile.lastIndexOf(".java");
159: if (suffix > 0)
160: dataFile = javaFile.substring(0, suffix) + ".dat";
161: }
162: }
163:
164: public void beginPageProcessing() throws JasperException {
165: for (int i = 0; i < Constants.STANDARD_IMPORTS.length; i++)
166: imports.addElement(Constants.STANDARD_IMPORTS[i]);
167: }
168:
169: public void endPageProcessing() throws JasperException {
170: generateHeader();
171: writer.println();
172: generateAll(ServiceMethodPhase.class);
173: writer.println();
174: generateFooter();
175: if (ctxt.getOptions().getLargeFile())
176: try {
177: ObjectOutputStream o = new ObjectOutputStream(
178: new FileOutputStream(dataFile));
179:
180: /*
181: * Serialize an array of char[]'s instead of an
182: * array of String's because there is a limitation
183: * on the size of Strings that can be serialized.
184: */
185:
186: char[][] tempCharArray = new char[vector.size()][];
187: vector.copyInto(tempCharArray);
188: o.writeObject(tempCharArray);
189: o.close();
190: writer.close();
191: } catch (IOException ex) {
192: throw new JasperException(Constants
193: .getString("jsp.error.data.file.write"), ex);
194: }
195: ctxt.setContentType(servletContentType);
196: }
197:
198: private Stack getTagHandlerStack() {
199: if (tagHandlerStack == null) {
200: tagHandlerStack = new Stack();
201: }
202: return tagHandlerStack;
203: }
204:
205: private Hashtable getTagVarNumbers() {
206: if (tagVarNumbers == null) {
207: tagVarNumbers = new Hashtable();
208: }
209: return tagVarNumbers;
210: }
211:
212: private void generateAll(Class phase) throws JasperException {
213:
214: for (int i = 0; i < generators.size(); i++) {
215: Generator gen = (Generator) generators.elementAt(i);
216: if (phase.isInstance(gen)) {
217: gen.generate(writer, phase);
218: }
219: }
220:
221: }
222:
223: private void generateHeader() throws JasperException {
224: String servletPackageName = ctxt.getServletPackageName();
225: String servletClassName = ctxt.getServletClassName();
226: // First the package name:
227: if (!"".equals(servletPackageName)
228: && servletPackageName != null) {
229: writer.println("package " + servletPackageName + ";");
230: writer.println();
231: }
232:
233: Enumeration e = imports.elements();
234: while (e.hasMoreElements())
235: writer.println("import " + (String) e.nextElement() + ";");
236:
237: writer.println();
238: generateAll(FileDeclarationPhase.class);
239: writer.println();
240:
241: writer.print("public class " + servletClassName + " extends ");
242: writer.print(extendsClass.equals("") ? jspServletBase
243: : extendsClass);
244:
245: if (singleThreaded)
246: interfaces.addElement("SingleThreadModel");
247:
248: if (interfaces.size() != 0) {
249: writer.println();
250: writer.println(" implements ");
251:
252: for (int i = 0; i < interfaces.size() - 1; i++)
253: writer.println(" " + interfaces.elementAt(i) + ",");
254: writer.println(" "
255: + interfaces.elementAt(interfaces.size() - 1));
256: }
257:
258: writer.println(" {");
259:
260: writer.pushIndent();
261: writer.println();
262: generateAll(ClassDeclarationPhase.class);
263: writer.println();
264:
265: writer.println("static {");
266: writer.pushIndent();
267: generateAll(StaticInitializerPhase.class);
268: writer.popIndent();
269: writer.println("}");
270:
271: writer.println("public " + servletClassName + "( ) {");
272: writer.println("}");
273: writer.println();
274:
275: writer.println("private static boolean _jspx_inited = false;");
276: writer.println();
277:
278: writer
279: .println("public final void _jspx_init() throws JasperException {");
280: writer.pushIndent();
281: generateAll(InitMethodPhase.class);
282: writer.popIndent();
283: writer.println("}");
284: writer.println();
285:
286: writer.println("public void " + serviceMethodName + "("
287: + "HttpServletRequest request, "
288: + "HttpServletResponse response)");
289:
290: writer.println(" throws IOException, ServletException {");
291: writer.pushIndent();
292: writer.println();
293:
294: // A@ changes for JSPProvider
295: //writer.println("JspFactory _jspxFactory = null;");
296: writer
297: .println("com.sun.portal.providers.jsp.jasper3.jasper.JspFactory _jspxFactory = null;");
298:
299: writer.println("PageContext pageContext = null;");
300:
301: if (genSessionVariable)
302: writer.println("HttpSession session = null;");
303:
304: if (ctxt.isErrorPage())
305: writer
306: .println("Throwable exception = (Throwable) request.getAttribute(\"javax.servlet.jsp.jspException\");");
307:
308: writer.println("ServletContext application = null;");
309: writer.println("ServletConfig config = null;");
310: writer.println("JspWriter out = null;");
311: writer.println("Object page = this;");
312: writer.println("String _value = null;");
313:
314: // A@ changes for fixing the try/finally problem found in the
315: // reliability testing.
316: // Keep track of the current tag that needs to be released
317: writer
318: .println("javax.servlet.jsp.tagext.Tag _jspx_curTag = null;");
319: writer.println();
320: // END OF A@
321:
322: writer.println("try {");
323: writer.pushIndent();
324:
325: writer.println();
326: writer.println("if (_jspx_inited == false) {");
327: writer.pushIndent();
328: writer.println("_jspx_init();");
329: writer.println("_jspx_inited = true;");
330: writer.popIndent();
331: writer.println("}");
332:
333: // A@ changes for JSPProvider
334: //writer.println("_jspxFactory = JspFactory.getDefaultFactory();");
335: writer
336: .println("_jspxFactory = com.sun.portal.providers.jsp.jasper3.jasper.JspFactory.getPsFactory();");
337:
338: if (this .contentTypeDir == true)
339: writer.println("response.setContentType("
340: + writer.quoteString(servletContentType) + ");");
341: else
342: writer.println("response.setContentType(\""
343: + servletContentType + ";charset=ISO-8859-1\");");
344: writer
345: .println("pageContext = _jspxFactory.getPageContext(this, request, response,\n"
346: + "\t\t\t"
347: + writer.quoteString(error)
348: + ", "
349: + genSessionVariable
350: + ", "
351: + bufferSize
352: + ", "
353: + autoFlush + ");");
354: writer.println();
355:
356: writer
357: .println("application = pageContext.getServletContext();");
358: writer.println("config = pageContext.getServletConfig();");
359:
360: if (genSessionVariable)
361: writer.println("session = pageContext.getSession();");
362:
363: writer.println("out = pageContext.getOut();");
364: }
365:
366: private void generateFooter() throws JasperException {
367: writer.popIndent();
368: //writer.println("} catch (Throwable t) {");
369: writer.println("} catch (Exception ex) {");
370: writer.pushIndent();
371: writer.println("if (out != null && out.getBufferSize() != 0)");
372: writer.pushIndent();
373: writer.println("out.clearBuffer();");
374: writer.popIndent();
375: writer
376: .println("if (pageContext != null) pageContext.handlePageException(ex);");
377: writer.popIndent();
378: writer.println("} finally {");
379: writer.pushIndent();
380: /* Do stuff here for finally actions... */
381: //writer.println("out.close();");
382: // A@ changes for fixing the try/finally problem found in the
383: // reliability testing.
384: // Keep track of the current tag that needs to be released
385: writer.println("_jspx_releaseTags(_jspx_curTag, null);");
386: // END OF A@
387:
388: // Modified the generated code to just call flushBuffer
389: // Modification borrowed from jasper 3.3.1 implementation
390: writer
391: .println("if (out != null && (out instanceof com.sun.portal.providers.jsp.jasper3.jasper.runtime.JspWriterImpl)) {");
392: writer.pushIndent();
393: writer
394: .println("((com.sun.portal.providers.jsp.jasper3.jasper.runtime.JspWriterImpl) out).flushBuffer();");
395: writer.popIndent();
396: writer.println("}");
397:
398: writer
399: .println("if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);");
400: writer.popIndent();
401: writer.println("}");
402: // Close the service method:
403: writer.popIndent();
404: writer.println("}");
405:
406: // A@ changes for fixing the try/finally problem found in the
407: // reliability testing.
408: // Keep track of the current tag that needs to be released
409: generateReleaseTags();
410: // END OF A@
411:
412: // Close the class definition:
413: writer.popIndent();
414: writer.println("}");
415: }
416:
417: public void handleComment(Mark start, Mark stop)
418: throws JasperException {
419: Constants.message("jsp.message.htmlcomment",
420: new Object[] { reader.getChars(start, stop) },
421: Logger.DEBUG);
422: }
423:
424: interface PageDirectiveHandler {
425: void handlePageDirectiveAttribute(
426: JspParseEventListener listener, String value,
427: Mark start, Mark stop) throws JasperException;
428: }
429:
430: static final class PageDirectiveHandlerInfo {
431: String attribute;
432: PageDirectiveHandler handler;
433:
434: PageDirectiveHandlerInfo(String attribute,
435: PageDirectiveHandler handler) {
436: this .attribute = attribute;
437: this .handler = handler;
438: }
439: }
440:
441: static final String languageStr = "language";
442: static final String extendsStr = "extends";
443: static final String importStr = "import";
444: static final String sessionStr = "session";
445: static final String bufferStr = "buffer";
446: static final String autoFlushStr = "autoFlush";
447: static final String isThreadSafeStr = "isThreadSafe";
448: static final String infoStr = "info";
449: static final String errorPageStr = "errorPage";
450: static final String isErrorPageStr = "isErrorPage";
451: static final String contentTypeStr = "contentType";
452:
453: PageDirectiveHandlerInfo[] pdhis = new PageDirectiveHandlerInfo[] {
454: new PageDirectiveHandlerInfo(languageStr,
455: new LanguageHandler()),
456: new PageDirectiveHandlerInfo(extendsStr,
457: new ExtendsHandler()),
458: new PageDirectiveHandlerInfo(importStr,
459: new ImportsHandler()),
460: new PageDirectiveHandlerInfo(sessionStr,
461: new SessionHandler()),
462: new PageDirectiveHandlerInfo(bufferStr, new BufferHandler()),
463: new PageDirectiveHandlerInfo(autoFlushStr,
464: new AutoFlushHandler()),
465: new PageDirectiveHandlerInfo(isThreadSafeStr,
466: new IsThreadSafeHandler()),
467: new PageDirectiveHandlerInfo(infoStr, new InfoHandler()),
468: new PageDirectiveHandlerInfo(isErrorPageStr,
469: new IsErrorPageHandler()),
470: new PageDirectiveHandlerInfo(contentTypeStr,
471: new ContentTypeHandler()),
472: new PageDirectiveHandlerInfo(errorPageStr,
473: new ErrorPageHandler()) };
474:
475: // FIXME: Need to further refine these abstractions by moving the code
476: // to handle duplicate directive instance checks to outside.
477:
478: static final class ContentTypeHandler implements
479: PageDirectiveHandler {
480: public void handlePageDirectiveAttribute(
481: JspParseEventListener listener, String contentType,
482: Mark start, Mark stop) throws JasperException {
483: if (listener.contentTypeDir == true)
484: throw new CompileException(
485: start,
486: Constants
487: .getString("jsp.error.page.multiple.contenttypes"));
488: listener.contentTypeDir = true;
489: if (contentType == null)
490: throw new CompileException(
491: start,
492: Constants
493: .getString("jsp.error.page.invalid.contenttype"));
494: listener.servletContentType = contentType;
495: }
496: }
497:
498: static final class SessionHandler implements PageDirectiveHandler {
499: public void handlePageDirectiveAttribute(
500: JspParseEventListener listener, String session,
501: Mark start, Mark stop) throws JasperException {
502: if (listener.sessionDir == true)
503: throw new CompileException(start, Constants
504: .getString("jsp.error.page.multiple.session"));
505: listener.sessionDir = true;
506: if (session == null)
507: throw new CompileException(start, Constants
508: .getString("jsp.error.page.invalid.session"));
509: if (session.equalsIgnoreCase("true"))
510: listener.genSessionVariable = true;
511: else if (session.equalsIgnoreCase("false"))
512: listener.genSessionVariable = false;
513: else
514: throw new CompileException(start,
515: "Invalid value for session");
516: }
517: }
518:
519: static final class BufferHandler implements PageDirectiveHandler {
520: public void handlePageDirectiveAttribute(
521: JspParseEventListener listener, String buffer,
522: Mark start, Mark stop) throws JasperException {
523: if (listener.bufferDir == true)
524: throw new CompileException(start, Constants
525: .getString("jsp.error.page.multiple.buffer"));
526: listener.bufferDir = true;
527: if (buffer != null) {
528: if (buffer.equalsIgnoreCase("none"))
529: listener.bufferSize = 0;
530: else {
531: Integer i = null;
532: try {
533: int ind = buffer.indexOf("k");
534: String num;
535: if (ind == -1)
536: num = buffer;
537: else
538: num = buffer.substring(0, ind);
539: i = new Integer(num);
540: } catch (NumberFormatException n) {
541: throw new CompileException(
542: start,
543: Constants
544: .getString("jsp.error.page.invalid.buffer"));
545: }
546: listener.bufferSize = i.intValue() * 1024;
547: }
548: } else
549: throw new CompileException(start, Constants
550: .getString("jsp.error.page.invalid.buffer"));
551: }
552: }
553:
554: static final class AutoFlushHandler implements PageDirectiveHandler {
555: public void handlePageDirectiveAttribute(
556: JspParseEventListener listener, String autoflush,
557: Mark start, Mark stop) throws JasperException {
558: if (listener.autoFlushDir == true)
559: throw new CompileException(start, Constants
560: .getString("jsp.error.page.multiple.autoflush"));
561:
562: listener.autoFlushDir = true;
563: if (autoflush == null)
564: throw new CompileException(start, Constants
565: .getString("jsp.error.page.invalid.autoflush"));
566:
567: if (autoflush.equalsIgnoreCase("true"))
568: listener.autoFlush = true;
569: else if (autoflush.equalsIgnoreCase("false"))
570: listener.autoFlush = false;
571: else
572: throw new CompileException(start, Constants
573: .getString("jsp.error.page.invalid.autoflush"));
574: }
575: }
576:
577: static final class IsThreadSafeHandler implements
578: PageDirectiveHandler {
579: public void handlePageDirectiveAttribute(
580: JspParseEventListener listener, String threadsafe,
581: Mark start, Mark stop) throws JasperException {
582: if (listener.threadsafeDir == true)
583: throw new CompileException(
584: start,
585: Constants
586: .getString("jsp.error.page.multiple.threadsafe"));
587:
588: listener.threadsafeDir = true;
589: if (threadsafe == null)
590: throw new CompileException(start, Constants
591: .getString("jsp.error.page.invalid.threadsafe"));
592:
593: if (threadsafe.equalsIgnoreCase("true"))
594: listener.singleThreaded = false;
595: else if (threadsafe.equalsIgnoreCase("false"))
596: listener.singleThreaded = true;
597: else
598: throw new CompileException(start, Constants
599: .getString("jsp.error.page.invalid.threadsafe"));
600: }
601: }
602:
603: static final class InfoHandler implements PageDirectiveHandler {
604: public void handlePageDirectiveAttribute(
605: JspParseEventListener listener, String info,
606: Mark start, Mark stop) throws JasperException {
607: if (listener.infoDir == true)
608: throw new CompileException(start, Constants
609: .getString("jsp.error.page.multiple.info"));
610:
611: listener.infoDir = true;
612: if (info == null)
613: throw new CompileException(start, Constants
614: .getString("jsp.error.page.invalid.info"));
615:
616: GeneratorWrapper gen = listener.new GeneratorWrapper(
617: new InfoGenerator(info), start, stop);
618: listener.addGenerator(gen);
619: }
620: }
621:
622: static final class IsErrorPageHandler implements
623: PageDirectiveHandler {
624: public void handlePageDirectiveAttribute(
625: JspParseEventListener listener, String iserrorpage,
626: Mark start, Mark stop) throws JasperException {
627: if (listener.iserrorpageDir == true)
628: throw new CompileException(
629: start,
630: Constants
631: .getString("jsp.error.page.multiple.iserrorpage"));
632:
633: listener.iserrorpageDir = true;
634: if (iserrorpage == null)
635: throw new CompileException(
636: start,
637: Constants
638: .getString("jsp.error.page.invalid.iserrorpage"));
639:
640: if (iserrorpage.equalsIgnoreCase("true"))
641: listener.ctxt.setErrorPage(true);
642: else if (iserrorpage.equalsIgnoreCase("false"))
643: listener.ctxt.setErrorPage(false);
644: else
645: throw new CompileException(
646: start,
647: Constants
648: .getString("jsp.error.page.invalid.iserrorpage"));
649: }
650: }
651:
652: static final class ErrorPageHandler implements PageDirectiveHandler {
653: public void handlePageDirectiveAttribute(
654: JspParseEventListener listener, String errorpage,
655: Mark start, Mark stop) throws JasperException {
656: if (listener.errorpageDir == true)
657: throw new CompileException(start, Constants
658: .getString("jsp.error.page.multiple.errorpage"));
659:
660: listener.errorpageDir = true;
661: if (errorpage != null)
662: listener.error = errorpage;
663: }
664: }
665:
666: static final class LanguageHandler implements PageDirectiveHandler {
667: public void handlePageDirectiveAttribute(
668: JspParseEventListener listener, String language,
669: Mark start, Mark stop) throws JasperException {
670: if (listener.languageDir == true)
671: throw new CompileException(start, Constants
672: .getString("jsp.error.page.multiple.language"));
673:
674: listener.languageDir = true;
675: if (language != null)
676: if (!language.equalsIgnoreCase("java"))
677: throw new CompileException(
678: start,
679: Constants
680: .getString("jsp.error.page.nomapping.language")
681: + language);
682: }
683: }
684:
685: static final class ImportsHandler implements PageDirectiveHandler {
686: public void handlePageDirectiveAttribute(
687: JspParseEventListener listener, String importPkgs,
688: Mark start, Mark stop) throws JasperException {
689: if (importPkgs != null) {
690: StringTokenizer tokenizer = new StringTokenizer(
691: importPkgs, ",");
692: while (tokenizer.hasMoreTokens())
693: listener.imports.addElement(tokenizer.nextToken());
694: }
695: }
696: }
697:
698: static final class ExtendsHandler implements PageDirectiveHandler {
699: public void handlePageDirectiveAttribute(
700: JspParseEventListener listener, String extendsClzz,
701: Mark start, Mark stop) throws JasperException {
702: if (listener.extendsDir == true)
703: throw new CompileException(start, Constants
704: .getString("jsp.error.page.multiple.extends"));
705:
706: listener.extendsDir = true;
707: if (extendsClzz != null) {
708: listener.extendsClass = extendsClzz;
709:
710: /*
711: * If page superclass is top level class (i.e. not in a pkg)
712: * explicitly import it. If this is not done, the compiler
713: * will assume the extended class is in the same pkg as
714: * the generated servlet.
715: */
716: if (extendsClzz.indexOf(".") == -1) {
717: listener.imports.addElement(extendsClzz);
718: }
719: }
720: }
721: }
722:
723: public void handleDirective(String directive, Mark start,
724: Mark stop, Hashtable attrs) throws JasperException {
725: Constants.message("jsp.message.handling_directive",
726: new Object[] { directive, attrs }, Logger.DEBUG);
727:
728: if (directive.equals("page")) {
729: Enumeration e = attrs.keys();
730: String attr;
731: while (e.hasMoreElements()) {
732: attr = (String) e.nextElement();
733: for (int i = 0; i < pdhis.length; i++) {
734: PageDirectiveHandlerInfo pdhi = pdhis[i];
735: if (attr.equals(pdhi.attribute)) {
736: String value = (String) attrs
737: .get(pdhi.attribute);
738: pdhi.handler.handlePageDirectiveAttribute(this ,
739: value, start, stop);
740: }
741: }
742: }
743: }
744:
745: // Do some validations...
746: if (bufferSize == 0 && autoFlush == false)
747: throw new CompileException(start, Constants
748: .getString("jsp.error.page.bad_b_and_a_combo"));
749:
750: if (directive.equals("taglib")) {
751: String uri = (String) attrs.get("uri");
752: String prefix = (String) attrs.get("prefix");
753: try {
754: TagLibraryInfo tl = new TagLibraryInfoImpl(ctxt,
755: prefix, uri);
756: libraries.addTagLibrary(prefix, tl);
757: } catch (Exception ex) {
758: Object[] args = new Object[] { uri, ex.getMessage() };
759: throw new CompileException(start, Constants.getString(
760: "jsp.error.badtaglib", args));
761: }
762: }
763:
764: if (directive.equals("include")) {
765: String file = (String) attrs.get("file");
766: if (file == null)
767: throw new CompileException(start, Constants
768: .getString("jsp.error.include.missing.file"));
769:
770: // jsp.error.include.bad.file needs taking care of here??
771: try {
772: reader.pushFile(file, null);
773: } catch (FileNotFoundException fnfe) {
774: throw new CompileException(start, Constants
775: .getString("jsp.error.include.bad.file"));
776: }
777: }
778: }
779:
780: class GeneratorWrapper implements Generator, ClassDeclarationPhase,
781: FileDeclarationPhase, ServiceMethodPhase, InitMethodPhase,
782: StaticInitializerPhase {
783: Generator generator;
784: Mark start, stop;
785:
786: GeneratorWrapper(Generator generator, Mark start, Mark stop) {
787: this .generator = generator;
788: this .start = start;
789: this .stop = stop;
790: }
791:
792: /*
793: * This is really a no-op.
794: */
795: public boolean generateCoordinates(Class phase) {
796: return generator.generateCoordinates(phase);
797: }
798:
799: public void init(JspCompilationContext ctxt)
800: throws JasperException {
801: generator.init(ctxt);
802: }
803:
804: public void generate(ServletWriter out, Class phase)
805: throws JasperException {
806: if (phase.isInstance(generator)) {
807: boolean genCoords = generator
808: .generateCoordinates(phase);
809: if (genCoords) {
810: commentGenerator.generateStartComment(generator,
811: out, start, stop);
812: }
813: generator.generate(out, phase);
814: if (genCoords) {
815: commentGenerator.generateEndComment(generator, out,
816: start, stop);
817: }
818: }
819: }
820: }
821:
822: public void handleDeclaration(Mark start, Mark stop, Hashtable attrs)
823: throws JasperException {
824: Generator gen = new GeneratorWrapper(new DeclarationGenerator(
825: reader.getChars(start, stop)), start, stop);
826: addGenerator(gen);
827: }
828:
829: public void handleScriptlet(Mark start, Mark stop, Hashtable attrs)
830: throws JasperException {
831: Generator gen = new GeneratorWrapper(new ScriptletGenerator(
832: reader.getChars(start, stop)), start, stop);
833: addGenerator(gen);
834: }
835:
836: public void handleExpression(Mark start, Mark stop, Hashtable attrs)
837: throws JasperException {
838: Generator gen = new GeneratorWrapper(new ExpressionGenerator(
839: reader.getChars(start, stop)), start, stop);
840: addGenerator(gen);
841: }
842:
843: public void handleBean(Mark start, Mark stop, Hashtable attrs,
844: boolean isBodyEmpty) throws JasperException {
845: Generator gen = new GeneratorWrapper(new BeanGenerator(start,
846: attrs, beanInfo, genSessionVariable, isBodyEmpty),
847: start, stop);
848:
849: addGenerator(gen);
850: }
851:
852: public void handleBeanEnd(Mark start, Mark stop, Hashtable attrs,
853: boolean isBodyEmpty) throws JasperException {
854: Generator gen = new GeneratorWrapper(new BeanEndGenerator(
855: isBodyEmpty), start, stop);
856: // End the block started by useBean body.
857: addGenerator(gen);
858: }
859:
860: public void handleGetProperty(Mark start, Mark stop, Hashtable attrs)
861: throws JasperException {
862: Generator gen = new GeneratorWrapper(new GetPropertyGenerator(
863: start, stop, attrs, beanInfo), start, stop);
864:
865: addGenerator(gen);
866: }
867:
868: public void handleSetProperty(Mark start, Mark stop, Hashtable attrs)
869: throws JasperException {
870: Generator gen = new GeneratorWrapper(new SetPropertyGenerator(
871: start, stop, attrs, beanInfo), start, stop);
872:
873: addGenerator(gen);
874: }
875:
876: public void handlePlugin(Mark start, Mark stop, Hashtable attrs,
877: Hashtable param, String fallback) throws JasperException {
878: Constants.message("jsp.message.handling_plugin",
879: new Object[] { attrs }, Logger.DEBUG);
880:
881: Generator gen = new GeneratorWrapper(new PluginGenerator(start,
882: attrs, param, fallback), start, stop);
883: addGenerator(gen);
884: }
885:
886: public void handleForward(Mark start, Mark stop, Hashtable attrs,
887: Hashtable param) throws JasperException {
888: Generator gen = new GeneratorWrapper(new ForwardGenerator(
889: start, attrs, param), start, stop);
890:
891: addGenerator(gen);
892: }
893:
894: public void handleInclude(Mark start, Mark stop, Hashtable attrs,
895: Hashtable param) throws JasperException {
896: Generator gen = new GeneratorWrapper(new IncludeGenerator(
897: start, attrs, param), start, stop);
898:
899: addGenerator(gen);
900: }
901:
902: public void handleCharData(Mark start, Mark stop, char[] chars)
903: throws JasperException {
904: GeneratorBase cdg;
905:
906: if (ctxt.getOptions().getLargeFile())
907: cdg = new StoredCharDataGenerator(vector, dataFile,
908: stringId++, chars);
909: else if (ctxt.getOptions().getMappedFile())
910: cdg = new MappedCharDataGenerator(chars);
911: else
912: cdg = new CharDataGenerator(chars);
913:
914: Generator gen = new GeneratorWrapper(cdg, start, stop);
915:
916: addGenerator(gen);
917: }
918:
919: public void handleTagBegin(Mark start, Mark stop, Hashtable attrs,
920: String prefix, String shortTagName, TagLibraryInfo tli,
921: TagInfo ti) throws JasperException {
922: TagBeginGenerator tbg = new TagBeginGenerator(start, prefix,
923: shortTagName, attrs, tli, ti, libraries,
924: getTagHandlerStack(), getTagVarNumbers());
925: Generator gen = new GeneratorWrapper(tbg, start, stop);
926:
927: addGenerator(gen);
928: }
929:
930: public void handleTagEnd(Mark start, Mark stop, String prefix,
931: String shortTagName, Hashtable attrs, TagLibraryInfo tli,
932: TagInfo ti) throws JasperException {
933: TagEndGenerator teg = new TagEndGenerator(prefix, shortTagName,
934: attrs, tli, ti, libraries, getTagHandlerStack(),
935: getTagVarNumbers());
936: Generator gen = new GeneratorWrapper(teg, start, stop);
937:
938: addGenerator(gen);
939: }
940:
941: public TagLibraries getTagLibraries() {
942: return libraries;
943: }
944:
945: // A@ changes for fixing the try/finally problem found in the
946: // reliability testing.
947: // Keep track of the current tag that needs to be released
948: private void generateReleaseTags() {
949: writer
950: .println("private static void _jspx_releaseTags(javax.servlet.jsp.tagext.Tag tag, javax.servlet.jsp.tagext.Tag until) {");
951: writer.pushIndent();
952: writer.println("while (tag != until && tag != null) {");
953: writer.pushIndent();
954: writer.println("javax.servlet.jsp.tagext.Tag cur = tag;");
955: writer.println("tag = tag.getParent();");
956: writer.println("try {");
957: writer.pushIndent();
958: writer.println("cur.release();");
959: writer.popIndent();
960: writer.println("} catch (Exception e) {}");
961: writer.popIndent();
962: writer.println("}");
963: writer.popIndent();
964: writer.println("}");
965: }
966: // END OF A@
967: }
|