You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@locus.apache.org on 2000/07/29 01:59:59 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util Enumerator.java

craigmcc    00/07/28 16:59:59

  Modified:    proposals/catalina/src/share/org/apache/tomcat/session
                        StandardSession.java
  Added:       proposals/catalina/src/share/org/apache/tomcat/util
                        Enumerator.java
  Log:
  Tune the performance of attribute setting and retrieval, using collection
  clases where appropriate.
  
  Introduce a new utility class (Enumerator) that can provide Enumerations
  for Java2 collections classes and their iterators.  This makes it easy to
  bridge back to the servlet APIs that want to return Enumeration.
  
  Revision  Changes    Path
  1.11      +105 -72   jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardSession.java
  
  Index: StandardSession.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardSession.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- StandardSession.java	2000/07/12 04:43:15	1.10
  +++ StandardSession.java	2000/07/28 23:59:57	1.11
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardSession.java,v 1.10 2000/07/12 04:43:15 craigmcc Exp $
  - * $Revision: 1.10 $
  - * $Date: 2000/07/12 04:43:15 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardSession.java,v 1.11 2000/07/28 23:59:57 craigmcc Exp $
  + * $Revision: 1.11 $
  + * $Date: 2000/07/28 23:59:57 $
    *
    * ====================================================================
    *
  @@ -71,9 +71,10 @@
   import java.io.ObjectOutputStream;
   import java.io.Serializable;
   import java.security.Principal;
  +import java.util.ArrayList;
   import java.util.Enumeration;
  -import java.util.Hashtable;
  -import java.util.Vector;
  +import java.util.HashMap;
  +import java.util.Iterator;
   import javax.servlet.ServletException;
   import javax.servlet.http.HttpSession;
   import javax.servlet.http.HttpSessionBindingEvent;
  @@ -81,6 +82,7 @@
   import javax.servlet.http.HttpSessionContext;
   import org.apache.tomcat.Manager;
   import org.apache.tomcat.Session;
  +import org.apache.tomcat.util.Enumerator;
   import org.apache.tomcat.util.StringManager;
   
   
  @@ -102,7 +104,7 @@
    * @author Craig R. McClanahan
    * @author Sean Legassick
    * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
  - * @version $Revision: 1.10 $ $Date: 2000/07/12 04:43:15 $
  + * @version $Revision: 1.11 $ $Date: 2000/07/28 23:59:57 $
    */
   
   final class StandardSession
  @@ -139,7 +141,7 @@
       /**
        * The collection of user data attributes associated with this Session.
        */
  -    private Hashtable attributes = new Hashtable();
  +    private HashMap attributes = new HashMap();
   
   
       /**
  @@ -150,6 +152,14 @@
   
   
       /**
  +     * We are currently processing a session expiration, so bypass
  +     * certain IllegalStateException tests.  NOTE:  This value is not
  +     * included in the serialized version of this object.
  +     */
  +    private transient boolean expiring = false;
  +
  +
  +    /**
        * The session identifier of this Session.
        */
       private String id = null;
  @@ -324,7 +334,7 @@
        */
       public int getMaxInactiveInterval() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.getMaxInactiveInterval.ise"));
   
  @@ -411,26 +421,24 @@
        */
       public void expire() {
   
  +	if (expiring)
  +	    return;		// Already in progress
  +	expiring = true;
  +
   	// Remove this session from our manager's active sessions
   	if ((manager != null) && (manager instanceof ManagerBase))
   	    ((ManagerBase) manager).remove(this);
   
   	// Unbind any objects associated with this session
  -	Vector results = new Vector();
  -	Enumeration attrs = getAttributeNames();
  -	while (attrs.hasMoreElements()) {
  -	    String attr = (String) attrs.nextElement();
  -	    results.addElement(attr);
  -	}
  -	Enumeration names = results.elements();
  -	while (names.hasMoreElements()) {
  -	    String name = (String) names.nextElement();
  -	    removeAttribute(name);
  -	}
  +	String keys[] = keys();
  +	for (int i = 0; i < keys.length; i++)
  +	    removeAttribute(keys[i]);
   
   	// Mark this session as invalid
   	setValid(false);
   
  +	expiring = false;
  +
       }
   
   
  @@ -453,6 +461,7 @@
   	// Reset the instance variables associated with this Session
   	attributes.clear();
   	creationTime = 0L;
  +	expiring = false;
   	id = null;
   	lastAccessedTime = 0L;
   	manager = null;
  @@ -520,7 +529,7 @@
        */
       public long getCreationTime() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.getCreationTime.ise"));
   
  @@ -559,11 +568,13 @@
        */
       public Object getAttribute(String name) {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.getAttribute.ise"));
   
  -	return (attributes.get(name));
  +	synchronized (attributes) {
  +	    return (attributes.get(name));
  +	}
   
       }
   
  @@ -577,11 +588,13 @@
        */
       public Enumeration getAttributeNames() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.getAttributeNames.ise"));
   
  -	return (attributes.keys());
  +	synchronized (attributes) {
  +	    return (new Enumerator(attributes.keySet()));
  +	}
   
       }
   
  @@ -617,20 +630,11 @@
        */
       public String[] getValueNames() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.getValueNames.ise"));
   
  -	Vector results = new Vector();
  -	Enumeration attrs = getAttributeNames();
  -	while (attrs.hasMoreElements()) {
  -	    String attr = (String) attrs.nextElement();
  -	    results.addElement(attr);
  -	}
  -	String names[] = new String[results.size()];
  -	for (int i = 0; i < names.length; i++)
  -	    names[i] = (String) results.elementAt(i);
  -	return (names);
  +	return (keys());
   
       }
   
  @@ -643,7 +647,7 @@
        */
       public void invalidate() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.invalidate.ise"));
   
  @@ -665,7 +669,7 @@
        */
       public boolean isNew() {
   
  -	if (!isValid())
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.isNew.ise"));
   
  @@ -715,20 +719,25 @@
        */
       public void removeAttribute(String name) {
   
  -	if (!isValid())
  +	// Validate our current state
  +	if (!expiring && !isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.removeAttribute.ise"));
   
  +	// Remove this attribute from our collection
  +	Object object = null;
   	synchronized (attributes) {
  -	    Object object = attributes.get(name);
  +	    object = attributes.get(name);
   	    if (object == null)
   		return;
   	    attributes.remove(name);
  -	    if (object instanceof HttpSessionBindingListener)
  -		((HttpSessionBindingListener) object).valueUnbound
  -		    (new HttpSessionBindingEvent((HttpSession) this, name));
   	}
   
  +	// Call the valueUnbound() method if necessary
  +	if (object instanceof HttpSessionBindingListener)
  +	    ((HttpSessionBindingListener) object).valueUnbound
  +		(new HttpSessionBindingEvent((HttpSession) this, name));
  +
       }
   
   
  @@ -775,20 +784,23 @@
        */
       public void setAttribute(String name, Object value) {
   
  -	if (!isValid())
  +	// Validate our current state
  +	if (!isValid)
   	    throw new IllegalStateException
   		(sm.getString("standardSession.setAttribute.ise"));
  -
   	if ((manager != null) && manager.getDistributable() &&
   	  !(value instanceof Serializable))
   	    throw new IllegalArgumentException
   		(sm.getString("standardSession.setAttribute.iae"));
   
  +	// Call the valueBound() method if necessary
  +	if (value instanceof HttpSessionBindingListener)
  +	    ((HttpSessionBindingListener) value).valueBound
  +		(new HttpSessionBindingEvent((HttpSession) this, name));
  +
  +	// Replace or add this attribute
   	synchronized (attributes) {
   	    removeAttribute(name);
  -	    if (value instanceof HttpSessionBindingListener)
  -		((HttpSessionBindingListener) value).valueBound
  -		    (new HttpSessionBindingEvent((HttpSession) this, name));
   	    attributes.put(name, value);
   	}
   
  @@ -825,14 +837,14 @@
   
   	// Deserialize the attribute count and attribute values
   	if (attributes == null)
  -	    attributes = new Hashtable();
  +	    attributes = new HashMap();
   	int n = ((Integer) stream.readObject()).intValue();
   	for (int i = 0; i < n; i++) {
   	    String name = (String) stream.readObject();
   	    Object value = (Object) stream.readObject();
   	    if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
   		continue;
  -	    attributes.put(name, value);
  +	    attributes.put(name, value);	// No multithread access
   	}
   
       }
  @@ -869,38 +881,44 @@
   	stream.writeObject(new Long(thisAccessedTime));
   
   	// Accumulate the names of serializable and non-serializable attributes
  -	Vector results = new Vector();
  -	Vector unbinds = new Vector();
  -	Enumeration attrs = getAttributeNames();
  -	while (attrs.hasMoreElements()) {
  -	    String attr = (String) attrs.nextElement();
  -	    Object value = attributes.get(attr);
  -	    if (value instanceof Serializable)
  -		results.addElement(attr);
  -	    else
  -		unbinds.addElement(attr);
  +	String keys[] = keys();
  +	ArrayList saveNames = new ArrayList();
  +	ArrayList saveValues = new ArrayList();
  +	ArrayList unbinds = new ArrayList();
  +	for (int i = 0; i < keys.length; i++) {
  +	    Object value = null;
  +	    synchronized (attributes) {
  +		value = attributes.get(keys[i]);
  +	    }
  +	    if (value == null)
  +		continue;
  +	    else if (value instanceof Serializable) {
  +		saveNames.add(keys[i]);
  +		saveValues.add(value);
  +	    } else
  +		unbinds.add(keys[i]);
   	}
   
   	// Serialize the attribute count and the Serializable attributes
  -	stream.writeObject(new Integer(results.size()));
  -	Enumeration names = results.elements();
  -	while (names.hasMoreElements()) {
  -	    String name = (String) names.nextElement();
  -	    stream.writeObject(name);
  +	int n = saveNames.size();
  +	stream.writeObject(new Integer(n));
  +	for (int i = 0; i < n; i++) {
  +	    stream.writeObject((String) saveNames.get(i));
   	    try {
  -		stream.writeObject(attributes.get(name));
  +		stream.writeObject(saveValues.get(i));
   	    } catch (NotSerializableException e) {
   		log(sm.getString("standardSession.notSerializable",
  -				 name, id));
  +				 saveNames.get(i), id));
   		stream.writeObject(NOT_SERIALIZED);
  -		unbinds.addElement(name);
  +		unbinds.add(saveNames.get(i));
   	    }
   	}
   
   	// Unbind the non-Serializable attributes
  -	names = unbinds.elements();
  -	while (names.hasMoreElements())
  -	    removeAttribute((String) names.nextElement());
  +	Iterator names = unbinds.iterator();
  +	while (names.hasNext()) {
  +	    removeAttribute((String) names.next());
  +	}
   
       }
   
  @@ -909,6 +927,21 @@
   
   
       /**
  +     * Return the names of all currently defined session attributes
  +     * as an array of Strings.  If there are no defined attributes, a
  +     * zero-length array is returned.
  +     */
  +    private String[] keys() {
  +
  +	String results[] = new String[0];
  +	synchronized (attributes) {
  +	    return ((String[]) attributes.keySet().toArray(results));
  +	}
  +
  +    }
  +
  +
  +    /**
        * Log a message on the Logger associated with our Manager (if any).
        *
        * @param message Message to be logged
  @@ -962,7 +995,7 @@
   final class StandardSessionContext implements HttpSessionContext {
   
   
  -    private Vector dummy = new Vector();
  +    private HashMap dummy = new HashMap();
   
       /**
        * Return the session identifiers of all sessions defined
  @@ -974,7 +1007,7 @@
        */
       public Enumeration getIds() {
   
  -	return (dummy.elements());
  +	return (new Enumerator(dummy));
   
       }
   
  
  
  
  1.1                  jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/Enumerator.java
  
  Index: Enumerator.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/util/Enumerator.java,v 1.1 2000/07/28 23:59:59 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/07/28 23:59:59 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.tomcat.util;
  
  
  import java.util.Collection;
  import java.util.Enumeration;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.NoSuchElementException;
  
  
  /**
   * Adapter class that wraps an <code>Enumeration</code> around a Java2
   * collection classes object <code>Iterator</code> so that existing APIs
   * returning Enumerations can easily run on top of the new collections.
   * Constructors are provided to easliy create such wrappers.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/07/28 23:59:59 $
   */
  
  public final class Enumerator implements Enumeration {
  
  
      // ----------------------------------------------------------- Constructors
  
  
      /**
       * Return an Enumeration over the values of the specified Collection.
       *
       * @param collection Collection whose values should be enumerated
       */
      public Enumerator(Collection collection) {
  
  	this(collection.iterator());
  
      }
  
  
      /**
       * Return an Enumeration over the values returned by the
       * specified Iterator.
       *
       * @param iterator Iterator to be wrapped
       */
      public Enumerator(Iterator iterator) {
  
  	super();
  	this.iterator = iterator;
  
      }
  
  
      /**
       * Return an Enumeration over the values of the specified Map.
       *
       * @param map Map whose values should be enumerated
       */
      public Enumerator(Map map) {
  
  	this(map.values().iterator());
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  
  
      /**
       * The <code>Iterator</code> over which the <code>Enumeration</code>
       * represented by this class actually operates.
       */
      private Iterator iterator = null;
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Tests if this enumeration contains more elements.
       *
       * @return <code>true</code> if and only if this enumeration object
       *  contains at least one more element to provide, <code>false</code>
       *  otherwise
       */
      public boolean hasMoreElements() {
  
  	return (iterator.hasNext());
  
      }
  
  
      /**
       * Returns the next element of this enumeration if this enumeration
       * has at least one more element to provide.
       *
       * @return the next element of this enumeration
       *
       * @exception NoSuchElementException if no more elements exist
       */
      public Object nextElement() throws NoSuchElementException {
  
  	return (iterator.next());
  
      }
  
  
  }