| 
What this is
 Other links
 The source code
/*
 *  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.apache.jasper.servlet;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SingleThreadModel;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspFactory;
import org.apache.jasper.Constants;
import org.apache.jasper.EmbededServletOptions;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.JspEngineContext;
import org.apache.jasper.Options;
import org.apache.jasper.compiler.Compiler;
import org.apache.jasper.compiler.Mangler;
import org.apache.jasper.runtime.HttpJspBase;
import org.apache.jasper.runtime.JspFactoryImpl;
import org.apache.tomcat.util.log.Log;
/**
 * The JSP engine (a.k.a Jasper)! 
 *
 * @author Anil K. Vijendran
 * @author Harish Prabandham
 * @author Marc A. Saegesser
 */
public class JspServlet extends HttpServlet {
    Log loghelper = Log.getLog("JASPER_LOG", "JspServlet");
    /**
     * Adds reference counting to the JSP implementation servlet.  This
     * is required to handle the case where a JSP implementation servlet
     * is executing requests on several threads when a new implementation
     * arrives (the JSP source was updated).  We need to wait until all
     * the requests complete before calling the implementation servlet's
     * destroy() method.
     */
    class JspCountedServlet extends HttpServlet
    {
        private Servlet servlet = null;
        private int threadCount = 0;
        private boolean destroyed = false;
        public JspCountedServlet(Servlet servlet)
        {
            this.servlet = servlet;
        }
        public void init(ServletConfig config) throws ServletException, JasperException
        {
            try{
                servlet.init(config);
            }catch(NullPointerException e){
                throw new JasperException(e);
            }
        }
        public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException, JasperException
        {
            try{
                incrementCount();
                if(servlet instanceof SingleThreadModel){
                    synchronized(servlet){
                        servlet.service(req, res);
                    }
                } else {
                    servlet.service(req, res);
                }
            }catch(NullPointerException e){
                throw new JasperException(e);
            }finally{
                decrementCount();
            }
        }
        /*
         * Flags this servlet for destrction once all active requests have completed.
         * After calling this method it is invalid to call service().
         */
        public void destroy()
        {
            destroyed = true;
            if(getCount() == 0)
                doDestroy();
        }
        private void doDestroy()
        {
            try{
                servlet.destroy();
                servlet = null;
            }catch(NullPointerException e){
            }
        }
        private synchronized void incrementCount()
        {
            threadCount++;
        }
        private synchronized void decrementCount()
        {
            if(threadCount <= 0){
                Constants.message("jsp.error.badcount", Log.ERROR);
                return;
            }
            --threadCount;
            if(threadCount == 0 && destroyed)
                doDestroy();
        }
        private synchronized int getCount()
        {
            return threadCount;
        }
    }
    class JspServletWrapper {
        JspCountedServlet theServlet;
	String jspUri;
	boolean isErrorPage;
	Class servletClass;
	
	JspServletWrapper(String jspUri, boolean isErrorPage) {
	    this.jspUri = jspUri;
	    this.isErrorPage = isErrorPage;
	    this.theServlet = null;
	}
	
        public synchronized void instantiateServlet(Class servletClass) throws JasperException, ServletException
        {
            try {
                this.servletClass = servletClass;
                // If we're replacing an existing JSP Implementation class, then
                // schedule it for destruction
                if(theServlet != null)
                    theServlet.destroy();
                // Create an instance of the JSP implementation class
                Servlet servlet = (Servlet) servletClass.newInstance();
                // Set the class loader
                if(servlet instanceof HttpJspBase) {
                    ((HttpJspBase)servlet).setClassLoader(JspServlet.this.parentClassLoader);
                }
                // Wrap this servlet in a counted servlet
                theServlet = new JspCountedServlet(servlet);
                // Call the JSP Implementation servlet's init() method.  This
                // will cause the page's jspInit() method to be invoked if one exists.
                theServlet.init(JspServlet.this.config);
            } catch(Exception ex) {
                throw new JasperException(ex);
            }
        }
        public synchronized Servlet getServlet()
        {
            return theServlet;
        }
        public synchronized boolean isInstantiated()
        {
            return theServlet != null;
        }
	private void loadIfNecessary(HttpServletRequest req, HttpServletResponse res) 
            throws JasperException, ServletException, FileNotFoundException 
        {
            // First try context attribute; if that fails then use the 
            // classpath init parameter. 
            // Should I try to concatenate them if both are non-null?
            String cp = (String) context.getAttribute(Constants.SERVLET_CLASSPATH);
            String accordingto;
            if (cp == null || cp.equals("")) {
                accordingto = "according to the init parameter";
                cp = options.getClassPath();
            } else 
                accordingto = "according to the Servlet Engine";
            
            Constants.message("jsp.message.cp_is", 
                              new Object[] { 
                                  accordingto,
                                  cp == null ? "" : cp
                              }, 
                              Log.INFORMATION);
            loadJSP(jspUri, cp, isErrorPage, req, res);
	}
	
