Package org.jboss.web.tomcat.service.jasper

Source Code of org.jboss.web.tomcat.service.jasper.TagLibCache

/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.web.tomcat.service.jasper;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import javax.servlet.ServletContext;

import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Localizer;
import org.apache.jasper.compiler.TldLocationsCache;
import org.apache.jasper.xmlparser.ParserUtils;
import org.apache.jasper.xmlparser.TreeNode;
import org.jboss.logging.Logger;

/**
* A prototype TagLibCache that allows one to obtain shared tlds from the
* jbossweb sar conf/tlds directory.
* @author Scott.Stark@jboss.org
* @version $Revision: 85945 $
*/
public class TagLibCache extends TldLocationsCache
{
   private static final String WEB_XML = "/WEB-INF/web.xml";
   private static final String JAR_FILE_SUFFIX = ".jar";

   private static Logger log = Logger.getLogger(TagLibCache.class);

   private ServletContext ctx;
   private HashMap mappings;
   private ArrayList tagLibJars;

   public TagLibCache(ServletContext ctx, ArrayList tagLibJars)
   {
      super(ctx, true);
      this.ctx = ctx;
      this.tagLibJars = tagLibJars;
   }

   /**
    * Gets the 'location' of the TLD associated with the given taglib 'uri'.
    *
    * Returns null if the uri is not associated with any tag library 'exposed'
    * in the web application. A tag library is 'exposed' either explicitly in
    * web.xml or implicitly via the uri tag in the TLD of a taglib deployed in a
    * jar file (WEB-INF/lib).
    * @param uri The taglib uri
    * @return An array of two Strings: The first element denotes the real path
    *         to the TLD. If the path to the TLD points to a jar file, then the
    *         second element denotes the name of the TLD entry in the jar file.
    *         Returns null if the uri is not associated with any tag library
    *         'exposed' in the web application.
    */
   public String[] getLocation(String uri) throws JasperException
   {
      if (mappings == null)
         init();
      String[] locations = (String[]) mappings.get(uri);
      return locations;
   }

   private synchronized void init() throws JasperException
   {
     if (mappings != null)
     {
       return;
     }

     HashMap tmpMappings = null;
      try
      {
         tmpMappings = new HashMap();
         processWebDotXml(tmpMappings);
         loadStandardTlds(tmpMappings);
         processTldsInFileSystem("/WEB-INF/", tmpMappings);
      }
      catch (Exception ex)
      {
         String msg = Localizer.getMessage("jsp.error.internal.tldinit", ex.getMessage());
         throw new JasperException(msg, ex);
      }
      finally
      {
        mappings = tmpMappings;
      }
   }

   /*
    * Populates taglib map described in web.xml.
    */
   protected void processWebDotXml(Map tmpMappings) throws Exception
   {

      InputStream is = null;

      try
      {
         // Acquire input stream to web application deployment descriptor
         String altDDName = (String) ctx.getAttribute(Constants.ALT_DD_ATTR);
         if (altDDName != null)
         {
            try
            {
               is = new FileInputStream(altDDName);
            }
            catch (FileNotFoundException e)
            {
               log.warn(Localizer.getMessage("jsp.error.internal.filenotfound",
                  altDDName));
            }
         }
         else
         {
            is = ctx.getResourceAsStream(WEB_XML);
            if (is == null)
            {
               log.warn(Localizer.getMessage("jsp.error.internal.filenotfound",
                  WEB_XML));
            }
         }

         if (is == null)
         {
            return;
         }

         // Parse the web application deployment descriptor
         TreeNode webtld = null;
         // altDDName is the absolute path of the DD
         if (altDDName != null)
         {
            webtld = new ParserUtils().parseXMLDocument(altDDName, is);
         }
         else
         {
            webtld = new ParserUtils().parseXMLDocument(WEB_XML, is);
         }

         // Allow taglib to be an element of the root or jsp-config (JSP2.0)
         TreeNode jspConfig = webtld.findChild("jsp-config");
         if (jspConfig != null)
         {
            webtld = jspConfig;
         }
         Iterator taglibs = webtld.findChildren("taglib");
         while (taglibs.hasNext())
         {

            // Parse the next <taglib> element
            TreeNode taglib = (TreeNode) taglibs.next();
            String tagUri = null;
            String tagLoc = null;
            TreeNode child = taglib.findChild("taglib-uri");
            if (child != null)
               tagUri = child.getBody();
            child = taglib.findChild("taglib-location");
            if (child != null)
               tagLoc = child.getBody();

            // Save this location if appropriate
            if (tagLoc == null)
               continue;
            if (uriType(tagLoc) == NOROOT_REL_URI)
               tagLoc = "/WEB-INF/" + tagLoc;
            String tagLoc2 = null;
            if (tagLoc.endsWith(JAR_FILE_SUFFIX))
            {
               tagLoc = ctx.getResource(tagLoc).toString();
               tagLoc2 = "META-INF/taglib.tld";
            }
            tmpMappings.put(tagUri, new String[]{tagLoc, tagLoc2}); // SYNC
         }
      }
      finally
      {
         if (is != null)
         {
            try
            {
               is.close();
            }
            catch (Throwable t)
            {
            }
         }
      }
   }

