Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » runtime » [javadoc | source]
    1   /*
    2    * The Apache Software License, Version 1.1
    3    *
    4    * Copyright (c) 1999 The Apache Software Foundation.  All rights
    5    * reserved.
    6    *
    7    * Redistribution and use in source and binary forms, with or without
    8    * modification, are permitted provided that the following conditions
    9    * are met:
   10    *
   11    * 1. Redistributions of source code must retain the above copyright
   12    *    notice, this list of conditions and the following disclaimer.
   13    *
   14    * 2. Redistributions in binary form must reproduce the above copyright
   15    *    notice, this list of conditions and the following disclaimer in
   16    *    the documentation and/or other materials provided with the
   17    *    distribution.
   18    *
   19    * 3. The end-user documentation included with the redistribution, if
   20    *    any, must include the following acknowlegement:
   21    *       "This product includes software developed by the
   22    *        Apache Software Foundation (http://www.apache.org/)."
   23    *    Alternately, this acknowlegement may appear in the software itself,
   24    *    if and wherever such third-party acknowlegements normally appear.
   25    *
   26    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   27    *    Foundation" must not be used to endorse or promote products derived
   28    *    from this software without prior written permission. For written
   29    *    permission, please contact apache@apache.org.
   30    *
   31    * 5. Products derived from this software may not be called "Apache"
   32    *    nor may "Apache" appear in their names without prior written
   33    *    permission of the Apache Group.
   34    *
   35    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   36    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   37    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   38    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   39    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   40    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   41    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   42    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   43    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   44    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   45    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   46    * SUCH DAMAGE.
   47    * ====================================================================
   48    *
   49    * This software consists of voluntary contributions made by many
   50    * individuals on behalf of the Apache Software Foundation.  For more
   51    * information on the Apache Software Foundation, please see
   52    * <http://www.apache.org/>.
   53    *
   54    */
   55   
   56   package org.apache.jasper.runtime;
   57   
   58   import java.io.FileInputStream;
   59   import java.io.ByteArrayOutputStream;
   60   import java.io.File;
   61   import java.io.FileNotFoundException;
   62   import java.io.InputStream;
   63   import java.io.IOException;
   64   
   65   import java.util.Hashtable;
   66   import java.util.Vector;
   67   import java.util.zip.ZipFile;
   68   import java.util.zip.ZipEntry;
   69   
   70   import javax.servlet.ServletContext;
   71   import javax.servlet.http.HttpServletRequest;
   72   import javax.servlet.http.HttpServletResponse;
   73   
   74   import org.apache.jasper.JasperException;
   75   import org.apache.jasper.Constants;
   76   import org.apache.jasper.JspEngineContext;
   77   import org.apache.jasper.Options;
   78   import org.apache.jasper.compiler.Compiler;
   79   
   80   /**
   81    * This is a class loader that loads JSP files as though they were
   82    * Java classes. It calls the compiler to compile the JSP file into a
   83    * servlet and then loads the generated class.
   84    *
   85    * This code is quite fragile and needs careful
   86    * treatment/handling/revisiting. I know this doesn't work very well
   87    * right now for:
   88    *
   89    * 	(a) inner classes
   90    *	(b) does not work at all for tag handlers that have inner
   91    *          classes; but that is likely to change with the new JSP PR2
   92    *          spec.
   93    *
   94    * @author Anil K. Vijendran
   95    * @author Harish Prabandham
   96    */
   97   public class JspLoader extends ClassLoader {
   98       Hashtable loadedJSPs = new Hashtable();
   99       ClassLoader parent;
  100       ServletContext context;
  101       Options options;
  102   
  103   
  104       JspLoader(ServletContext context,
  105                 ClassLoader cl, Options options)
  106       {
  107   	//	super(cl); // JDK 1.2 FIXME
  108   	super();
  109           this.context = context;
  110   	this.parent = cl;
  111           this.options = options;
  112       }
  113   
  114       public Class getJspServletClass(String name) {
  115   	return (Class) loadedJSPs.get(name);
  116       }
  117   
  118       protected synchronized Class loadClass(String name, boolean resolve)
  119   	throws ClassNotFoundException
  120       {
  121   	// First, check if the class has already been loaded
  122   	Class c = findLoadedClass(name);
  123   	if (c == null) {
  124   	    try {
  125   		//System.out.println("JspLoader: parent = " + parent);
  126   		if (parent != null) {
  127   		    c = parent.loadClass(name);
  128                   }
  129   		else {
  130   		    c = findSystemClass(name);
  131                   }
  132   	    } catch (ClassNotFoundException e) {
  133   		// If still not found, then call findClass in order
  134   		// to find the class.
  135   		try {
  136   		    c = findClass(name);
  137   		} catch (ClassNotFoundException ex) {
  138   		    throw ex;
  139   		}
  140   	    }
  141   	}
  142   	if (resolve) {
  143   	    resolveClass(c);
  144   	}
  145   	return c;
  146       }
  147   
  148       protected Class findClass(String className) throws ClassNotFoundException {
  149   	try {
  150   	    int beg = className.lastIndexOf(".") == -1 ? 0 :
  151   		className.lastIndexOf(".")+1;
  152   	    int end = className.lastIndexOf("_jsp_");
  153   
  154   	    if (end <= 0) {     // this is a class that the JSP file depends on (example: class
  155                                   // in a tag library)
  156                   byte[] classBytes = loadClassDataFromJar(className);
  157                   if (classBytes == null)
  158                       throw new ClassNotFoundException(className);
  159                   return defClass(className, classBytes);
  160   	    } else {
  161                   String fileName = null;
  162                   String outputDir = options.scratchDir().toString();
  163   
  164                   if (className.indexOf('$', end) != -1) {
  165                       // this means we're loading an inner class
  166                       fileName = outputDir + File.separatorChar +
  167                           className.replace('.', File.separatorChar) + ".class";
  168                   } else {
  169                       fileName = className.substring(beg, end) + ".class";
  170                       fileName = outputDir + File.separatorChar + fileName;
  171                   }
  172                   FileInputStream fin = new FileInputStream(fileName);
  173                   ByteArrayOutputStream baos = new ByteArrayOutputStream();
  174                   byte buf[] = new byte[1024];
  175                   for(int i = 0; (i = fin.read(buf)) != -1; )
  176                       baos.write(buf, 0, i);
  177                   fin.close();
  178                   baos.close();
  179                   byte[] classBytes = baos.toByteArray();
  180                   return defClass(className, classBytes);
  181               }
  182   	} catch (Exception ex) {
  183   	    throw new ClassNotFoundException(Constants.getString(
  184   	    				     "jsp.error.unable.loadclass",
  185   					      new Object[] {className}));
  186   	}
  187       }
  188   
  189       /**
  190        * Just a short hand for defineClass now... I suspect we might need to
  191        * make this public at some point of time.
  192        */
  193       private final Class defClass(String className, byte[] classData) {
  194           return defineClass(className, classData, 0, classData.length);
  195       }
  196   
  197       /*  Check if we need to reload a JSP page.
  198        *
  199        *  Side-effect: re-compile the JSP page.
  200        *
  201        *  @param classpath explicitly set the JSP compilation path.
  202        *  @return true if JSP files is newer
  203        */
  204       public boolean loadJSP(String name, String classpath, boolean isErrorPage,
  205                              HttpServletRequest req, HttpServletResponse res)
  206   	throws JasperException, FileNotFoundException
  207       {
  208   	Class jspClass = (Class) loadedJSPs.get(name);
  209   	boolean firstTime = jspClass == null;
  210   
  211           JspEngineContext ctxt = new JspEngineContext(this, classpath,
  212                                                        context, name,
  213                                                        isErrorPage, options,
  214                                                        req, res);
  215   	boolean outDated = false;
  216   
  217           Compiler compiler = ctxt.createCompiler();
  218   
  219           try {
  220               outDated = compiler.compile();
  221           } catch (FileNotFoundException ex) {
  222               throw ex;
  223           } catch (JasperException ex) {
  224               throw ex;
  225           } catch (Exception ex) {
  226               throw new JasperException(Constants.getString("jsp.error.unable.compile"),
  227                                         ex);
  228           }
  229   
  230   	// Reload only if it's outdated
  231   	if((jspClass == null) || outDated) {
  232   	    try {
  233   		jspClass = loadClass(ctxt.getFullClassName(), true);
  234   	    } catch (ClassNotFoundException cex) {
  235   		throw new JasperException(Constants.getString("jsp.error.unable.load"),
  236   					  cex);
  237   	    }
  238   	    loadedJSPs.put(name, jspClass);
  239   	}
  240   
  241   	return outDated;
  242       }
  243   
  244       private Vector jars = new Vector();
  245   
  246       private byte[] loadClassDataFromJar(String className) {
  247           String entryName = className.replace('.','/')+".class";
  248   	InputStream classStream = null;
  249   
  250           for(int i = 0; i < jars.size(); i++) {
  251               File thisFile = new File((String) jars.elementAt(i));
  252               try {
  253                   // check if it exists...
  254                   if (!thisFile.exists())
  255                       return null;
  256   
  257                   if (thisFile.isFile()) {
  258                       ZipFile zip = new ZipFile(thisFile);
  259                       ZipEntry entry = zip.getEntry(entryName);
  260                       if (entry != null) {
  261   			classStream = zip.getInputStream(entry);
  262                           byte[] classData = getClassData(classStream);
  263   			zip.close();
  264   			return classData;
  265   		    } else {
  266   			zip.close();
  267   		    }
  268                   } else { // its a directory...
  269                       File classFile = new File(thisFile,
  270                                                 entryName.replace('/', File.separatorChar));
  271                       if (classFile.exists()) {
  272                           classStream = new FileInputStream(classFile);
  273                           byte[] classData = getClassData(classStream);
  274                           classStream.close();
  275                           return classData;
  276                       }
  277                   }
  278               } catch (IOException ioe) {
  279                   return null;
  280               }
  281           }
  282   
  283           return null;
  284       }
  285   
  286       private byte[] getClassData(InputStream istream) throws IOException {
  287   	byte[] buf = new byte[1024];
  288   	ByteArrayOutputStream bout = new ByteArrayOutputStream();
  289   	int num = 0;
  290   	while((num = istream.read(buf)) != -1) {
  291   	    bout.write(buf, 0, num);
  292   	}
  293   
  294   	return bout.toByteArray();
  295       }
  296   
  297   
  298       public void addJar(String jarFileName) throws IOException {
  299           if (!jars.contains(jarFileName)) {
  300               Constants.message("jsp.message.adding_jar",
  301                                 new Object[] { jarFileName },
  302                                 Constants.MED_VERBOSITY);
  303   
  304               jars.addElement(jarFileName);
  305           }
  306       }
  307   
  308       public String getClassPath() {
  309           StringBuffer cpath = new StringBuffer();
  310           String sep = System.getProperty("path.separator");
  311   
  312           for(int i = 0; i < jars.size(); i++) {
  313               cpath.append((String)jars.elementAt(i)+sep);
  314           }
  315   
  316           return cpath.toString();
  317       }
  318   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » runtime » [javadoc | source]