You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by gd...@apache.org on 2001/10/19 16:58:12 UTC

cvs commit: xml-axis/java/src/org/apache/axis/transport/http AxisHttpSession.java

gdaniels    01/10/19 07:58:12

  Modified:    java/src/org/apache/axis MessageContext.java
               java/src/org/apache/axis/session Session.java
                        SimpleSession.java
               java/src/org/apache/axis/transport/http AxisHttpSession.java
  Added:       java/src/org/apache/axis/handlers SimpleSessionHandler.java
  Log:
  Expand Session class a little, and an initial implementation of a
  Handler to do sessions based on SOAP headers.
  
  With help from Christoph Cemper (christoph@cemper.com).
  
  Revision  Changes    Path
  1.58      +10 -1     xml-axis/java/src/org/apache/axis/MessageContext.java
  
  Index: MessageContext.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/MessageContext.java,v
  retrieving revision 1.57
  retrieving revision 1.58
  diff -u -r1.57 -r1.58
  --- MessageContext.java	2001/10/18 14:26:39	1.57
  +++ MessageContext.java	2001/10/19 14:58:12	1.58
  @@ -60,6 +60,7 @@
   import org.apache.axis.registries.HandlerRegistry;
   import org.apache.axis.session.Session;
   import org.apache.axis.utils.AxisClassLoader;
  +import org.apache.axis.client.AxisClient;
   import org.apache.log4j.Category;
   
   import java.util.Hashtable;
  @@ -384,7 +385,15 @@
               setTypeMappingRegistry(tmr);
           }
       }
  -
  +    
  +    /**
  +     * Let us know whether this is the client or the server.
  +     */
  +    public boolean isClient()
  +    {
  +        return (axisEngine instanceof AxisClient);
  +    }
  +    
       /** Contains an instance of Handler, which is the
        *  ServiceContext and the entrypoint of this service.
        *
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/handlers/SimpleSessionHandler.java
  
  Index: SimpleSessionHandler.java
  ===================================================================
  package org.apache.axis.handlers;
  
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" 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 name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * 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/>.
   */
  
  import org.apache.axis.MessageContext;
  import org.apache.axis.Message;
  import org.apache.axis.AxisFault;
  import org.apache.axis.AxisEngine;
  import org.apache.axis.session.SimpleSession;
  import org.apache.axis.encoding.SOAPTypeMappingRegistry;
  import org.apache.axis.message.SOAPEnvelope;
  import org.apache.axis.message.SOAPHeader;
  import org.apache.log4j.Category;
  
  import javax.xml.rpc.namespace.QName;
  import java.util.Hashtable;
  import java.util.Set;
  import java.util.Iterator;
  
  /** This handler uses SOAP headers to do simple session management.
   * 
   * <p>Essentially, you install it on both the request and response chains of
   * your service, on both the client and the server side.</p>
   * 
   * <p>ON THE SERVER:</p>
   * <ul>
   * <li>The REQUEST is checked for a session ID header.  If present, we
   *     look up the correct SimpleSession.  If not, we create a new session.
   *     In either case, we install the session into the MessageContext, and
   *     put its ID in the SESSION_ID property.
   * <li>The RESPONSE gets a session ID header tacked on, assuming we found a
   *     SESSION_ID property in the MessageContext.
   * </ul>
   * <p>ON THE CLIENT:</p>
   * <ul>
   * <li>The RESPONSE messages are checked for session ID headers.  If present,
   *     we pull the ID out and insert it into an option in the AxisClient.
   *     This works because a given Call object is associated with a single
   *     AxisClient.  However, we might want to find a way to put it into the
   *     Call object itself, which would make a little more sense.  This would
   *     mean being able to get to the Call from the MC, i.e. adding a getCall()
   *     API (which would only work on the client side)....
   * <li>When REQUESTS are generated, we look to see if an ID option is present
   *     in the AxisClient associated with the MessageContext.  If so, we
   *     insert a session ID header with the appropriate ID.
   * </ul>
   * 
   * <p>SimpleSessions are "reaped" periodically via a very simplistic
   * mechanism.  Each time the handler is invoke()d we check to see if more
   * than <b>reapPeriodicity</b> milliseconds have elapsed since the last
   * reap.  If so, we walk the collection of active Sessions, and for each
   * one, if it hasn't been "touched" (i.e. had a getProperty() or setProperty()
   * performed) in longer than its timeout, we remove it from the collection.</p>
   *
   * @author Glen Daniels (gdaniels@macromedia.com)
   */
  public class SimpleSessionHandler extends BasicHandler
  {
      static Category category =
              Category.getInstance(SimpleSessionHandler.class.getName());
  
      public static final String SESSION_ID = SESSION_ID;
      public static final String SESSION_NS = "http://xml.apache.org/axis/session";
      public static final String SESSION_LOCALPART = "sessionID";
      public static final QName sessionHeaderName = new QName(SESSION_NS,
                                                              SESSION_LOCALPART);
  
      private Hashtable activeSessions = new Hashtable();
      private long curSessionID = 0;
      
      // Reap timed-out sessions on the first request after this many
      // milliseconds.
      private long reapPeriodicity = 60000;
      private long lastReapTime = 0;
      
      /**
       * Process a MessageContext.
       */ 
      public void invoke(MessageContext context) throws AxisFault
      {
          // Should we reap timed out sessions?
          long curTime = System.currentTimeMillis();
          boolean reap = false;
          
          // Minimize synchronicity, just check in here, do reap later.
          synchronized (this) {
              if (curTime > lastReapTime + reapPeriodicity) {
                  reap = true;
                  lastReapTime = curTime;
              }
          }
          
          if (reap) {
              Set keys = activeSessions.keySet();
              Object key;
              for (Iterator i = keys.iterator(); i.hasNext();) {
                  key = i.next();
                  SimpleSession session = (SimpleSession)activeSessions.get(key);
                  if (session.getTimeout() >
                       (curTime - session.getLastAccessTime())) {
                      category.debug("Session id " + key + " timed out.");
                      // Hashtable is synchronized, so this is safe.
                      activeSessions.remove(key);
                  }
              }
          }
          
          if (context.isClient()) {
              doClient(context);
          } else {
              doServer(context);
          }
      }
  
      /**
       * Client side of processing.
       */ 
      public void doClient(MessageContext context) throws AxisFault
      {
          if (context.getPastPivot()) {
              // This is a response.  Check it for the session header.
              Message msg = context.getResponseMessage();
              if (msg == null)
                  return;
              SOAPEnvelope env = msg.getAsSOAPEnvelope();
              SOAPHeader header = env.getHeaderByName(SESSION_NS,
                                                      SESSION_LOCALPART);
              if (header == null)
                  return;
              
              // Got one!
              try {
                  Long id = (Long)header.
                               getValueAsType(SOAPTypeMappingRegistry.XSD_LONG);
                  // Store it away.
                  AxisEngine engine = context.getAxisEngine();
                  engine.addOption(SESSION_ID, id);
              } catch (Exception e) {
                  throw new AxisFault(e);
              }
          } else {
              AxisEngine engine = context.getAxisEngine();
              Long id = (Long)engine.getOption(SESSION_ID);
              if (id == null)
                  return;
              
              // We have a session ID, so insert the header
              Message msg = context.getRequestMessage();
              if (msg == null)
                  throw new AxisFault("No request message in MessageContext?");
              
              SOAPEnvelope env = msg.getAsSOAPEnvelope();
              SOAPHeader header = new SOAPHeader(SESSION_NS,
                                                 SESSION_LOCALPART,
                                                 id);
              env.addHeader(header);
          }
      }
  
      /**
       * Server side of processing.
       */ 
      public void doServer(MessageContext context) throws AxisFault
      {
          if (context.getPastPivot()) {
              // This is a response.  Add the session header if we have an
              // ID.
              Long id = (Long)context.getProperty(SESSION_ID);
              if (id == null)
                  return;
              
              Message msg = context.getResponseMessage();
              if (msg == null)
                  return;
              SOAPEnvelope env = msg.getAsSOAPEnvelope();
              SOAPHeader header = new SOAPHeader(SESSION_NS,
                                                 SESSION_LOCALPART,
                                                 id);
              env.addHeader(header);
          } else {
              // Request.  Set up the session if we find the header.
              Message msg = context.getRequestMessage();
              if (msg == null)
                  throw new AxisFault("No request message?");
              
              SOAPEnvelope env = msg.getAsSOAPEnvelope();
              SOAPHeader header = env.getHeaderByName(SESSION_NS,
                                                      SESSION_LOCALPART);
              Long id;
              
              if (header != null) {
                  // Got one!
                  try {
                      id = (Long)header.
                              getValueAsType(SOAPTypeMappingRegistry.XSD_LONG);
                  } catch (Exception e) {
                      throw new AxisFault(e);
                  }
              } else {
                  id = getNewSession();
              }
              
              SimpleSession session = (SimpleSession)activeSessions.get(id);
              if (session == null) {
                  // Must have timed out, get a new one.
                  id = getNewSession();
                  session = (SimpleSession)activeSessions.get(id);
              }
  
              // This session is still active...
              session.touch();
              
              // Store it away in the MessageContext.
              context.setSession(session);
              context.setProperty(SESSION_ID, id);
          }
      }
      
      /**
       * Generate a new session, register it, and return its ID.
       * 
       * @return the new session's ID for later lookup.
       */ 
      private synchronized Long getNewSession()
      {
          Long id = new Long(curSessionID++);
          SimpleSession session = new SimpleSession();
          activeSessions.put(id, session);
          return id;
      }
  
      public void undo(MessageContext msgContext) {
          category.debug("Enter: SimpleSessionHandler::undo" );
          category.debug("Exit: SimpleSessionHandler::undo" );
      }
  }
  
  
  
  1.3       +12 -0     xml-axis/java/src/org/apache/axis/session/Session.java
  
  Index: Session.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/session/Session.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Session.java	2001/06/14 07:04:12	1.2
  +++ Session.java	2001/10/19 14:58:12	1.3
  @@ -90,4 +90,16 @@
        * out and invalidate.  "inactivity" is implementation-specific.
        */
       public void setTimeout(int timeout);
  +    
  +    /**
  +     * Return the sessions' time-to-live.
  +     * 
  +     * @return the timeout value for this session.
  +     */ 
  +    public int getTimeout();
  +    
  +    /**
  +     * "Touch" the session (mark it recently used)
  +     */ 
  +    public void touch();
   }
  
  
  
  1.3       +25 -0     xml-axis/java/src/org/apache/axis/session/SimpleSession.java
  
  Index: SimpleSession.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/session/SimpleSession.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SimpleSession.java	2001/06/14 07:04:13	1.2
  +++ SimpleSession.java	2001/10/19 14:58:12	1.3
  @@ -71,6 +71,14 @@
        */
       private int timeout = -1;
       private long lastTouched;
  +    
  +    /**
  +     * Default constructor - set lastTouched to now
  +     */ 
  +    public SimpleSession()
  +    {
  +        lastTouched = System.currentTimeMillis();
  +    }
                             
       /** Get a property from the session
        *
  @@ -117,5 +125,22 @@
       public void setTimeout(int timeout)
       {
           this.timeout = timeout;
  +    }
  +    
  +    public int getTimeout()
  +    {
  +        return timeout;
  +    }
  +
  +    /**
  +     * "Touch" the session (mark it recently used)
  +     */
  +    public void touch() {
  +        lastTouched = System.currentTimeMillis();
  +    }
  +
  +    public long getLastAccessTime()
  +    {
  +        return lastTouched;
       }
   }
  
  
  
  1.5       +16 -0     xml-axis/java/src/org/apache/axis/transport/http/AxisHttpSession.java
  
  Index: AxisHttpSession.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/transport/http/AxisHttpSession.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- AxisHttpSession.java	2001/10/03 15:30:07	1.4
  +++ AxisHttpSession.java	2001/10/19 14:58:12	1.5
  @@ -120,4 +120,20 @@
       {
           rep.setMaxInactiveInterval(timeout);
       }
  +
  +    /**
  +     * Return the sessions' time-to-live.
  +     * 
  +     * @return the timeout value for this session.
  +     */
  +    public int getTimeout() {
  +        return rep.getMaxInactiveInterval();
  +    }
  +
  +    /**
  +     * "Touch" the session (mark it recently used)
  +     */
  +    public void touch() {
  +        // ???
  +    }
   }