KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > ext > jsp > TaglibFactory


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.ext.jsp;
54
55 import java.beans.IntrospectionException JavaDoc;
56 import java.io.ByteArrayInputStream JavaDoc;
57 import java.io.FilterInputStream JavaDoc;
58 import java.io.IOException JavaDoc;
59 import java.io.InputStream JavaDoc;
60 import java.net.MalformedURLException JavaDoc;
61 import java.util.ArrayList JavaDoc;
62 import java.util.HashMap JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.List JavaDoc;
65 import java.util.Map JavaDoc;
66 import java.util.Set JavaDoc;
67 import java.util.zip.ZipEntry JavaDoc;
68 import java.util.zip.ZipInputStream JavaDoc;
69
70 import javax.servlet.ServletContext JavaDoc;
71 import javax.servlet.http.HttpServletRequest JavaDoc;
72 import javax.xml.parsers.ParserConfigurationException JavaDoc;
73 import javax.xml.parsers.SAXParserFactory JavaDoc;
74
75 import org.xml.sax.Attributes JavaDoc;
76 import org.xml.sax.EntityResolver JavaDoc;
77 import org.xml.sax.InputSource JavaDoc;
78 import org.xml.sax.Locator JavaDoc;
79 import org.xml.sax.SAXException JavaDoc;
80 import org.xml.sax.SAXParseException JavaDoc;
81 import org.xml.sax.XMLReader JavaDoc;
82 import org.xml.sax.helpers.DefaultHandler JavaDoc;
83
84 import freemarker.core.Environment;
85 import freemarker.ext.servlet.FreemarkerServlet;
86 import freemarker.ext.servlet.HttpRequestHashModel;
87 import freemarker.log.Logger;
88 import freemarker.template.TemplateHashModel;
89 import freemarker.template.TemplateModel;
90 import freemarker.template.TemplateModelException;
91 import freemarker.template.utility.ClassUtil;
92
93
94
95 /**
96  * A hash model associated with a servlet context that can load JSP tag
97  * libraries associated with that servlet context. An instance of this class is
98  * made available in the root data model of templates executed by
99  * {@link freemarker.ext.servlet.FreemarkerServlet} under key
100  * <tt>JspTaglibs</tt>. It can be added to custom servlets as well to enable JSP
101  * taglib integration in them as well.
102  * @version $Id: TaglibFactory.java,v 1.26 2005/06/13 20:52:55 szegedia Exp $
103  * @author Attila Szegedi
104  */