	public void service(HttpServletRequest request, 
			    HttpServletResponse response,
			    boolean precompile)
	    throws ServletException, IOException, FileNotFoundException 
	{
            Servlet servlet = null;
            try {
                loadIfNecessary(request, response);
                servlet = getServlet();
		// If a page is to only to be precompiled return.
		if (precompile)
		    return;
		if (servlet instanceof SingleThreadModel) {
		    // sync on the wrapper so that the freshness
		    // of the page is determined right before servicing
		    synchronized (this) {
			servlet.service(request, response);
		    }
		} else {
		    servlet.service(request, response);
		}
            } catch (FileNotFoundException ex) {
		try {
                    if (insecure_TMI) {
                        response.sendError(HttpServletResponse.SC_NOT_FOUND, 
                                           Constants.getString
                                           ("jsp.error.file.not.found.TMI", 
                                            new Object[] {
                                                ex.getMessage()
                                            }));
                    } else {
                        response.sendError(HttpServletResponse.SC_NOT_FOUND, 
                                           Constants.getString
                                           ("jsp.error.file.not.found", 
                                            new Object[] {
                                                // Too Much Information -- ex.getMessage()
                                            }));
                    }
		} catch (IllegalStateException ise) {
                    // logs are presumed to be secure, thus the TMI info can be logged
		    Constants.jasperLog.log(Constants.getString
					    ("jsp.error.file.not.found.TMI",
					     new Object[] {
						 ex.getMessage()
					     }), ex,
					    Log.ERROR);
		    // rethrow FileNotFoundException so someone higher up can handle
                    if (insecure_TMI)
                        throw ex;
                    else
			throw new FileNotFoundException(Constants.getString
                                           ("jsp.error.file.not.found", 
                                            new Object[] {
                                                // Too Much Information -- ex.getMessage()
                                            }));
		}
                return;
            }
	}
        public void destroy()
        {
            if(theServlet != null)
                theServlet.destroy();
        }
    }
	
	
    protected ServletContext context = null;
    protected Hashtable jsps = new Hashtable();
    //    protected Hashtable loadedJSPs = new Hashtable();
    protected ServletConfig config;
    protected JasperLoader loader;
    protected Options options;
    protected ClassLoader parentClassLoader;
    protected ServletEngine engine;
    protected String serverInfo;
    
    /** Set to true to provide Too Much Information on errors */
    private final boolean insecure_TMI = false;
    static boolean firstTime = true;
    static boolean jdk12=false;
    static {
	try {
	    Class.forName( "java.security.PrivilegedAction" );
	    jdk12=true;
	} catch(Throwable ex ) {
	}
    }
    public void init(ServletConfig config)
	throws ServletException
    {
	super.init(config);
	this.config = config;
	this.context = config.getServletContext();
        this.serverInfo = context.getServerInfo();
        
	options = new EmbededServletOptions(config, context);
	parentClassLoader = (ClassLoader) context.getAttribute(Constants.SERVLET_CLASS_LOADER);
	if (parentClassLoader == null)
	    parentClassLoader = this.getClass().getClassLoader();
            
	// getClass().getClassLoader() returns null in JDK 1.1.6/1.1.8
	if (parentClassLoader != null) {
            Constants.message("jsp.message.parent_class_loader_is", 
                              new Object[] {
                                  parentClassLoader.toString()
                              }, Log.DEBUG);
            }
	else {
            Constants.message("jsp.message.parent_class_loader_is", 
                              new Object[] {
                                  "
 | 
| ... this post is sponsored by my books ... | |
         
           #1 New Release!  | 
      
         
           FP Best Seller  | 
  
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse 
URI on this website is
paid back to open source projects.