Save This Page
Home » freemarker-2.3.13 » freemarker.ext.jsp » [javadoc | source]
    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;
   56   import java.io.ByteArrayInputStream;
   57   import java.io.FilterInputStream;
   58   import java.io.IOException;
   59   import java.io.InputStream;
   60   import java.net.MalformedURLException;
   61   import java.util.ArrayList;
   62   import java.util.HashMap;
   63   import java.util.Iterator;
   64   import java.util.List;
   65   import java.util.Map;
   66   import java.util.Set;
   67   import java.util.zip.ZipEntry;
   68   import java.util.zip.ZipInputStream;
   69   
   70   import javax.servlet.ServletContext;
   71   import javax.servlet.http.HttpServletRequest;
   72   import javax.servlet.jsp.tagext.Tag;
   73   import javax.xml.parsers.ParserConfigurationException;
   74   import javax.xml.parsers.SAXParserFactory;
   75   
   76   import org.xml.sax.Attributes;
   77   import org.xml.sax.EntityResolver;
   78   import org.xml.sax.InputSource;
   79   import org.xml.sax.Locator;
   80   import org.xml.sax.SAXException;
   81   import org.xml.sax.SAXParseException;
   82   import org.xml.sax.XMLReader;
   83   import org.xml.sax.helpers.DefaultHandler;
   84   
   85   import freemarker.core.Environment;
   86   import freemarker.ext.servlet.FreemarkerServlet;
   87   import freemarker.ext.servlet.HttpRequestHashModel;
   88   import freemarker.log.Logger;
   89   import freemarker.template.TemplateHashModel;
   90   import freemarker.template.TemplateModel;
   91   import freemarker.template.TemplateModelException;
   92   import freemarker.template.utility.ClassUtil;
   93   
   94   
   95   
   96   /**
   97    * A hash model associated with a servlet context that can load JSP tag 
   98    * libraries associated with that servlet context. An instance of this class is
   99    * made available in the root data model of templates executed by 
  100    * {@link freemarker.ext.servlet.FreemarkerServlet} under key
  101    * <tt>JspTaglibs</tt>. It can be added to custom servlets as well to enable JSP
  102    * taglib integration in them as well.
  103    * @version $Id: TaglibFactory.java,v 1.26.2.1 2007/05/16 12:13:04 szegedia Exp $
  104    * @author Attila Szegedi
  105    */
  106   public class TaglibFactory implements TemplateHashModel {
  107       private static final Logger logger = Logger.getLogger("freemarker.jsp");
  108   
  109       // No TLDs have been looked up yet
  110       private static final int LOOKUP_NONE = 0;
  111       // Only explicit TLDs in web.xml have been looked up
  112       private static final int LOOKUP_WEB_XML = 1;
  113       // Both explicit TLDs and those in JARs have been looked up
  114       private static final int LOOKUP_JARS = 2;
  115       
  116       private final ServletContext ctx;
  117       private final Map taglibs = new HashMap();
  118       private final Map locations = new HashMap();
  119       private int lookupPhase = LOOKUP_NONE;
  120   
  121       /**
  122        * Creates a new JSP taglib factory that will be used to load JSP taglibs
  123        * for the web application represented by the passed servlet context.
  124        * @param ctx the servlet context whose JSP tag libraries will this factory
  125        * load.
  126        */
  127       public TaglibFactory(ServletContext ctx) {
  128           this.ctx = ctx;
  129       }
  130   
  131       /**
  132        * Retrieves a JSP tag library identified by an URI. The matching of the URI
  133        * to a JSP taglib is done as described in the JSP 1.2 FCS specification.
  134        * @param uri the URI that describes the JSP taglib. It can be any of the
  135        * three forms allowed by the JSP specification: absolute URI, root relative
  136        * URI and non-root relative URI. Note that if a non-root relative URI is
  137        * used it is resolved relative to the URL of the current request. In this
  138        * case, the current request is obtained by looking up a
  139        * {@link HttpRequestHashModel} object named <tt>Request</tt> in the root
  140        * data model. FreemarkerServlet provides this object under the expected
  141        * name, and custom servlets that want to integrate JSP taglib support
  142        * should do the same.
  143        * @return a hash model representing the JSP taglib. Each element of this
  144        * hash model represents a single custom tag from the library, implemented
  145        * as a {@link freemarker.template.TemplateTransformModel}.
  146        */
  147       public TemplateModel get(String uri) throws TemplateModelException {
  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                   // Not found -- in case of NOROOT_REL_URI, let's resolve it and
  166                   // try again.
  167                   String resolvedUri = resolveRelativeUri(uri);
  168                   if(resolvedUri != uri) {
  169                       taglib = (Taglib) taglibs.get(resolvedUri);
  170                       if(taglib != null) {
  171                           return taglib;
  172                       }
  173                       taglib = new Taglib();
  174                       if(taglib.load(resolvedUri, ctx, locations)) {
  175                           taglibs.put(resolvedUri, taglib);
  176                           return taglib;
  177                       }
  178                   }
  179               }
  180               catch(TemplateModelException e) {
  181                   throw e;
  182               }
  183               catch(Exception e) {
  184                   throw new TemplateModelException("Could not load taglib information", e);
  185               }
  186               return null;
  187           }
  188       }
  189   
  190       /**
  191        * Returns false.
  192        */
  193       public boolean isEmpty() {
  194           return false;
  195       }
  196   
  197       private boolean getMoreTaglibLocations() throws MalformedURLException, ParserConfigurationException, IOException, SAXException
  198       {
  199           switch(lookupPhase) {
  200               case LOOKUP_NONE: {
  201                   getLocationsFromWebXml();
  202                   lookupPhase = LOOKUP_WEB_XML;
  203                   return true;
  204               }
  205               case LOOKUP_WEB_XML: {
  206                   getLocationsFromLibJars();
  207                   lookupPhase = LOOKUP_JARS;
  208                   return true;
  209               }
  210               default : {
  211                   return false;
  212               }
  213           }
  214       }
  215       
  216       private void getLocationsFromWebXml() throws MalformedURLException, ParserConfigurationException, IOException, SAXException
  217       {
  218           WebXmlParser webXmlParser = new WebXmlParser(locations);
  219           InputStream in = ctx.getResourceAsStream("/WEB-INF/web.xml");
  220           if (in == null) {
  221               // No /WEB-INF/web.xml - do nothing
  222               return;
  223           }
  224           try {
  225               parseXml(in, ctx.getResource("/WEB-INF/web.xml").toExternalForm(), webXmlParser);
  226           }
  227           finally {
  228               in.close();
  229           }
  230       }
  231       
  232       private static class WebXmlParser extends DefaultHandler {
  233           private final Map locations;
  234           
  235           private StringBuffer buf;
  236           private String uri;
  237           private String location;
  238   
  239           WebXmlParser(Map locations) {
  240               this.locations = locations;
  241           }
  242   
  243           public void startElement(
  244               String nsuri,
  245               String localName,
  246               String qName,
  247               Attributes atts) {
  248               if ("taglib-uri".equals(qName)
  249                   || "taglib-location".equals(qName)) {
  250                   buf = new StringBuffer();
  251               }
  252           }
  253   
  254           public void characters(char[] chars, int off, int len) {
  255               if (buf != null) {
  256                   buf.append(chars, off, len);
  257               }
  258           }
  259   
  260           public void endElement(String nsuri, String localName, String qName) {
  261               if ("taglib-uri".equals(qName)) {
  262                   uri = buf.toString().trim();
  263                   buf = null;
  264               }
  265               else if ("taglib-location".equals(qName)) {
  266                   location = buf.toString().trim();
  267                   if(location.indexOf("://") == -1 && !location.startsWith("/")) {
  268                       location = "/WEB-INF/" + location;
  269                   }
  270                   buf = null;
  271               }
  272               else if ("taglib".equals(qName)) {
  273                   String[] loc = new String[2];
  274                   loc[0] = location;
  275                   if(location.endsWith(".jar") || location.endsWith(".zip")) {
  276                       loc[1] = "META-INF/taglib.tld";
  277                   }
  278                   locations.put(uri, loc);
  279                   if(logger.isDebugEnabled()) {
  280                       logger.debug("web.xml assigned URI " + uri + " to location " + loc[0] + (loc[1] != null ? "!" + loc[1] : ""));
  281                   }
  282               }
  283           }
  284       }
  285   
  286   
  287       private void getLocationsFromLibJars() throws ParserConfigurationException, IOException, SAXException
  288       {
  289           Set libs = ctx.getResourcePaths("/WEB-INF/lib");
  290           for (Iterator iter = libs.iterator(); iter.hasNext();) {
  291               String path = (String) iter.next();
  292               if(path.endsWith(".jar") || path.endsWith(".zip")) {
  293                   ZipInputStream zin = new ZipInputStream(ctx.getResourceAsStream(path));
  294                   // Make stream uncloseable by XML parsers
  295                   InputStream uin = new FilterInputStream(zin) {
  296                       public void close() {
  297                       }
  298                   };
  299                   try {
  300                       for(;;) {
  301                           ZipEntry ze = zin.getNextEntry();
  302                           if(ze == null) {
  303                               break;
  304                           }
  305                           String zname = ze.getName();
  306                           if(zname.startsWith("META-INF/") && zname.endsWith(".tld")) {
  307                               String url = "jar:" + 
  308                                   ctx.getResource(path).toExternalForm() + 
  309                                   "!" + zname;
  310                               String loc = getTldUri(uin, url);
  311                               if(loc != null) {
  312                                   locations.put(loc, new String[] { path, zname });
  313                                   if(logger.isDebugEnabled()) {
  314                                       logger.debug("libjar assigned URI " + loc + " to location " + path + "!" + zname);
  315                                   }
  316                               } 
  317                           }
  318                       }
  319                   }
  320                   finally {
  321                       zin.close();
  322                   }
  323               }
  324           }
  325       }
  326   
  327       private String getTldUri(InputStream in, String url) throws ParserConfigurationException, IOException, SAXException 
  328       {
  329           TldUriReader tur = new TldUriReader(); 
  330           parseXml(in, url, tur);
  331           return tur.getUri();
  332       }
  333       
  334       private static class TldUriReader extends DefaultHandler {
  335   
  336           private StringBuffer buf;
  337           private String uri;
  338   
  339           TldUriReader() {
  340           }
  341   
  342           String getUri() {
  343               return uri;
  344           }
  345           
  346           public void startElement(
  347               String nsuri,
  348               String localName,
  349               String qName,
  350               Attributes atts) {
  351               if ("uri".equals(qName)) {
  352                   buf = new StringBuffer();
  353               }
  354           }
  355   
  356           public void characters(char[] chars, int off, int len) {
  357               if (buf != null) {
  358                   buf.append(chars, off, len);
  359               }
  360           }
  361   
  362           public void endElement(String nsuri, String localName, String qName) {
  363               if ("uri".equals(qName)) {
  364                   uri = buf.toString().trim();
  365                   buf = null;
  366               }
  367           }
  368       }
  369   
  370       private static void parseXml(InputStream in, String url, DefaultHandler handler)
  371       throws 
  372           ParserConfigurationException, IOException, SAXException
  373       {
  374           InputSource is = new InputSource();
  375           is.setByteStream(in);
  376           is.setSystemId(url);
  377           SAXParserFactory factory = SAXParserFactory.newInstance();
  378           factory.setNamespaceAware(false);
  379           factory.setValidating(false);
  380           XMLReader reader = factory.newSAXParser().getXMLReader();
  381           reader.setEntityResolver(new LocalTaglibDtds());
  382           reader.setContentHandler(handler);
  383           reader.setErrorHandler(handler);
  384           reader.parse(is);
  385       }
  386   
  387       private static final class Taglib implements TemplateHashModel {
  388           private Map tags;
  389   
  390           Taglib() {
  391           }
  392   
  393           public TemplateModel get(String key) {
  394               return (TemplateModel)tags.get(key);
  395           }
  396   
  397           public boolean isEmpty() {
  398               return false;
  399           }
  400           
  401           boolean load(String uri, ServletContext ctx, Map locations)
  402           throws 
  403               ParserConfigurationException, 
  404               IOException, 
  405               SAXException,
  406               TemplateModelException
  407           {
  408               String[] tldPath = getTldPath(uri, locations);
  409               if(tldPath != null) {
  410                   if(logger.isDebugEnabled()) {
  411                       logger.debug("Loading taglib " + uri + " from location " + 
  412                           tldPath[0] + (tldPath[1] != null ? "!" + tldPath[1] : ""));
  413                   }
  414                   tags = loadTaglib(tldPath, ctx);
  415                   if(tags != null) {
  416                       locations.remove(uri);
  417                       return true;
  418                   }
  419               }
  420               return false;
  421           }
  422       }
  423   
  424       private static final Map loadTaglib(String[] tldPath, ServletContext ctx)
  425       throws
  426           ParserConfigurationException, IOException, SAXException, TemplateModelException
  427       {
  428           String filePath = tldPath[0]; 
  429           TldParser tldParser = new TldParser();
  430           InputStream in = ctx.getResourceAsStream(filePath);
  431           if(in == null) {
  432               throw new TemplateModelException("Could not find webapp resource " + filePath);
  433           }
  434           String url = ctx.getResource(filePath).toExternalForm();
  435           try {
  436               String jarPath = tldPath[1];
  437               if(jarPath != null) {
  438                   ZipInputStream zin = new ZipInputStream(in);
  439                   for(;;) {
  440                       ZipEntry ze = zin.getNextEntry();
  441                       if(ze == null) {
  442                           throw new TemplateModelException("Could not find JAR entry " + jarPath + " inside webapp resource " + filePath);
  443                       }
  444                       String zname = ze.getName(); 
  445                       if(zname.equals(jarPath)) {
  446                           parseXml(zin, "jar:" + url + "!" + zname, tldParser);
  447                           break;
  448                       }
  449                   }
  450               }
  451               else {
  452                   parseXml(in, url, tldParser);
  453               }
  454           }
  455           finally {
  456               in.close();
  457           }
  458           EventForwarding eventForwarding = EventForwarding.getInstance(ctx);
  459           if(eventForwarding != null) {
  460               eventForwarding.addListeners(tldParser.getListeners());
  461           }
  462           else if(tldParser.getListeners().size() > 0) {
  463               throw new TemplateModelException(
  464                   "Event listeners specified in the TLD could not be " +
  465                   " registered since the web application doesn't have a" +
  466                   " listener of class " + EventForwarding.class.getName() + 
  467                   ". To remedy this, add this element to web.xml:\n" +
  468                   "| <listener>\n" +
  469                   "|   <listener-class>" + EventForwarding.class.getName() + "</listener-class>\n" +
  470                   "| </listener>");
  471           }
  472           return tldParser.getTags();
  473       }
  474   
  475       private static final String[] getTldPath(String uri, Map locations)
  476       {
  477           String[] path = (String[])locations.get(uri);
  478           // If location was explicitly defined in web.xml, or discovered in a
  479           // JAR file, use it. (Hopefully this is 99% of the cases)
  480           if(path != null) {
  481               return path;
  482           }
  483           
  484           // If there was no explicit mapping in web.xml, but URI is a 
  485           // ROOT_REL_URI, return it (JSP.7.6.3.2)
  486           if(uri.startsWith("/")) {
  487               path = new String[2];
  488               path[0] = uri;
  489               if(uri.endsWith(".jar") || uri.endsWith(".zip")) {
  490                   path[1] = "META-INF/taglib.tld";
  491               }
  492               return path;
  493           }
  494   
  495           // Unmapped NOROOT_REL_URI - do nothing with it, so eventually get() 
  496           // will resolve it and try again
  497           return null;
  498       }
  499   
  500       private static String resolveRelativeUri(String uri)
  501       throws
  502           TemplateModelException
  503       {
  504           // Absolute and root-relative URIs are left as they are.
  505           if(uri.startsWith("/") || uri.indexOf("://") != -1) {
  506               return uri;
  507           }
  508           
  509           // Otherwise it is a NOROOT_REL_URI, and has to be resolved relative
  510           // to current page... We have to obtain the request object to know what
  511           // is the URL of the current page (this assumes there's a 
  512           // HttpRequestHashModel under name FreemarkerServlet.KEY_REQUEST in the
  513           // environment...) (JSP.7.6.3.2)
  514           TemplateModel reqHash = 
  515               Environment.getCurrentEnvironment().getVariable(
  516                   FreemarkerServlet.KEY_REQUEST_PRIVATE);
  517           if(reqHash instanceof HttpRequestHashModel) {
  518               HttpServletRequest req  = 
  519                   ((HttpRequestHashModel)reqHash).getRequest();
  520               String pi = req.getPathInfo();
  521               String reqPath = req.getServletPath();
  522               if(reqPath == null) {
  523                   reqPath = "";
  524               }
  525               reqPath += (pi == null ? "" : pi);
  526               // We don't care about paths with ".." in them. If the container
  527               // wishes to resolve them on its own, let it be.
  528               int lastSlash = reqPath.lastIndexOf('/');
  529               if(lastSlash != -1) {
  530                   return reqPath.substring(0, lastSlash + 1) + uri;
  531               }
  532               else {
  533                   return '/' + uri;
  534               }
  535           }
  536           throw new TemplateModelException(
  537               "Can't resolve relative URI " + uri + 
  538               " as request URL information is unavailable.");
  539       }
  540       
  541       private static final class TldParser extends DefaultHandler {
  542           private final Map tags = new HashMap();
  543           private final List listeners = new ArrayList();
  544           
  545           private Locator locator;
  546           private StringBuffer buf;
  547           private String tagName;
  548           private String tagClassName;
  549   
  550           Map getTags() {
  551               return tags;
  552           }
  553   
  554           List getListeners() {
  555               return listeners;
  556           }
  557                   
  558           public void setDocumentLocator(Locator locator) {
  559               this.locator = locator;
  560           }
  561   
  562           public void startElement(
  563               String nsuri,
  564               String localName,
  565               String qName,
  566               Attributes atts) {
  567               if ("name".equals(qName) || "tagclass".equals(qName) || "tag-class".equals(qName) || "listener-class".equals(qName)) {
  568                   buf = new StringBuffer();
  569               }
  570           }
  571   
  572           public void characters(char[] chars, int off, int len) {
  573               if (buf != null) {
  574                   buf.append(chars, off, len);
  575               }
  576           }
  577   
  578           public void endElement(String nsuri, String localName, String qName)
  579               throws SAXParseException {
  580               if ("name".equals(qName)) {
  581                   if(tagName == null) {
  582                       tagName = buf.toString().trim();
  583                   }
  584                   buf = null;
  585               }
  586               else if ("tagclass".equals(qName) || "tag-class".equals(qName)) {
  587                   tagClassName = buf.toString().trim();
  588                   buf = null;
  589               }
  590               else if ("tag".equals(qName)) {
  591                   try {
  592                       Class tagClass = ClassUtil.forName(tagClassName);
  593                       TemplateModel impl;
  594                       if(Tag.class.isAssignableFrom(tagClass)) {
  595                           impl = new TagTransformModel(tagClass); 
  596                       }
  597                       else {
  598                           impl = new SimpleTagDirectiveModel(tagClass); 
  599                       }
  600                       tags.put(tagName, impl);
  601                       tagName = null;
  602                       tagClassName = null;
  603                   }
  604                   catch (IntrospectionException e) {
  605                       throw new SAXParseException(
  606                           "Can't introspect tag class " + tagClassName,
  607                           locator,
  608                           e);
  609                   }
  610                   catch (ClassNotFoundException e) {
  611                       throw new SAXParseException(
  612                           "Can't find tag class " + tagClassName,
  613                           locator,
  614                           e);
  615                   }
  616               }
  617               else if ("listener-class".equals(qName)) {
  618                   String listenerClass = buf.toString().trim();
  619                   buf = null;
  620                   try {
  621                       listeners.add(ClassUtil.forName(listenerClass).newInstance());
  622                   }
  623                   catch(Exception e) {
  624                       throw new SAXParseException(
  625                           "Can't instantiate listener class " + listenerClass,
  626                           locator,
  627                           e);
  628                   }
  629               }
  630           }
  631       }
  632   
  633       private static final Map dtds = new HashMap();
  634       static
  635       {
  636           // JSP taglib 2.1
  637           dtds.put("http://java.sun.com/xml/ns/jee/web-jsptaglibrary_2_1.xsd", "web-jsptaglibrary_2_1.xsd");
  638           // JSP taglib 2.0
  639           dtds.put("http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd", "web-jsptaglibrary_2_0.xsd");
  640           // JSP taglib 1.2
  641           dtds.put("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN", "web-jsptaglibrary_1_2.dtd");
  642           dtds.put("http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd", "web-jsptaglibrary_1_2.dtd");
  643           // JSP taglib 1.1
  644           dtds.put("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN", "web-jsptaglibrary_1_1.dtd");
  645           dtds.put("http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd", "web-jsptaglibrary_1_1.dtd");
  646           // Servlet 2.5
  647           dtds.put("http://java.sun.com/xml/ns/jee/web-app_2_5.xsd", "web-app_2_5.xsd");
  648           // Servlet 2.4
  649           dtds.put("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd", "web-app_2_4.xsd");
  650           // Servlet 2.3
  651           dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN", "web-app_2_3.dtd");
  652           dtds.put("http://java.sun.com/dtd/web-app_2_3.dtd", "web-app_2_3.dtd");
  653           // Servlet 2.2
  654           dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN", "web-app_2_2.dtd");
  655           dtds.put("http://java.sun.com/j2ee/dtds/web-app_2_2.dtd", "web-app_2_2.dtd");
  656       }
  657       private static final class LocalTaglibDtds implements EntityResolver {
  658           public InputSource resolveEntity(String publicId, String systemId)
  659           {
  660               String resourceName = (String)dtds.get(publicId);
  661               if(resourceName == null)
  662               {
  663                   resourceName = (String)dtds.get(systemId);
  664               }
  665               InputStream resourceStream;
  666               if(resourceName != null)
  667               {
  668                   resourceStream = getClass().getResourceAsStream(resourceName);
  669               }
  670               else
  671               {
  672                   // Fake an empty stream for unknown DTDs 
  673                   resourceStream = new ByteArrayInputStream(new byte[0]);
  674               }
  675               InputSource is = new InputSource();
  676               is.setPublicId(publicId);
  677               is.setSystemId(systemId);
  678               is.setByteStream(resourceStream);
  679               return is;
  680           }
  681       }
  682   }

Save This Page
Home » freemarker-2.3.13 » freemarker.ext.jsp » [javadoc | source]