tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From craig...@locus.apache.org
Subject cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session StandardManager.java
Date Fri, 12 May 2000 21:59:35 GMT
craigmcc    00/05/12 14:59:34

  Modified:    proposals/catalina/src/conf server.xml
               proposals/catalina/src/share/org/apache/tomcat Context.java
                        Loader.java
               proposals/catalina/src/share/org/apache/tomcat/core
                        LocalStrings.properties StandardContext.java
               proposals/catalina/src/share/org/apache/tomcat/loader
                        FileClassLoader.java LocalStrings.properties
                        StandardLoader.java
               proposals/catalina/src/share/org/apache/tomcat/session
                        StandardManager.java
  Log:
  Initial implementation of automatic reloading for Catalina.  Compared to
  Tomcat 3.x, the following differences will be observed:
  
  - Checking for modified classes (to trigger an automatic reload) is done
    by a background thread at a user-specified interval (default is 15
    seconds), rather than on the request processing path.
  
  - All servlets, and subordinate classes referenced by those servlets,
    are loaded by a single class loader.  (Classes that are initially
    referenced from a JSP page appear to be loaded by a different class
    loader -- more research is necessary in this area).
  
  - When the need for reloading is detected, the entire web application
    is shut down and restarted (including serialization of session data
    if your session manager is configured to do so).  This is important
    to avoid potential class cast problems (class a.b.c.Foo loaded by
    one class loader is *not* the same as class a.b.c.Foo loaded by a
    different class loader, even if they both came from the same class
    file on disk).
  
  - During a reload, request processing for this application is gracefully
    paused, so there should be no race conditions caused by requests being
    executed in the middle of a reload.
  
  - The default class loader follows a different policy than the
    AdaptiveClassLoader/AdaptiveServletLoader set used by Tomcat.  The
    new class loader looks *first* in the WEB-INF/classes and
    WEB-INF/lib/*.jar repositories, and *second* to the system class path,
    while the current Tomcat code does the opposite.  IMHO the new approach
    is better because it allows webapps to override JAR files etc. that are
    listed on the system classpath with different versions specific to
    that application.
  
  - The Context interface exposes a "reload()" method that can be used
    by an administrative application to reload the app unconditionally.
  
  The following similarities to the current Tomcat implementation exist:
  
  - Automatic reloading is configured on a per-context basis with an
    attribute in the "conf/server.xml" file (in the case of Catalina,
    it is just "reloadable" instead of "isReloadable").
  
  - Automatic reloading only checks for updated classes that came from
    WEB-INF/classes or WEB-INF/lib/*.jar -- updates to classes loaded
    from the system class path are not checked.
  
  - Automatic reloading is very useful during development, but is not
    recommended for production applications.  Therefore, reloading is
    *not* enabled by default.
  
  At present, at least the following issues exist:
  
  - Java classes (such as beans) that are initially loaded from a JSP page
    do not trigger reloading.  Apparently, the JSP servlet uses its own
    class loader for the pages.  Further investigation is needed here.
  
  - Although servlets and sessions are unloaded and reloaded when a
    reload occurs, servlet context attributes are not.  Class cast problems
    can still exist if these objects were created by a servlet (which is
    quite typical) using classes loaded from WEB-INF/classes or
    WEB-INF/lib/*.jar.
  
  Revision  Changes    Path
  1.23      +2 -1      jakarta-tomcat/proposals/catalina/src/conf/server.xml
  
  Index: server.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/conf/server.xml,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- server.xml	2000/05/12 00:47:23	1.22
  +++ server.xml	2000/05/12 21:59:31	1.23
  @@ -69,7 +69,8 @@
         </Context>
   
         <!-- Tomcat Examples Context -->
  -      <Context path="/examples" docBase="webapps/examples" debug="0">
  +      <Context path="/examples" docBase="webapps/examples" debug="0"
  +               reloadable="true">
           <Listener className="org.apache.tomcat.startup.ContextConfig"
   	          debug="0"/>
           <Manager className="org.apache.tomcat.session.StandardManager"
  
  
  
  1.10      +27 -4     jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Context.java
  
  Index: Context.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Context.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Context.java	2000/05/03 22:58:22	1.9
  +++ Context.java	2000/05/12 21:59:32	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Context.java,v
1.9 2000/05/03 22:58:22 craigmcc Exp $
  - * $Revision: 1.9 $
  - * $Date: 2000/05/03 22:58:22 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Context.java,v
1.10 2000/05/12 21:59:32 craigmcc Exp $
  + * $Revision: 1.10 $
  + * $Date: 2000/05/12 21:59:32 $
    *
    * ====================================================================
    *
  @@ -90,7 +90,7 @@
    * <p>
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.9 $ $Date: 2000/05/03 22:58:22 $
  + * @version $Revision: 1.10 $ $Date: 2000/05/12 21:59:32 $
    */
   
   public interface Context extends Container {
  @@ -158,6 +158,20 @@
   
   
       /**
  +     * Return the reloadable flag for this web application.
  +     */
  +    public boolean getReloadable();
  +
  +
  +    /**
  +     * Set the reloadable flag for this web application.
  +     *
  +     * @param reloadable The new reloadable flag
  +     */
  +    public void setReloadable(boolean reloadable);
  +
  +
  +    /**
        * Return the servlet context for which this Context is a facade.
        */
       public ServletContext getServletContext();
  @@ -527,6 +541,15 @@
        * @param update Update request to reflect this mapping?
        */
       public Wrapper map(Request request, boolean update);
  +
  +
  +    /**
  +     * Reload this web application, if reloading is supported.
  +     *
  +     * @exception IllegalStateException if the <code>reloadable</code>
  +     *  property is set to <code>false</code>.
  +     */
  +    public void reload();
   
   
       /**
  
  
  
  1.4       +20 -13    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Loader.java
  
  Index: Loader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Loader.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Loader.java	2000/05/12 00:47:23	1.3
  +++ Loader.java	2000/05/12 21:59:32	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Loader.java,v
1.3 2000/05/12 00:47:23 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/05/12 00:47:23 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/Loader.java,v
1.4 2000/05/12 21:59:32 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/05/12 21:59:32 $
    *
    * ====================================================================
    *
  @@ -76,7 +76,7 @@
    * repository.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/05/12 00:47:23 $
  + * @version $Revision: 1.4 $ $Date: 2000/05/12 21:59:32 $
    */
   
   public interface Loader {
  @@ -92,13 +92,13 @@
   
   
       /**
  -     * Return the Container with which this Logger has been associated.
  +     * Return the Container with which this Loader has been associated.
        */
       public Container getContainer();
   
   
       /**
  -     * Set the Container with which this Logger has been associated.
  +     * Set the Container with which this Loader has been associated.
        *
        * @param container The associated Container
        */
  @@ -113,6 +113,20 @@
       public String getInfo();
   
   
  +    /**
  +     * Return the reloadable flag for this Loader.
  +     */
  +    public boolean getReloadable();
  +
  +
  +    /**
  +     * Set the reloadable flag for this Loader.
  +     *
  +     * @param reloadable The new reloadable flag
  +     */
  +    public void setReloadable(boolean reloadable);
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -144,13 +158,6 @@
        * such that the loaded classes should be reloaded?
        */
       public boolean modified();
  -
  -
  -    /**
  -     * Cause the underlying class loader (and therefore all of the classes
  -     * loaded by that class loader) to be thrown away, and creates a new one.
  -     */
  -    public void reload();
   
   
       /**
  
  
  
  1.13      +9 -0      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/LocalStrings.properties,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- LocalStrings.properties	2000/05/12 00:47:24	1.12
  +++ LocalStrings.properties	2000/05/12 21:59:32	1.13
  @@ -9,8 +9,17 @@
   interceptorValve.notStarted=InterceptorValve has not yet been started
   standardContext.alreadyStarted=Context has already been started
   standardContext.mappingError=MAPPING configuration error for relative URI {0}
  +standardContext.notReloadable=Reloading is disabled on this Context
   standardContext.notStarted=Context has not yet been started
   standardContext.notWrapper=Child of a Context must be a Wrapper
  +standardContext.reloadingCompleted=Reloading this Context is completed
  +standardContext.reloadingStarted=Reloading this Context has started
  +standardContext.startingLoader=Exception starting Loader
  +standardContext.startingManager=Exception starting Manager
  +standardContext.startingWrapper=Exception starting Wrapper for servlet {0}
  +standardContext.stoppingLoader=Exception stopping Loader
  +standardContext.stoppingManager=Exception stopping Manager
  +standardContext.stoppingWrapper=Exception stopping Wrapper for servlet {0}
   standardEngine.alreadyStarted=Engine has already been started
   standardEngine.mappingError=MAPPING configuration error for server name {0}
   standardEngine.notHost=Child of an Engine must be a Host
  
  
  
  1.19      +191 -4    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java
  
  Index: StandardContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- StandardContext.java	2000/05/12 00:47:24	1.18
  +++ StandardContext.java	2000/05/12 21:59:33	1.19
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java,v
1.18 2000/05/12 00:47:24 craigmcc Exp $
  - * $Revision: 1.18 $
  - * $Date: 2000/05/12 00:47:24 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java,v
1.19 2000/05/12 21:59:33 craigmcc Exp $
  + * $Revision: 1.19 $
  + * $Date: 2000/05/12 21:59:33 $
    *
    * ====================================================================
    *
  @@ -77,6 +77,7 @@
   import org.apache.tomcat.Container;
   import org.apache.tomcat.Context;
   import org.apache.tomcat.HttpRequest;
  +import org.apache.tomcat.Lifecycle;
   import org.apache.tomcat.LifecycleException;
   import org.apache.tomcat.Loader;
   import org.apache.tomcat.Request;
  @@ -95,7 +96,7 @@
    * requests directed to a particular servlet.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.18 $ $Date: 2000/05/12 00:47:24 $
  + * @version $Revision: 1.19 $ $Date: 2000/05/12 21:59:33 $
    */
   
   public final class StandardContext
  @@ -190,6 +191,18 @@
   
   
       /**
  +     * The request processing pause flag (while reloading occurs)
  +     */
  +    private boolean paused = false;
  +
  +
  +    /**
  +     * The reloadable flag for this web application.
  +     */
  +    private boolean reloadable = false;
  +
  +
  +    /**
        * The resource references for this web application, keyed by name.
        */
       private Hashtable resources = new Hashtable();
  @@ -375,6 +388,32 @@
   
   
       /**
  +     * Return the reloadable flag for this web application.
  +     */
  +    public boolean getReloadable() {
  +
  +	return (this.reloadable);
  +
  +    }
  +
  +
  +    /**
  +     * Set the reloadable flag for this web application.
  +     *
  +     * @param reloadable The new reloadable flag
  +     */
  +    public void setReloadable(boolean reloadable) {
  +
  +	boolean oldReloadable = this.reloadable;
  +	this.reloadable = reloadable;
  +	support.firePropertyChange("reloadable",
  +				   new Boolean(oldReloadable),
  +				   new Boolean(this.reloadable));
  +
  +    }
  +
  +
  +    /**
        * Return the servlet context for which this Context is a facade.
        */
       public synchronized ServletContext getServletContext() {
  @@ -1117,6 +1156,36 @@
   
   
       /**
  +     * Process the specified Request, and generate the corresponding Response,
  +     * according to the design of this particular Container.
  +     *
  +     * @param request Request to be processed
  +     * @param response Response to be produced
  +     *
  +     * @exception IOException if an input/output error occurred while
  +     *  processing
  +     * @exception ServletException if a ServletException was thrown
  +     *  while processing this request
  +     */
  +    public void invoke(Request request, Response response)
  +	throws IOException, ServletException {
  +
  +	// Wait if we are reloading
  +	while (getPaused()) {
  +	    try {
  +		Thread.sleep(1000);
  +	    } catch (InterruptedException e) {
  +		;
  +	    }
  +	}
  +
  +	// Normal request processing
  +	super.invoke(request, response);
  +
  +    }
  +
  +
  +    /**
        * Return the Wrapper associated with the servlet that matches the
        * specified context-relative URI, if any; otherwise return
        * <code>null</code>.
  @@ -1250,6 +1319,102 @@
   
   
       /**
  +     * Reload this web application, if reloading is supported.
  +     * <p>
  +     * <b>IMPLEMENTATION NOTE</b>:  This method is designed to deal with
  +     * reloads required by changes to classes in the underlying repositories
  +     * of our class loader.  It does not handle changes to the web application
  +     * deployment descriptor.  If that has occurred, you should stop this
  +     * Context and create (and start) a new Context instance instead.
  +     * <p>
  +     * <b>FIXME</b>:  What about context attributes that have been created
  +     * by servlets?  ClassCastException?
  +     *
  +     * @exception IllegalStateException if the <code>reloadable</code>
  +     *  property is set to <code>false</code>.
  +     */
  +    public void reload() {
  +
  +	// Make sure reloading is enabled
  +	if (!reloadable)
  +	    throw new IllegalStateException
  +		(sm.getString("standardContext.notReloadable"));
  +	log(sm.getString("standardContext.reloadingStarted"));
  +
  +	// Stop accepting requests temporarily
  +	setPaused(true);
  +
  +	// Shut down the current version of the relevant components
  +	Container children[] = findChildren();
  +
  +	for (int i = 0; i < children.length; i++) {
  +	    Wrapper wrapper = (Wrapper) children[i];
  +	    if (wrapper instanceof Lifecycle) {
  +		try {
  +		    ((Lifecycle) wrapper).stop();
  +		} catch (LifecycleException e) {
  +		    log(sm.getString("standardContext.stoppingWrapper",
  +				     wrapper.getName()),
  +			e);
  +		}
  +	    }
  +	}
  +
  +	if ((manager != null) && (manager instanceof Lifecycle)) {
  +	    try {
  +		((Lifecycle) manager).stop();
  +	    } catch (LifecycleException e) {
  +		log(sm.getString("standardContext.stoppingManager"), e);
  +	    }
  +	}
  +
  +	if ((loader != null) && (loader instanceof Lifecycle)) {
  +	    try {
  +		((Lifecycle) loader).stop();
  +	    } catch (LifecycleException e) {
  +		log(sm.getString("standardContext.stoppingLoader"), e);
  +	    }
  +	}
  +
  +	// Start up the new version of the relevant components
  +	if ((loader != null) && (loader instanceof Lifecycle)) {
  +	    try {
  +		;	// FIXME - check for new WEB-INF/lib/*.jar files?
  +		((Lifecycle) loader).start();
  +	    } catch (LifecycleException e) {
  +		log(sm.getString("standardContext.startingLoader"), e);
  +	    }
  +	}
  +
  +	if ((manager != null) && (manager instanceof Lifecycle)) {
  +	    try {
  +		((Lifecycle) manager).start();
  +	    } catch (LifecycleException e) {
  +		log(sm.getString("standardContext.startingManager"), e);
  +	    }
  +	}
  +
  +	for (int i = 0; i < children.length; i++) {
  +	    Wrapper wrapper = (Wrapper) children[i];
  +	    if (wrapper instanceof Lifecycle) {
  +		try {
  +		    ((Lifecycle) wrapper).start();
  +		} catch (LifecycleException e) {
  +		    log(sm.getString("standardContext.startingWrapper",
  +				     wrapper.getName()),
  +			e);
  +		}
  +	    }
  +	}
  +
  +	// Start accepting requests again
  +	setPaused(false);
  +	log(sm.getString("standardContext.reloadingCompleted"));
  +
  +    }
  +
  +
  +    /**
        * Remove the specified security constraint from this web application.
        *
        * @param constraint Constraint to be removed
  @@ -1478,6 +1643,28 @@
   
   
       // -------------------------------------------------------- Private Methods
  +
  +
  +    /**
  +     * Return the request processing paused flag for this Context.
  +     */
  +    private boolean getPaused() {
  +
  +	return (this.paused);
  +
  +    }
  +
  +
  +    /**
  +     * Set the request processing paused flag for this Context.
  +     *
  +     * @param paused The new request processing paused flag
  +     */
  +    private void setPaused(boolean paused) {
  +
  +	this.paused = paused;
  +
  +    }
   
   
       /**
  
  
  
  1.3       +20 -27    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java
  
  Index: FileClassLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- FileClassLoader.java	2000/05/12 00:47:25	1.2
  +++ FileClassLoader.java	2000/05/12 21:59:33	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java,v
1.2 2000/05/12 00:47:25 craigmcc Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/05/12 00:47:25 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java,v
1.3 2000/05/12 21:59:33 craigmcc Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/05/12 21:59:33 $
    *
    * ====================================================================
    *
  @@ -94,7 +94,7 @@
    * modified at runtime.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.2 $ $Date: 2000/05/12 00:47:25 $
  + * @version $Revision: 1.3 $ $Date: 2000/05/12 21:59:33 $
    */
   
   public final class FileClassLoader
  @@ -318,8 +318,8 @@
        */
       public boolean modified() {
   
  -	if (debug >= 2)
  -	    log("modified()");
  +	//	if (debug >= 2)
  +	//	    log("modified()");
   
   	// Build a list of the classes we currently have cached
   	Vector temp = new Vector();
  @@ -338,36 +338,29 @@
   		continue;
   	    if (entry.origin == null)	// System classes cannot be modified
   		continue;
  +	    /*
  +	    if (debug >= 2)
  +		log("Check classname=" + classname +
  +		    ", entry=" +
  +		    (new java.sql.Timestamp(entry.lastModified)).toString() +
  +		    ", origin=" +
  +		    (new java.sql.Timestamp(entry.origin.lastModified())).toString());
  +	    */
   	    if (entry.lastModified != entry.origin.lastModified()) {
  -		if (debug >= 2)
  -		    log("  Class " + classname + " was modified");
  +		//		if (debug >= 2)
  +		//		    log("  Class " + classname + " was modified");
   		return (true);
   	    }
   	}
   
  -	if (debug >= 2)
  -	    log("  No classes were modified");
  +	//	if (debug >= 2)
  +	//	    log("  No classes were modified");
           return (false);
   
       }
   
   
       /**
  -     * Create a new ClassLoader instance based on our current repositories.
  -     */
  -    public Reloader reload() {
  -
  -	if (debug >= 1)
  -	    log("reload()");
  -
  -	FileClassLoader loader = new FileClassLoader(findRepositories());
  -	loader.setDebug(getDebug());
  -	return (loader);
  -
  -    }
  -
  -
  -    /**
        * Remove the specified repository from the set of places this ClassLoader
        * can look for classes to be loaded.  Any classes already loaded from this
        * repository will remain, but no future loads from here will take place.
  @@ -474,8 +467,8 @@
   	    if (directory != null) {
   	        InputStream theStream =
   		  loadStreamFromDirectory(directory, name);
  -		if ((theStream != null) && (debug >= 2))
  -		    log("  Returning directory resource stream");
  +		//		if ((theStream != null) && (debug >= 2))
  +		//		    log("  Returning directory resource stream");
   		if (theStream != null)
   		    return (theStream);
   	    }
  
  
  
  1.4       +7 -4      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/LocalStrings.properties,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LocalStrings.properties	2000/05/12 00:47:25	1.3
  +++ LocalStrings.properties	2000/05/12 21:59:34	1.4
  @@ -1,11 +1,14 @@
   fileClassLoader.canRead=Repository {0} cannot be read
   fileClassLoader.exists=Repository {0} does not exist
   fileClassLoader.jarFile=Cannot read JAR file {0}
  -standardLoader.alreadyStarted=Loader has already been started
   standardLoader.addRepository=Adding repository {0}
  -standardLoader.reload=Reloading this Loader
  -standardLoader.reloadError=Error reloading this loader
  +standardLoader.alreadyStarted=Loader has already been started
  +standardLoader.checkInterval=Cannot set reload check interval to {0} seconds
  +standardLoader.notContext=Cannot auto-reload unless our Container is a Context
  +standardLoader.notReloadabe=Reloadable property is set to false
  +standardLoader.notStarted=Loader has not yet been started
  +standardLoader.reloadable=Cannot set reloadable property to {0}
  +standardLoader.reloading=Reloading checks are enabled for this Context
   standardLoader.removeRepository=Removing repository {0}
   standardLoader.starting=Starting this Loader
  -standardLoader.notStarted=Loader has not yet been started
   standardLoader.stopping=Stopping this Loader
  
  
  
  1.5       +315 -30   jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java
  
  Index: StandardLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- StandardLoader.java	2000/05/12 00:47:25	1.4
  +++ StandardLoader.java	2000/05/12 21:59:34	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v
1.4 2000/05/12 00:47:25 craigmcc Exp $
  - * $Revision: 1.4 $
  - * $Date: 2000/05/12 00:47:25 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v
1.5 2000/05/12 21:59:34 craigmcc Exp $
  + * $Revision: 1.5 $
  + * $Date: 2000/05/12 21:59:34 $
    *
    * ====================================================================
    *
  @@ -65,6 +65,7 @@
   package org.apache.tomcat.loader;
   
   
  +import java.beans.PropertyChangeEvent;
   import java.beans.PropertyChangeListener;
   import java.beans.PropertyChangeSupport;
   import java.io.File;
  @@ -72,6 +73,7 @@
   import java.util.Enumeration;
   import java.util.Vector;
   import org.apache.tomcat.Container;
  +import org.apache.tomcat.Context;
   import org.apache.tomcat.Lifecycle;
   import org.apache.tomcat.LifecycleEvent;
   import org.apache.tomcat.LifecycleException;
  @@ -95,17 +97,24 @@
    * is not present, the system class loader will be used instead.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.4 $ $Date: 2000/05/12 00:47:25 $
  + * @version $Revision: 1.5 $ $Date: 2000/05/12 21:59:34 $
    */
   
   public final class StandardLoader
  -    implements Lifecycle, Loader {
  +    implements Lifecycle, Loader, PropertyChangeListener, Runnable {
   
   
       // ----------------------------------------------------- Instance Variables
   
   
       /**
  +     * The number of seconds between checks for modified classes, if
  +     * automatic reloading is enabled.
  +     */
  +    private int checkInterval = 15;
  +
  +
  +    /**
        * The class loader being managed by this Loader component.
        */
       private Reloader classLoader = null;
  @@ -146,6 +155,12 @@
   
   
       /**
  +     * The reloadable flag for this Loader.
  +     */
  +    private boolean reloadable = false;
  +
  +
  +    /**
        * The set of repositories associated with this class loader.
        */
       private Vector repositories = new Vector();
  @@ -170,10 +185,54 @@
       protected PropertyChangeSupport support = new PropertyChangeSupport(this);
   
   
  +    /**
  +     * The background thread.
  +     */
  +    private Thread thread = null;
  +
  +
  +    /**
  +     * The background thread completion semaphore.
  +     */
  +    private boolean threadDone = false;
  +
  +
  +    /**
  +     * Name to register for the background thread.
  +     */
  +    private String threadName = "StandardLoader";
  +
  +
       // ------------------------------------------------------------- Properties
   
   
       /**
  +     * Return the check interval for this Loader.
  +     */
  +    public int getCheckInterval() {
  +
  +	return (this.checkInterval);
  +
  +    }
  +
  +
  +    /**
  +     * Set the check interval for this Loader.
  +     *
  +     * @param checkInterval The new check interval
  +     */
  +    public void setCheckInterval(int checkInterval) {
  +
  +        int oldCheckInterval = this.checkInterval;
  +	this.checkInterval = checkInterval;
  +	support.firePropertyChange("checkInterval",
  +				   new Integer(oldCheckInterval),
  +				   new Integer(this.checkInterval));
  +
  +    }
  +
  +
  +    /**
        * Return the Java class loader to be used by this Container.
        */
       public ClassLoader getClassLoader() {
  @@ -200,10 +259,21 @@
        */
       public void setContainer(Container container) {
   
  +	// Deregister from the old Container (if any)
  +	if ((this.container != null) && (this.container instanceof Context))
  +	    ((Context) this.container).removePropertyChangeListener(this);
  +
  +	// Process this property change
   	Container oldContainer = this.container;
   	this.container = container;
   	support.firePropertyChange("container", oldContainer, this.container);
   
  +	// Register with the new Container (if any)
  +	if ((this.container != null) && (this.container instanceof Context)) {
  +	    setReloadable( ((Context) this.container).getReloadable() );
  +	    ((Context) this.container).addPropertyChangeListener(this);
  +	}
  +
       }
   
   
  @@ -266,6 +336,41 @@
       }
   
   
  +    /**
  +     * Return the reloadable flag for this Loader.
  +     */
  +    public boolean getReloadable() {
  +
  +	return (this.reloadable);
  +
  +    }
  +
  +
  +    /**
  +     * Set the reloadable flag for this Loader.
  +     *
  +     * @param reloadable The new reloadable flag
  +     */
  +    public void setReloadable(boolean reloadable) {
  +
  +	// Process this property change
  +	boolean oldReloadable = this.reloadable;
  +	this.reloadable = reloadable;
  +	support.firePropertyChange("reloadable",
  +				   new Boolean(oldReloadable),
  +				   new Boolean(this.reloadable));
  +
  +	// Start or stop our background thread if required
  +	if (!started)
  +	    return;
  +	if (!oldReloadable && this.reloadable)
  +	    ;	// FIXME - threadStart()
  +	else if (oldReloadable && !this.reloadable)
  +	    ;	// FIXME - threadStop()
  +
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -325,29 +430,6 @@
   
   
       /**
  -     * Cause the underlying class loader (and therefore all of the classes
  -     * loaded by that class loader) to be thrown away, and creates a new one.
  -     *
  -     * @exception IllegalStateException if a change to the repositories for
  -     *  this class loader has rendered restart impossible
  -     */
  -    public void reload() {
  -
  -        if (debug >= 1)
  -	    log(sm.getString("standardLoader.reload"));
  -
  -	try {
  -	    stop();
  -	    start();
  -	} catch (Throwable t) {
  -	    log(sm.getString("standardLoader.reloadError"), t);
  -	    throw new IllegalStateException("reload: " + t);
  -	}
  -
  -    }
  -
  -
  -    /**
        * Remove a property change listener from this component.
        *
        * @param listener The listener to remove
  @@ -445,6 +527,17 @@
   	    throw new LifecycleException("start: ", t);
   	}
   
  +	// Start our background thread if we are reloadable
  +	if (reloadable) {
  +	    log(sm.getString("standardLoader.reloading"));
  +	    try {
  +		threadStart();
  +	    } catch (IllegalStateException e) {
  +		throw new LifecycleException(e);
  +	    }
  +	}
  +	    
  +
       }
   
   
  @@ -464,6 +557,10 @@
   	lifecycle.fireLifecycleEvent(STOP_EVENT, null);
   	started = false;
   
  +	// Stop our background thread if we are reloadable
  +	if (reloadable)
  +	    threadStop();
  +
   	// Throw away our current class loader
   	if (classLoader instanceof Lifecycle)
   	    ((Lifecycle) classLoader).stop();
  @@ -472,6 +569,35 @@
       }
   
   
  +    // ----------------------------------------- PropertyChangeListener Methods
  +
  +
  +    /**
  +     * Process property change events from our associated Context.
  +     *
  +     * @param event The property change event that has occurred
  +     */
  +    public void propertyChange(PropertyChangeEvent event) {
  +
  +	// Validate the source of this event
  +	if (!(event.getSource() instanceof Context))
  +	    return;
  +	Context context = (Context) event.getSource();
  +
  +	// Process a relevant property change
  +	if (event.getPropertyName().equals("reloadable")) {
  +	    try {
  +		setReloadable
  +		    ( ((Boolean) event.getNewValue()).booleanValue() );
  +	    } catch (NumberFormatException e) {
  +		log(sm.getString("standardLoader.reloadable",
  +				 event.getNewValue().toString()));
  +	    }
  +	}
  +
  +    }
  +
  +
       // ------------------------------------------------------- Private Methods
   
   
  @@ -510,10 +636,10 @@
   	Logger logger = null;
   	if (container != null)
   	    logger = container.getLogger();
  -	if (logger != null)
  +	if (logger != null) {
   	    logger.log("StandardLoader[" + container.getName() + "] "
   		       + message, throwable);
  -	else {
  +	} else {
   	    String containerName = null;
   	    if (container != null)
   		containerName = container.getName();
  @@ -522,6 +648,165 @@
   	    System.out.println("" + throwable);
   	    throwable.printStackTrace(System.out);
   	}
  +
  +    }
  +
  +
  +    /**
  +     * Notify our Context that a reload is appropriate.
  +     */
  +    private void notifyContext() {
  +
  +	ContextNotifier notifier = new ContextNotifier((Context) container);
  +	(new Thread(notifier)).start();
  +
  +    }
  +
  +
  +    /**
  +     * Sleep for the duration specified by the <code>checkInterval</code>
  +     * property.
  +     */
  +    private void threadSleep() {
  +
  +	try {
  +	    Thread.sleep(checkInterval * 1000L);
  +	} catch (InterruptedException e) {
  +	    ;
  +	}
  +
  +    }
  +
  +
  +    /**
  +     * Start the background thread that will periodically check for
  +     * session timeouts.
  +     *
  +     * @exception IllegalStateException if we should not be starting
  +     *  a background thread now
  +     */
  +    private void threadStart() {
  +
  +	// Has the background thread already been started?
  +	if (thread != null)
  +	    return;
  +
  +	// Validate our current state
  +	if (!reloadable)
  +	    throw new IllegalStateException
  +		(sm.getString("standardLoader.notReloadable"));
  +	if (!(container instanceof Context))
  +	    throw new IllegalStateException
  +		(sm.getString("standardLoader.notContext"));
  +
  +	// Start the background thread
  +	if (debug >= 1)
  +	    log(" Starting background thread");
  +	threadDone = false;
  +	threadName = "StandardLoader[" + container.getName() + "]";
  +	thread = new Thread(this, threadName);
  +	thread.setDaemon(true);
  +	thread.start();
  +
  +    }
  +
  +
  +    /**
  +     * Stop the background thread that is periodically checking for
  +     * modified classes.
  +     */
  +    private void threadStop() {
  +
  +	if (thread == null)
  +	    return;
  +
  +	if (debug >= 1)
  +	    log(" Stopping background thread");
  +	threadDone = true;
  +	thread.interrupt();
  +	try {
  +	    thread.join();
  +	} catch (InterruptedException e) {
  +	    ;
  +	}
  +
  +	thread = null;
  +
  +    }
  +
  +
  +    // ------------------------------------------------------ Background Thread
  +
  +
  +    /**
  +     * The background thread that checks for session timeouts and shutdown.
  +     */
  +    public void run() {
  +
  +	if (debug >= 1)
  +	    log("BACKGROUND THREAD Starting");
  +
  +	// Loop until the termination semaphore is set
  +	while (!threadDone) {
  +
  +	    // Wait for our check interval
  +	    threadSleep();
  +
  +	    // Perform our modification check
  +	    if (!classLoader.modified())
  +		continue;
  +
  +	    // Handle a need for reloading
  +	    notifyContext();
  +	    break;
  +
  +	}
  +
  +	if (debug >= 1)
  +	    log("BACKGROUND THREAD Stopping");
  +
  +    }
  +
  +
  +}
  +
  +
  +// ------------------------------------------------------------ Private Classes
  +
  +
  +/**
  + * Private thread class to notify our associated Context that we have
  + * recognized the need for a reload.
  + */
  +
  +final class ContextNotifier implements Runnable {
  +
  +
  +    /**
  +     * The Context we will notify.
  +     */
  +    private Context context = null;
  +
  +
  +    /**
  +     * Construct a new instance of this class.
  +     *
  +     * @param context The Context to be notified
  +     */
  +    public ContextNotifier(Context context) {
  +
  +	super();
  +	this.context = context;
  +
  +    }
  +
  +
  +    /**
  +     * Perform the requested notification.
  +     */
  +    public void run() {
  +
  +	context.reload();
   
       }
   
  
  
  
  1.12      +9 -6      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java
  
  Index: StandardManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- StandardManager.java	2000/05/05 22:45:39	1.11
  +++ StandardManager.java	2000/05/12 21:59:34	1.12
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v
1.11 2000/05/05 22:45:39 craigmcc Exp $
  - * $Revision: 1.11 $
  - * $Date: 2000/05/05 22:45:39 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v
1.12 2000/05/12 21:59:34 craigmcc Exp $
  + * $Revision: 1.12 $
  + * $Date: 2000/05/12 21:59:34 $
    *
    * ====================================================================
    *
  @@ -67,7 +67,6 @@
   import java.beans.PropertyChangeEvent;
   import java.beans.PropertyChangeListener;
   import java.beans.PropertyChangeSupport;
  -import java.beans.PropertyChangeListener;
   import java.io.BufferedInputStream;
   import java.io.BufferedOutputStream;
   import java.io.File;
  @@ -105,7 +104,7 @@
    * <code>stop()</code> methods of this class at the correct times.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.11 $ $Date: 2000/05/05 22:45:39 $
  + * @version $Revision: 1.12 $ $Date: 2000/05/12 21:59:34 $
    */
   
   public final class StandardManager
  @@ -231,8 +230,11 @@
   	super.setContainer(container);
   
   	// Register with the new Container (if any)
  -	if ((this.container != null) && (this.container instanceof Context))
  +	if ((this.container != null) && (this.container instanceof Context)) {
  +	    setMaxInactiveInterval
  +		( ((Context) this.container).getSessionTimeout() );
   	    ((Context) this.container).addPropertyChangeListener(this);
  +	}
   
       }
   
  @@ -741,6 +743,7 @@
   	    return;
   
   	threadDone = false;
  +	threadName = "StandardManager[" + container.getName() + "]";
   	thread = new Thread(this, threadName);
   	thread.setDaemon(true);
   	thread.start();
  
  
  

Mime
View raw message