   protected void loadStandardTlds(Map tmpMappings) throws MalformedURLException // SYNC
   {
      if( tagLibJars.size() == 0 )
         return;

      // Locate the conf/web.xml
      ClassLoader loader = Thread.currentThread().getContextClassLoader();
      URL web = loader.getResource("server.xml");
      URL sarURL = new URL(web, ".");
      for(int n = 0; n < tagLibJars.size(); n ++)
      {
         String jarPath = (String) tagLibJars.get(n);
         try
         {
            URL url = new URL(sarURL, jarPath);
            String resourcePath = url.toString();
            log.debug("Scanning for tlds in: "+resourcePath);
            URLConnection conn = url.openConnection();
            conn.setUseCaches(false);
            scanJar(conn, resourcePath, true, tmpMappings); // SYNC
         }
         catch (Exception e)
         {
            log.debug("Failed to scan: "+jarPath, e);
         }
      }
   }

   /*
    * Searches the filesystem under /WEB-INF for any TLD files, and adds
    * an implicit map entry to the taglib map for any TLD that has a <uri>
    * element.
    */
   protected void processTldsInFileSystem(String startPath, Map tmpMappings) // SYNC
      throws Exception
   {

      Set dirList = ctx.getResourcePaths(startPath);
      if (dirList != null)
      {
         Iterator it = dirList.iterator();
         while (it.hasNext())
         {
            String path = (String) it.next();
            if (path.endsWith("/"))
            {
               processTldsInFileSystem(path, tmpMappings); // SYNC
            }
            if( path.endsWith(".jar") )
            {
               URL resURL = ctx.getResource(path);
               URLConnection conn = resURL.openConnection();
               conn.setUseCaches(false);
               this.scanJar(conn, resURL.toString(), false, tmpMappings); // SYNC
            }
            else if ( path.endsWith(".tld") == true )
            {
               InputStream stream = ctx.getResourceAsStream(path);
               String uri = null;
               try
               {
                  uri = getUriFromTld(path, stream);
               }
               finally
               {
                  if (stream != null)
                  {
                     try
                     {
                        stream.close();
                     }
                     catch (Throwable t)
                     {
                        // do nothing
                     }
                  }
               }
               // Add implicit map entry only if its uri is not already
               // present in the map
               if (uri != null && tmpMappings.get(uri) == null) // SYNC
               {
                  tmpMappings.put(uri, new String[]{path, null}); // SYNC
               }
            }
         }
      }
   }

   /**
    * Scans the given JarInputStream for TLD files located in META-INF (or a
    * subdirectory of it), adding an implicit map entry to the taglib map for
    * any TLD that has a <uri> element.
    * @param conn - the
    * @param ignore true if any exceptions raised when processing the given JAR
    * should be ignored, false otherwise
    */
   private void scanJar(URLConnection conn, String resourcePath, boolean ignore, Map tmpMappings) // SYNC
      throws JasperException, IOException
   {
      InputStream connIS = conn.getInputStream();
      JarInputStream jis = new JarInputStream(connIS);
      try
      {
         JarEntry entry = jis.getNextJarEntry();
         while( entry != null )
         {
            String name = entry.getName();
            if( name.endsWith(".tld") == false )
            {
               entry = jis.getNextJarEntry();
               continue;
            }

            EntryInputStream eis = new EntryInputStream(jis);
            String uri = getUriFromTld(resourcePath, eis);
            // Add implicit map entry only if its uri is not already
            // present in the map
            if (uri != null && tmpMappings.get(uri) == null) // SYNC
            {
               tmpMappings.put(uri, new String[]{resourcePath, name}); // SYNC
            }
            entry = jis.getNextJarEntry();
         }
      }
      catch (Exception ex)
      {
         if (!ignore)
         {
            throw new JasperException(ex);
         }
      }
      finally
      {
         if( jis != null )
         {
            try
            {
               jis.close();
            }
            catch (Throwable t)
            {
               // ignore
            }
         }

         if (connIS != null)
         {
            try
            {
               connIS.close();
            }
            catch (Throwable t)
            {
               // ignore
            }
         }
      }
   }

   /*
    * Returns the value of the uri element of the given TLD, or null if the
    * given TLD does not contain any such element.
    */
   private String getUriFromTld(String resourcePath, InputStream in)
      throws JasperException
   {
      // Parse the tag library descriptor at the specified resource path
      TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath, in);
      TreeNode uri = tld.findChild("uri");
      if (uri != null)
      {
         String body = uri.getBody();
         if (body != null)
            return body;
      }

      return null;
   }

   /**
    * Used to ignore the close on the jar entry input stream since this
    * closes the jar stream, not just the entry.
    */
   static class EntryInputStream extends InputStream
   {
      private JarInputStream jis;
      EntryInputStream(JarInputStream jis)
      {
         this.jis = jis;
      }

      public int read() throws IOException
      {
         return jis.read();
      }

      public int available() throws IOException
      {
         return jis.available();
      }

      public void close() throws IOException
      {
        
      }

      public void reset() throws IOException
      {
         jis.reset();
      }

      public boolean markSupported()
      {
         return jis.markSupported();
      }

      public synchronized void mark(int readlimit)
      {
         jis.mark(readlimit);
      }

      public long skip(long n) throws IOException
      {
         return jis.skip(n);
      }

      public int read(byte b[], int off, int len) throws IOException
      {
         return jis.read(b, off, len);
      }
   }
}
TOP

Related Classes of org.jboss.web.tomcat.service.jasper.TagLibCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.