KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jsp > java > CustomTag


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jsp.java;
31
32 import com.caucho.jsp.AnalyzedTag;
33 import com.caucho.jsp.TagInstance;
34 import com.caucho.xml.QName;
35
36 import javax.servlet.jsp.tagext.*;
37 import java.lang.reflect.Method JavaDoc;
38 import java.util.ArrayList JavaDoc;
39
40 /**
41  * Represents a custom tag.
42  */

43 public class CustomTag extends GenericTag
44 {
45   protected String JavaDoc _bodyContent;
46   
47   /**
48    * Generates the code for a custom tag.
49    *
50    * @param out the output writer for the generated java.
51    */

52   public void generate(JspJavaWriter out)
53     throws Exception JavaDoc
54   {
55     String JavaDoc name = _tag.getId();
56     String JavaDoc className = _tagInfo.getTagClassName();
57     String JavaDoc tagHackVar = "_jsp_endTagHack" + _gen.uniqueId();
58     Class JavaDoc cl = _tagClass;
59
60     AnalyzedTag analyzedTag = _tag.getAnalyzedTag();
61
62     boolean isIterator = (IterationTag.class.isAssignableFrom(cl) ||
63                           BodyTag.class.isAssignableFrom(cl));
64     boolean isBodyTag = BodyTag.class.isAssignableFrom(cl);
65     boolean isCatch = TryCatchFinally.class.isAssignableFrom(cl);
66
67     boolean isEmpty = isEmpty();
68     boolean usesTagBody = isBodyTag && ! isEmpty &&
69       analyzedTag.getStartReturnsBuffered();
70     boolean hasEndTag = analyzedTag.getDoEnd();
71     
72     if ("empty".equalsIgnoreCase(_bodyContent)) {
73       if (! isEmpty)
74     throw error(L.l("<{0}> expects an empty body", getTagName()));
75     }
76     if (usesTagBody && hasEndTag)
77       out.println("com.caucho.jsp.BodyContentImpl " + tagHackVar + " = null;");
78     else
79       tagHackVar = "out";
80
81     if (! isDeclared()) {
82       out.println("if (" + name + " == null) {");
83       out.pushDepth();
84       generateTagInit(out);
85       out.popDepth();
86       out.println("}");
87       out.println();
88     }
89
90     fillAttributes(out, name);
91
92     printVarDeclare(out, VariableInfo.AT_BEGIN);
93
94     String JavaDoc oldTag = "_jsp_writer" + _gen.uniqueId();
95     
96     if (analyzedTag.getDoCatch())
97       out.println("javax.servlet.jsp.JspWriter " + oldTag + " = out;");
98     
99     if (analyzedTag.getDoCatch() || analyzedTag.getDoFinally()) {
100       out.println("try {");
101       out.pushDepth();
102     }
103
104     boolean hasStartTag = analyzedTag.getDoStart();
105     int startCount = ((analyzedTag.getStartReturnsSkip() ? 1 : 0) +
106               (analyzedTag.getStartReturnsInclude() ? 1 : 0) +
107               (analyzedTag.getStartReturnsBuffered() ? 1 : 0));
108     
109     int thisId = _gen.uniqueId();
110     if (! hasStartTag) {
111     }
112     else if (startCount == 1) {
113       out.println(name + ".doStartTag();");
114     }
115     else {
116       out.println("int _jspEval" + thisId + " = " + name + ".doStartTag();");
117     }
118     printVarAssign(out, VariableInfo.AT_BEGIN);
119
120     if (analyzedTag.getStartReturnsSkip() &&
121     ! analyzedTag.getStartReturnsInclude() &&
122     ! analyzedTag.getStartReturnsBuffered()) {
123       // jsp/18cp
124
generateChildrenEmpty();
125     }
126     else if (isEmpty) {
127       // jsp/18kc
128
/*
129       if (isBodyTag)
130     out.println(" " + name + ".setBodyContent((javax.servlet.jsp.tagext.BodyContent) null);");
131       */

132     }
133     else {
134       if (startCount > 1 && analyzedTag.getStartReturnsSkip()) {
135         out.println("if (_jspEval" + thisId + " != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {");
136         out.pushDepth();
137       }
138       else if ((hasVarDeclaration(VariableInfo.NESTED) ||
139         childHasScriptlet()) &&
140            ! (analyzedTag.getDoCatch() ||
141           analyzedTag.getDoFinally() ||
142           analyzedTag.getDoAfter() &&
143           analyzedTag.getAfterReturnsAgain())) {
144     out.println("{");
145     out.pushDepth();
146       }
147
148       if (usesTagBody) {
149         if (analyzedTag.getStartReturnsBuffered() &&
150         analyzedTag.getStartReturnsInclude()) {
151           out.println("if (_jspEval" + thisId + " == javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED) {");
152           out.pushDepth();
153         }
154         
155         out.println("out = pageContext.pushBody();");
156
157     if (hasEndTag) {
158       out.println(tagHackVar + " = (com.caucho.jsp.BodyContentImpl) out;");
159       out.println(name + ".setBodyContent(" + tagHackVar + ");");
160     }
161     else
162       out.println(name + ".setBodyContent((javax.servlet.jsp.tagext.BodyContent) " + tagHackVar + ");");
163         
164         if (analyzedTag.getDoInit())
165           out.println(name + ".doInitBody();");
166         
167         if (analyzedTag.getStartReturnsBuffered() &&
168         analyzedTag.getStartReturnsInclude()) {
169           out.popDepth();
170           out.println("}");
171
172       // jsp/18kf - req by JSP TCK
173
/*
174       if (_tag.getBodyContent()) {
175         out.println("else");
176         out.println(" " + name + ".setBodyContent((javax.servlet.jsp.tagext.BodyContent) null);");
177       }
178       */

179         }
180       }
181       else if (isBodyTag && _tag.getBodyContent())
182         out.println(name + ".setBodyContent((javax.servlet.jsp.tagext.BodyContent) null);");
183
184       if (analyzedTag.getDoAfter() && analyzedTag.getAfterReturnsAgain()) {
185     out.println("do {");
186     out.pushDepth();
187       }
188
189       out.setLocation(getFilename(), getStartLine());
190
191       if (_children != null)
192     printVarDeclaration(out, VariableInfo.NESTED);
193       
194       out.setLocation(getFilename(), getStartLine());
195       
196       generateChildren(out);
197
198       out.setLocation(getFilename(), getEndLine());
199
200       if (analyzedTag.getDoAfter() && analyzedTag.getAfterReturnsAgain()) {
201     out.popDepth();
202     out.println("} while (" + name + ".doAfterBody() == javax.servlet.jsp.tagext.IterationTag.EVAL_BODY_AGAIN);");
203       }
204       else if (analyzedTag.getDoAfter()) {
205     out.println(name + ".doAfterBody();");
206       }
207
208       if (usesTagBody) {
209         if (analyzedTag.getStartReturnsBuffered() &&
210         analyzedTag.getStartReturnsInclude()) {
211           out.println("if (_jspEval" + thisId + " == javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED)");
212
213       if (hasEndTag)
214         out.println(" out = pageContext.popBody();");
215       else
216         out.println(" out = pageContext.popAndReleaseBody();");
217         }
218         else if (analyzedTag.getStartReturnsBuffered()) {
219       if (hasEndTag)
220         out.println("out = pageContext.popBody();");
221       else
222         out.println("out = pageContext.popAndReleaseBody();");
223     }
224       }
225
226       if (startCount > 1 && analyzedTag.getStartReturnsSkip()) {
227         out.popDepth();
228         out.println("}");
229       }
230       else if (isEmpty) {
231       }
232       else if ((hasVarDeclaration(VariableInfo.NESTED) ||
233         childHasScriptlet()) &&
234            ! (analyzedTag.getDoCatch() ||
235           analyzedTag.getDoFinally() ||
236           analyzedTag.getDoAfter() &&
237           analyzedTag.getAfterReturnsAgain())) {
238         out.popDepth();
239         out.println("}");
240       }
241     }
242
243     out.setLocation(getFilename(), getEndLine());
244     
245     int endCount = ((analyzedTag.getEndReturnsSkip() ? 1 : 0) +
246             (analyzedTag.getEndReturnsEval() ? 1 : 0));
247     
248     String JavaDoc endVar = "_jsp_end_" + _gen.uniqueId();
249
250     if (! hasEndTag) {
251     }
252     else if (endCount > 1)
253       out.println("int " + endVar + " = " + name + ".doEndTag();");
254     else
255       out.println(name + ".doEndTag();");
256
257     if (! hasEndTag || ! usesTagBody) {
258     }
259     else if (hasStartTag &&
260          (analyzedTag.getStartReturnsSkip() ||
261           analyzedTag.getStartReturnsInclude())) {
262       out.println("if (" + tagHackVar + " != null) {");
263       out.println(" pageContext.releaseBody(" + tagHackVar + ");");
264       out.println(" " + tagHackVar + " = null;");
265       out.println("}");
266     }
267     else {
268       out.println("pageContext.releaseBody(" + tagHackVar + ");");
269     }
270
271     if (analyzedTag.getEndReturnsSkip()) {
272       if (hasEndTag && endCount > 1)
273     out.println("if (" + endVar + " == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)");
274       else
275     out.println("if (true)");
276
277       if (_gen.isTag() || isInFragment())
278     out.println(" throw new SkipPageException();");
279       else
280     out.println(" return;");
281     }
282     
283     if (analyzedTag.getDoCatch()) {
284       String JavaDoc t = "_jsp_exn_" + _gen.uniqueId();
285       
286       out.popDepth();
287       out.println("} catch (Throwable " + t + ") {");
288       out.println(" pageContext.setWriter(" + oldTag + ");");
289       out.println(" out = " + oldTag + ";");
290       out.println(" " + name + ".doCatch(" + t + ");");
291       out.pushDepth();
292     }
293     
294     if (analyzedTag.getDoFinally()) {
295       out.popDepth();
296       out.println("} finally {");
297       out.println(" " + name + ".doFinally();");
298       out.pushDepth();
299     }
300
301     if (analyzedTag.getDoCatch() || analyzedTag.getDoFinally()) {
302       out.popDepth();
303       out.println("}");
304     }
305     
306     printVarDeclaration(out, VariableInfo.AT_END);
307     
308     out.setLocation(getFilename(), getEndLine());
309   }
310
311   /**
312    * Returns true if the tag implements the named method, false if it
313    * relies on the default.
314    */

315   private boolean tagImplementsMethod(Class JavaDoc cl, String JavaDoc name)
316     throws NoSuchMethodException JavaDoc
317   {
318     Method JavaDoc method;
319
320     try {
321       method = cl.getMethod(name, new Class JavaDoc[0]);
322     } catch (Exception JavaDoc e) {
323       return false;
324     }
325
326     if (method == null)
327       return false;
328
329     Class JavaDoc declaringClass = method.getDeclaringClass();
330
331     return (! declaringClass.equals(TagSupport.class) &&
332             ! declaringClass.equals(BodyTagSupport.class));
333   }
334
335   /**
336    * Generates the initialization code for the tag.
337    *
338    * @param out the output stream
339    */

340   private void generateTagInit(JspJavaWriter out)
341     throws Exception JavaDoc
342   {
343     TagInstance parent = _tag.getParent();
344     String JavaDoc id = _tag.getId();
345
346     String JavaDoc var = _tag.getId();
347     String JavaDoc className = _tag.getTagClass().getName();
348       
349     out.print(var + " = new ");
350     out.printClass(_tag.getTagClass());
351     out.println("();");
352
353     if (JspIdConsumer.class.isAssignableFrom(_tag.getTagClass())) {
354       String JavaDoc shortName = className;
355       int p = shortName.lastIndexOf('.');
356       if (p >= 0)
357     shortName = shortName.substring(p + 1);
358
359       out.print(var + ".setJspId(\"" + shortName + "-" + _gen.generateJspId() + "\");");
360     }
361
362     if (_tag.getAnalyzedTag().getHasInjection()) {
363       out.println("_jsp_inject_" + _tag.getId() + ".configure(" + var + ");");
364     }
365     
366     AnalyzedTag analyzedTag = _tag.getAnalyzedTag();
367
368     JspNode parentTagNode = getParent().getParentTagNode();
369
370     out.println(var + ".setPageContext(pageContext);");
371     if (parentTagNode == null) {
372       out.println(var + ".setParent((javax.servlet.jsp.tagext.Tag) null);");
373     }
374     else if (parentTagNode.isSimpleTag()) {
375       String JavaDoc parentName = parentTagNode.getCustomTagName();
376       
377       out.println("if (" + parentName + "_adapter == null)");
378       out.println(" " + parentName + "_adapter = new javax.servlet.jsp.tagext.TagAdapter(" + parentName + ");");
379       out.println(var + ".setParent(" + parentName + "_adapter);");
380     }
381     else {
382       String JavaDoc parentName = parentTagNode.getCustomTagName();
383       
384       out.println(var + ".setParent((javax.servlet.jsp.tagext.Tag) " + parentName + ");");
385     }
386
387     ArrayList JavaDoc<QName> names = _tag.getAttributeNames();
388     for (int i = 0; i < names.size(); i++) {
389       QName name = names.get(i);
390
391       String JavaDoc value = _tag.getAttribute(name);
392       if (value == null)
393         continue;
394       
395       TagAttributeInfo attrInfo = _tag.getAttributeInfo(name.getLocalName());
396
397       generateSetAttribute(out, var, name, value, false, false, attrInfo);
398     }
399   }
400
401   /**
402    * Returns true if the node or one of its children is a scriptlet
403    */

404   private boolean childHasScriptlet()
405   {
406     ArrayList JavaDoc<JspNode> children = getChildren();
407
408     if (children == null)
409       return false;
410
411     for (int i = 0; i < children.size(); i++) {
412       JspNode child = children.get(i);
413
414       if (child instanceof JspScriptlet || child instanceof JspExpression)
415     return true;
416     }
417
418     return false;
419   }
420 }
421
Popular Tags