Java tutorial
// ======================================================================== // $Id: ServletHolder.java,v 1.53 2005/11/03 08:52:48 gregwilkins Exp $ // Copyright 199-2004 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // 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 net.lightbody.bmp.proxy.jetty.jetty.servlet; import net.lightbody.bmp.proxy.jetty.http.HttpRequest; import net.lightbody.bmp.proxy.jetty.http.UserRealm; import net.lightbody.bmp.proxy.jetty.log.LogFactory; import org.apache.commons.logging.Log; import javax.servlet.*; import java.io.IOException; import java.security.Principal; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Stack; /* --------------------------------------------------------------------- */ /** Servlet Instance and Context Holder. * Holds the name, params and some state of a javax.servlet.Servlet * instance. It implements the ServletConfig interface. * This class will organise the loading of the servlet when needed or * requested. * * @version $Id: ServletHolder.java,v 1.53 2005/11/03 08:52:48 gregwilkins Exp $ * @author Greg Wilkins */ public class ServletHolder extends Holder implements Comparable { private static Log log = LogFactory.getLog(ServletHolder.class); /* ---------------------------------------------------------------- */ private int _initOrder; private boolean _initOnStartup = false; private Map _roleMap; private String _forcedPath; private String _runAs; private UserRealm _realm; private transient Stack _servlets; private transient Servlet _servlet; private transient Config _config; private transient long _unavailable; private transient UnavailableException _unavailableEx; /* ---------------------------------------------------------------- */ /** Constructor for Serialization. */ public ServletHolder() { } /* ---------------------------------------------------------------- */ /** Constructor. * @param handler The ServletHandler instance for this servlet. * @param name The name of the servlet. * @param className The class name of the servlet. */ public ServletHolder(ServletHandler handler, String name, String className) { super(handler, (name == null) ? className : name, className); } /* ---------------------------------------------------------------- */ /** Constructor. * @param handler The ServletHandler instance for this servlet. * @param name The name of the servlet. * @param className The class name of the servlet. * @param forcedPath If non null, the request attribute * javax.servlet.include.servlet_path will be set to this path before * service is called. */ public ServletHolder(ServletHandler handler, String name, String className, String forcedPath) { this(handler, (name == null) ? className : name, className); _forcedPath = forcedPath; } /* ------------------------------------------------------------ */ public int getInitOrder() { return _initOrder; } /* ------------------------------------------------------------ */ /** Set the initialize order. * Holders with order<0, are initialized on use. Those with * order>=0 are initialized in increasing order when the handler * is started. */ public void setInitOrder(int order) { _initOnStartup = true; _initOrder = order; } /* ------------------------------------------------------------ */ /** Comparitor by init order. */ public int compareTo(Object o) { if (o instanceof ServletHolder) { ServletHolder sh = (ServletHolder) o; if (sh == this) return 0; if (sh._initOrder < _initOrder) return 1; if (sh._initOrder > _initOrder) return -1; int c = _className.compareTo(sh._className); if (c == 0) c = _name.compareTo(sh._name); if (c == 0) c = this.hashCode() > o.hashCode() ? 1 : -1; return c; } return 1; } /* ------------------------------------------------------------ */ public boolean equals(Object o) { return compareTo(o) == 0; } /* ------------------------------------------------------------ */ public int hashCode() { return _name.hashCode(); } /* ---------------------------------------------------------------- */ public ServletContext getServletContext() { return ((ServletHandler) _httpHandler).getServletContext(); } /* ------------------------------------------------------------ */ /** Link a user role. * Translate the role name used by a servlet, to the link name * used by the container. * @param name The role name as used by the servlet * @param link The role name as used by the container. */ public synchronized void setUserRoleLink(String name, String link) { if (_roleMap == null) _roleMap = new HashMap(); _roleMap.put(name, link); } /* ------------------------------------------------------------ */ /** get a user role link. * @param name The name of the role * @return The name as translated by the link. If no link exists, * the name is returned. */ public String getUserRoleLink(String name) { if (_roleMap == null) return name; String link = (String) _roleMap.get(name); return (link == null) ? name : link; } /* ------------------------------------------------------------ */ /** * @param role Role name that is added to UserPrincipal when this servlet * is called. */ public void setRunAs(String role) { _runAs = role; } /* ------------------------------------------------------------ */ public String getRunAs() { return _runAs; } /* ------------------------------------------------------------ */ public void start() throws Exception { _unavailable = 0; super.start(); if (!javax.servlet.Servlet.class.isAssignableFrom(_class)) { Exception ex = new IllegalStateException("Servlet " + _class + " is not a javax.servlet.Servlet"); super.stop(); throw ex; } _config = new Config(); if (_runAs != null) _realm = _httpHandler.getHttpContext().getRealm(); if (javax.servlet.SingleThreadModel.class.isAssignableFrom(_class)) _servlets = new Stack(); if (_initOnStartup) { _servlet = (Servlet) newInstance(); try { initServlet(_servlet, _config); } catch (Throwable e) { _servlet = null; _config = null; if (e instanceof Exception) throw (Exception) e; else if (e instanceof Error) throw (Error) e; else throw new ServletException(e); } } } /* ------------------------------------------------------------ */ public void stop() { Principal user = null; try { // Handle run as if (_runAs != null && _realm != null) user = _realm.pushRole(null, _runAs); if (_servlet != null) _servlet.destroy(); _servlet = null; while (_servlets != null && _servlets.size() > 0) { Servlet s = (Servlet) _servlets.pop(); s.destroy(); } _config = null; } finally { super.stop(); // pop run-as role if (_runAs != null && _realm != null && user != null) _realm.popRole(user); } } /* ------------------------------------------------------------ */ /** Get the servlet. * @return The servlet */ public synchronized Servlet getServlet() throws ServletException { // Handle previous unavailability if (_unavailable != 0) { if (_unavailable < 0 || _unavailable > 0 && System.currentTimeMillis() < _unavailable) throw _unavailableEx; _unavailable = 0; _unavailableEx = null; } try { if (_servlets != null) { Servlet servlet = null; if (_servlets.size() == 0) { servlet = (Servlet) newInstance(); if (_config == null) _config = new Config(); initServlet(servlet, _config); } else servlet = (Servlet) _servlets.pop(); return servlet; } if (_servlet == null) { _servlet = (Servlet) newInstance(); if (_config == null) _config = new Config(); initServlet(_servlet, _config); } return _servlet; } catch (UnavailableException e) { _servlet = null; _config = null; return makeUnavailable(e); } catch (ServletException e) { _servlet = null; _config = null; throw e; } catch (Throwable e) { _servlet = null; _config = null; throw new ServletException("init", e); } } /* ------------------------------------------------------------ */ private Servlet makeUnavailable(UnavailableException e) throws UnavailableException { _unavailableEx = e; _unavailable = -1; if (e.isPermanent()) _unavailable = -1; else { if (_unavailableEx.getUnavailableSeconds() > 0) _unavailable = System.currentTimeMillis() + 1000 * _unavailableEx.getUnavailableSeconds(); else _unavailable = System.currentTimeMillis() + 5000; // TODO configure } throw _unavailableEx; } /* ------------------------------------------------------------ */ private void initServlet(Servlet servlet, ServletConfig config) throws ServletException { Principal user = null; try { // Handle run as if (_runAs != null && _realm != null) user = _realm.pushRole(null, _runAs); servlet.init(config); } finally { // pop run-as role if (_runAs != null && _realm != null && user != null) _realm.popRole(user); } } /* ------------------------------------------------------------ */ /** Service a request with this servlet. */ public void handle(ServletRequest request, ServletResponse response) throws ServletException, UnavailableException, IOException { if (_class == null) throw new UnavailableException("Servlet Not Initialized"); Servlet servlet = (!_initOnStartup || _servlets != null) ? getServlet() : _servlet; if (servlet == null) throw new UnavailableException("Could not instantiate " + _class); // Service the request boolean servlet_error = true; Principal user = null; HttpRequest http_request = null; try { // Handle aliased path if (_forcedPath != null) // TODO complain about poor naming to the Jasper folks request.setAttribute("org.apache.catalina.jsp_file", _forcedPath); // Handle run as if (_runAs != null && _realm != null) { http_request = getHttpContext().getHttpConnection().getRequest(); user = _realm.pushRole(http_request.getUserPrincipal(), _runAs); http_request.setUserPrincipal(user); } servlet.service(request, response); servlet_error = false; } catch (UnavailableException e) { if (_servlets != null && servlet != null) stop(); makeUnavailable(e); } finally { // pop run-as role if (_runAs != null && _realm != null && user != null) { user = _realm.popRole(user); http_request.setUserPrincipal(user); } // Handle error params. if (servlet_error) request.setAttribute("javax.servlet.error.servlet_name", getName()); // Return to singleThreaded pool synchronized (this) { if (_servlets != null && servlet != null) _servlets.push(servlet); } } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ class Config implements ServletConfig { /* -------------------------------------------------------- */ public String getServletName() { return getName(); } /* -------------------------------------------------------- */ public ServletContext getServletContext() { return ((ServletHandler) _httpHandler).getServletContext(); } /* -------------------------------------------------------- */ public String getInitParameter(String param) { return ServletHolder.this.getInitParameter(param); } /* -------------------------------------------------------- */ public Enumeration getInitParameterNames() { return ServletHolder.this.getInitParameterNames(); } } }