105 public class TaglibFactory implements TemplateHashModel {
106     private static final Logger logger = Logger.getLogger("freemarker.jsp");
107
108     // No TLDs have been looked up yet
109
private static final int LOOKUP_NONE = 0;
110     // Only explicit TLDs in web.xml have been looked up
111
private static final int LOOKUP_WEB_XML = 1;
112     // Both explicit TLDs and those in JARs have been looked up
113
private static final int LOOKUP_JARS = 2;
114     
115     private final ServletContext JavaDoc ctx;
116     private final Map JavaDoc taglibs = new HashMap JavaDoc();
117     private final Map JavaDoc locations = new HashMap JavaDoc();
118     private int lookupPhase = LOOKUP_NONE;
119
120     /**
121      * Creates a new JSP taglib factory that will be used to load JSP taglibs
122      * for the web application represented by the passed servlet context.
123      * @param ctx the servlet context whose JSP tag libraries will this factory
124      * load.
125      */

126     public TaglibFactory(ServletContext JavaDoc ctx) {
127         this.ctx = ctx;
128     }
129
130     /**
131      * Retrieves a JSP tag library identified by an URI. The matching of the URI
132      * to a JSP taglib is done as described in the JSP 1.2 FCS specification.
133      * @param uri the URI that describes the JSP taglib. It can be any of the
134      * three forms allowed by the JSP specification: absolute URI, root relative
135      * URI and non-root relative URI. Note that if a non-root relative URI is
136      * used it is resolved relative to the URL of the current request. In this
137      * case, the current request is obtained by looking up a
138      * {@link HttpRequestHashModel} object named <tt>Request</tt> in the root
139      * data model. FreemarkerServlet provides this object under the expected
140      * name, and custom servlets that want to integrate JSP taglib support
141      * should do the same.
142      * @return a hash model representing the JSP taglib. Each element of this
143      * hash model represents a single custom tag from the library, implemented
144      * as a {@link freemarker.template.TemplateTransformModel}.
145      */

146     public TemplateModel get(String JavaDoc uri) throws TemplateModelException {
147         uri = resolveRelativeUri(uri);
148         synchronized (taglibs) {
149             Taglib taglib = null;
150             taglib = (Taglib) taglibs.get(uri);
151             if(taglib != null) {
152                 return taglib;
153             }
154             
155             taglib = new Taglib();
156             try {
157                 do {
158                     if(taglib.load(uri, ctx, locations)) {
159                         taglibs.put(uri, taglib);
160                         return taglib;
161                     }
162                 }
163                 while(getMoreTaglibLocations());
164             }
165             catch(TemplateModelException e) {
166                 throw e;
167             }
168             catch(Exception JavaDoc e) {
169                 throw new TemplateModelException("Could not load taglib information", e);
170             }
171             return null;
172         }
173     }
174
175     /**
176      * Returns false.
177      */

178     public boolean isEmpty() {
179         return false;
180     }
181
182     private boolean getMoreTaglibLocations() throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc
183     {
184         switch(lookupPhase) {
185             case LOOKUP_NONE: {
186                 getLocationsFromWebXml();
187                 lookupPhase = LOOKUP_WEB_XML;
188                 return true;
189             }
190             case LOOKUP_WEB_XML: {
191                 getLocationsFromLibJars();
192                 lookupPhase = LOOKUP_JARS;
193                 return true;
194             }
195             default : {
196                 return false;
197             }
198         }
199     }
200     
201     private void getLocationsFromWebXml() throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc
202     {
203         WebXmlParser webXmlParser = new WebXmlParser(locations);
204         InputStream JavaDoc in = ctx.getResourceAsStream("/WEB-INF/web.xml");
205         if (in == null) {
206             // No /WEB-INF/web.xml - do nothing
207
return;
208         }
209         try {
210             parseXml(in, ctx.getResource("/WEB-INF/web.xml").toExternalForm(), webXmlParser);
211         }
212         finally {
213             in.close();
214         }
215     }
216     
217     private static class WebXmlParser extends DefaultHandler JavaDoc {
218         private final Map JavaDoc locations;
219         
220         private StringBuffer JavaDoc buf;
221         private String JavaDoc uri;
222         private String JavaDoc location;
223
224         WebXmlParser(Map JavaDoc locations) {
225             this.locations = locations;
226         }
227
228         public void startElement(
229             String JavaDoc nsuri,
230             String JavaDoc localName,
231             String JavaDoc qName,
232             Attributes JavaDoc atts) {
233             if ("taglib-uri".equals(qName)
234                 || "taglib-location".equals(qName)) {
235                 buf = new StringBuffer JavaDoc();
236             }
237         }
238
239         public void characters(char[] chars, int off, int len) {
240             if (buf != null) {
241                 buf.append(chars, off, len);
242             }
243         }
244
245         public void endElement(String JavaDoc nsuri, String JavaDoc localName, String JavaDoc qName) {
246             if ("taglib-uri".equals(qName)) {
247                 uri = buf.toString().trim();
248                 buf = null;
249             }
250             else if ("taglib-location".equals(qName)) {
251                 location = buf.toString().trim();
252                 if(location.indexOf("://") == -1 && !location.startsWith("/")) {
253                     location = "/WEB-INF/" + location;
254                 }
255                 buf = null;
256             }
257             else if ("taglib".equals(qName)) {
258                 String JavaDoc[] loc = new String JavaDoc[2];
259                 loc[0] = location;
260                 if(location.endsWith(".jar") || location.endsWith(".zip")) {
261                     loc[1] = "META-INF/taglib.tld";
262                 }
263                 locations.put(uri, loc);
264                 if(logger.isDebugEnabled()) {
265                     logger.debug("web.xml assigned URI " + uri + " to location " + loc[0] + (loc[1] != null ? "!" + loc[1] : ""));
266                 }
267             }
268         }
269     }
270
271
272     private void getLocationsFromLibJars() throws ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc
273     {
274         Set JavaDoc libs = ctx.getResourcePaths("/WEB-INF/lib");
275         for (Iterator JavaDoc iter = libs.iterator(); iter.hasNext();) {
276             String JavaDoc path = (String JavaDoc) iter.next();
277             if(path.endsWith(".jar") || path.endsWith(".zip")) {
278                 ZipInputStream JavaDoc zin = new ZipInputStream JavaDoc(ctx.getResourceAsStream(path));
279                 // Make stream uncloseable by XML parsers
280
InputStream JavaDoc uin = new FilterInputStream JavaDoc(zin) {
281                     public void close() {
282                     }
283                 };
284                 try {
285                     for(;;) {
286                         ZipEntry JavaDoc ze = zin.getNextEntry();
287                         if(ze == null) {
288                             break;
289                         }
290                         String JavaDoc zname = ze.getName();
291                         if(zname.startsWith("META-INF/") && zname.endsWith(".tld")) {
292                             String JavaDoc url = "jar:" +
293                                 ctx.getResource(path).toExternalForm() +
294                                 "!" + zname;
295                             String JavaDoc loc = getTldUri(uin, url);
296                             if(loc != null) {
297                                 locations.put(loc, new String JavaDoc[] { path, zname });
298                                 if(logger.isDebugEnabled()) {
299                                     logger.debug("libjar assigned URI " + loc + " to location " + path + "!" + zname);
300                                 }
301                             }
302                         }
303                     }
304                 }
305                 finally {
306                     zin.close();
307                 }
308             }
309         }
310     }
311
312     private String JavaDoc getTldUri(InputStream JavaDoc in, String JavaDoc url) throws ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc
313     {
314         TldUriReader tur = new TldUriReader();
315         parseXml(in, url, tur);
316         return tur.getUri();
317     }
318     
319     private static class TldUriReader extends DefaultHandler JavaDoc {
320
321         private StringBuffer JavaDoc buf;
322         private String JavaDoc uri;
323
324         TldUriReader() {
325         }
326
327         String JavaDoc getUri() {
328             return uri;
329         }
330         
331         public void startElement(
332             String JavaDoc nsuri,
333             String JavaDoc localName,
334             String JavaDoc qName,
335             Attributes JavaDoc atts) {
336             if ("uri".equals(qName)) {
337                 buf = new StringBuffer JavaDoc();
338             }
339         }
340
341         public void characters(char[] chars, int off, int len) {
342             if (buf != null) {
343                 buf.append(chars, off, len);
344             }
345         }
346
347         public void endElement(String JavaDoc nsuri, String JavaDoc localName, String JavaDoc qName) {
348             if ("uri".equals(qName)) {
349                 uri = buf.toString().trim();
350                 buf = null;
351             }
352         }
353     }
354
355     private static void parseXml(InputStream JavaDoc in, String JavaDoc url, DefaultHandler JavaDoc handler)
356     throws
357         ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc
358     {
359         InputSource JavaDoc is = new InputSource JavaDoc();
360         is.setByteStream(in);
361         is.setSystemId(url);
362         SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
363         factory.setNamespaceAware(false);
364         factory.setValidating(true);
365         XMLReader JavaDoc reader = factory.newSAXParser().getXMLReader();
366         reader.setEntityResolver(new LocalTaglibDtds());
367         reader.setContentHandler(handler);
368         reader.parse(is);
369     }
370
371     private static final class Taglib implements TemplateHashModel {
372         private Map JavaDoc tags;
373
374         Taglib() {
375         }
376
377         public TemplateModel get(String JavaDoc key) {
378             return (TagTransformModel) tags.get(key);
379         }
380
381         public boolean isEmpty() {
382             return false;
383         }
384         
385         boolean load(String JavaDoc uri, ServletContext JavaDoc ctx, Map JavaDoc locations)
386         throws
387             ParserConfigurationException JavaDoc,
388             IOException JavaDoc,
389             SAXException JavaDoc,
390             TemplateModelException
391         {
392             String JavaDoc[] tldPath = getTldPath(uri, locations);
393             if(logger.isDebugEnabled()) {
394                 if(tldPath == null) {
395                     logger.debug("Loading taglib " + uri + " from location null");
396                 }
397                 else {
398                     logger.debug("Loading taglib " + uri + " from location " + tldPath[0] + (tldPath[1] != null ? "!" + tldPath[1] : ""));
399                 }
400             }
401             tags = loadTaglib(tldPath, ctx);
402             if(tags != null) {
403                 locations.remove(uri);
404                 return true;
405             }
406             else {
407                 return false;
408             }
409         }
410     }
411
412     private static final Map JavaDoc loadTaglib(String JavaDoc[] tldPath, ServletContext JavaDoc ctx)
413     throws
414         ParserConfigurationException JavaDoc, IOException JavaDoc, SAXException JavaDoc, TemplateModelException
415     {
416         if (tldPath == null) {
417             return null;
418         }
419         String JavaDoc filePath = tldPath[0];
420         TldParser tldParser = new TldParser();
421         InputStream JavaDoc in = ctx.getResourceAsStream(filePath);
422         if(in == null) {
423             throw new TemplateModelException("Could not find webapp resource " + filePath);
424         }
425         String JavaDoc url = ctx.getResource(filePath).toExternalForm();
426         try {
427             String JavaDoc jarPath = tldPath[1];
428             if(jarPath != null) {
429                 ZipInputStream JavaDoc zin = new ZipInputStream JavaDoc(in);
430                 for(;;) {
431                     ZipEntry JavaDoc ze = zin.getNextEntry();
432                     if(ze == null) {
433                         throw new TemplateModelException("Could not find JAR entry " + jarPath + " inside webapp resource " + filePath);
434                     }
435                     String JavaDoc zname = ze.getName();
436                     if(zname.equals(jarPath)) {
437                         parseXml(zin, "jar:" + url + "!" + zname, tldParser);
438                         break;
439                     }
440                 }
441             }
442             else {
443                 parseXml(in, url, tldParser);
444             }
445         }
446         finally {
447             in.close();
448         }
449         EventForwarding eventForwarding = EventForwarding.getInstance(ctx);
450         if(eventForwarding != null) {
451             eventForwarding.addListeners(tldParser.getListeners());
452         }
453         else if(tldParser.getListeners().size() > 0) {
454             throw new TemplateModelException(
455                 "Event listeners specified in the TLD could not be " +
456                 " registered since the web application doesn't have a" +
457                 " listener of class " + EventForwarding.class.getName() +
458                 ". To remedy this, add this element to web.xml:\n" +
459                 "| <listener>\n" +
460                 "| <listener-class>" + EventForwarding.class.getName() + "</listener-class>\n" +
461                 "| </listener>");
462         }
463         return tldParser.getTags();
464     }
465
466     private static final String JavaDoc[] getTldPath(String JavaDoc uri, Map JavaDoc locations)
467     {
468         String JavaDoc[] path = (String JavaDoc[])locations.get(uri);
469         // If location was explicitly defined in web.xml, or discovered in a
470
// JAR file, use it. (Hopefully this is 99% of the cases)
471
if(path != null) {
472             return path;
473         }
474         
475         // If there was no explicit mapping in web.xml, but URI is a
476
// ROOT_REL_URI, return it (JSP.7.6.3.2)
477
if(uri.startsWith("/")) {
478             path = new String JavaDoc[2];
479             path[0] = uri;
480             if(uri.endsWith(".jar") || uri.endsWith(".zip")) {
481                 path[1] = "META-INF/taglib.tld";
482             }
483             return path;
484         }
485
486         return null;
487     }
488
489     private static String JavaDoc resolveRelativeUri(String JavaDoc uri)
490     throws
491         TemplateModelException
492     {
493         // Absolute and root-relative URIs are left as they are.
494
if(uri.startsWith("/") || uri.indexOf("://") != -1) {
495             return uri;
496         }
497         
498         // Otherwise it is a NOROOT_REL_URI, and has to be resolved relative
499
// to current page... We have to obtain the request object to know what
500
// is the URL of the current page (this assumes there's a
501
// HttpRequestHashModel under name FreemarkerServlet.KEY_REQUEST in the
502
// environment...) (JSP.7.6.3.2)
503
TemplateModel reqHash =
504             Environment.getCurrentEnvironment().getVariable(
505                 FreemarkerServlet.KEY_REQUEST_PRIVATE);
506         if(reqHash instanceof HttpRequestHashModel) {
507             HttpServletRequest JavaDoc req =
508                 ((HttpRequestHashModel)reqHash).getRequest();
509             String JavaDoc pi = req.getPathInfo();
510             String JavaDoc reqPath = req.getServletPath();
511             if(reqPath == null) {
512                 reqPath = "";
513             }
514             reqPath += (pi == null ? "" : pi);
515             // We don't care about paths with ".." in them. If the container
516
// wishes to resolve them on its own, let it be.
517
int lastSlash = reqPath.lastIndexOf('/');
518             if(lastSlash != -1) {
519                 return reqPath.substring(0, lastSlash + 1) + uri;
520             }
521             else {
522                 return '/' + uri;
523             }
524         }
525         throw new TemplateModelException(
526             "Can't resolve relative URI " + uri +
527             " as request URL information is unavailable.");
528     }
529     
530     private static final class TldParser extends DefaultHandler JavaDoc {
531         private final Map JavaDoc tags = new HashMap JavaDoc();
532         private final List JavaDoc listeners = new ArrayList JavaDoc();
533         
534         private Locator JavaDoc locator;
535         private StringBuffer JavaDoc buf;
536         private String JavaDoc tagName;
537         private String JavaDoc tagClass;
538
539         Map JavaDoc getTags() {
540             return tags;
541         }
542
543         List JavaDoc getListeners() {
544             return listeners;
545         }
546                 
547         public void setDocumentLocator(Locator JavaDoc locator) {
548             this.locator = locator;
549         }
550
551         public void startElement(
552             String JavaDoc nsuri,
553             String JavaDoc localName,
554             String JavaDoc qName,
555             Attributes JavaDoc atts) {
556             if ("name".equals(qName) || "tagclass".equals(qName) || "tag-class".equals(qName) || "listener-class".equals(qName)) {
557                 buf = new StringBuffer JavaDoc();
558             }
559         }
560
561         public void characters(char[] chars, int off, int len) {
562             if (buf != null) {
563                 buf.append(chars, off, len);
564             }
565         }
566
567         public void endElement(String JavaDoc nsuri, String JavaDoc localName, String JavaDoc qName)
568             throws SAXParseException JavaDoc {
569             if ("name".equals(qName)) {
570                 if(tagName == null) {
571                     tagName = buf.toString().trim();
572                 }
573                 buf = null;
574             }
575             else if ("tagclass".equals(qName) || "tag-class".equals(qName)) {
576                 tagClass = buf.toString().trim();
577                 buf = null;
578             }
579             else if ("tag".equals(qName)) {
580                 try {
581                     tags.put(
582                         tagName,
583                         new TagTransformModel(ClassUtil.forName(tagClass)));
584                     tagName = null;
585                     tagClass = null;
586                 }
587                 catch (IntrospectionException JavaDoc e) {
588                     throw new SAXParseException JavaDoc(
589                         "Can't introspect tag class " + tagClass,
590                         locator,
591                         e);
592                 }
593                 catch (ClassNotFoundException JavaDoc e) {
594                     throw new SAXParseException JavaDoc(
595                         "Can't find tag class " + tagClass,
596                         locator,
597                         e);
598                 }
599             }
600             else if ("listener-class".equals(qName)) {
601                 String JavaDoc listenerClass = buf.toString().trim();
602                 buf = null;
603                 try {
604                     listeners.add(ClassUtil.forName(listenerClass).newInstance());
605                 }
606                 catch(Exception JavaDoc e) {
607                     throw new SAXParseException JavaDoc(
608                         "Can't instantiate listener class " + listenerClass,
609                         locator,
610                         e);
611                 }
612             }
613         }
614     }
615
616     private static final Map JavaDoc dtds = new HashMap JavaDoc();
617     static
618     {
619         // JSP taglib 2.0
620
dtds.put("http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd", "web-jsptaglibrary_2_0.xsd");
621         // JSP taglib 1.2
622
dtds.put("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN", "web-jsptaglibrary_1_2.dtd");
623         dtds.put("http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd", "web-jsptaglibrary_1_2.dtd");
624         // JSP taglib 1.1
625
dtds.put("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN", "web-jsptaglibrary_1_1.dtd");
626         dtds.put("http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd", "web-jsptaglibrary_1_1.dtd");
627         // Servlet 2.4
628
dtds.put("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd", "web-app_2_4.xsd");
629         // Servlet 2.3
630
dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN", "web-app_2_3.dtd");
631         dtds.put("http://java.sun.com/dtd/web-app_2_3.dtd", "web-app_2_3.dtd");
632         // Servlet 2.2
633
dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN", "web-app_2_2.dtd");
634         dtds.put("http://java.sun.com/j2ee/dtds/web-app_2_2.dtd", "web-app_2_2.dtd");
635     }
636     private static final class LocalTaglibDtds implements EntityResolver JavaDoc {
637         public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
638         {
639             String JavaDoc resourceName = (String JavaDoc)dtds.get(publicId);
640             if(resourceName == null)
641             {
642                 resourceName = (String JavaDoc)dtds.get(systemId);
643             }
644             InputStream JavaDoc resourceStream;
645             if(resourceName != null)
646             {
647                 resourceStream = getClass().getResourceAsStream(resourceName);
648             }
649             else
650             {
651                 // Fake an empty stream for unknown DTDs
652
resourceStream = new ByteArrayInputStream JavaDoc(new byte[0]);
653             }
654             InputSource JavaDoc is = new InputSource JavaDoc();
655             is.setPublicId(publicId);
656             is.setSystemId(systemId);
657             is.setByteStream(resourceStream);
658             return is;
659         }
660     }
661 }
662
Popular Tags