Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/j2ee/session/BindingInterceptor.java


1   // ========================================================================
2   // Copyright (c) 2002 Mort Bay Consulting (Australia) Pty. Ltd.
3   // $Id: BindingInterceptor.java,v 1.2 2003/10/05 14:04:54 gregwilkins Exp $
4   // ========================================================================
5   
6   package org.mortbay.j2ee.session;
7   
8   //----------------------------------------
9   
10  import java.rmi.RemoteException;
11  import javax.servlet.http.HttpSession;
12  import javax.servlet.http.HttpSessionBindingEvent;
13  import javax.servlet.http.HttpSessionBindingListener;
14  import org.jboss.logging.Logger;
15  
16  //----------------------------------------
17  
18  /**
19   * A <code>BindingInterceptor</code> is responsible for notifying
20   * HttpSessionAttributeListeners when Attributes are added to, removed
21   * from or replaced in a Session and HttpSessionBindingListeners when
22   * attributes are bound into or unbound from a Session. <P/> This is
23   * an expensive Interceptor to use since it requires that on rebinding
24   * an attribute in the Session, the old value is returned in case it
25   * is a Listener requiring notification of it's removal.If you are
26   * using a distributed store, this requirement will result in a
27   * serialisation and network traffic overhead which may not actually
28   * be necessary. Unfortunately it would be expensive to decide at
29   * runtime whether to add this interceptor since one of these
30   * Listeners might be bound into the session at any time from any
31   * node. This may be addressed in a future release.
32   *
33   * @author <a href="mailto:jules@mortbay.com">Jules Gosnell</a>
34   * @version 1.0
35   */
36  public class BindingInterceptor
37    extends StateInterceptor
38  {
39    protected static final Logger _log=Logger.getLogger(BindingInterceptor.class);
40    // All Interceptors are expected to provide this constructor...
41  
42    // HttpSessionBindingListeners are held in the SessionManager -
43    // because they are attached at the webapp, rather than session
44    // instance level. So they are notified via the Manager.
45  
46    protected Object
47      notifyValueUnbound(String name, Object value)
48    {
49      if (!(value instanceof HttpSessionBindingListener))
50        return value;
51  
52      HttpSessionBindingEvent event=new HttpSessionBindingEvent(getSession(), name, value);
53      ((HttpSessionBindingListener)value).valueUnbound(event);
54      event=null;
55  
56      return value;
57    }
58  
59    protected Object
60      notifyValueBound(String name, Object value)
61    {
62      if (!(value instanceof HttpSessionBindingListener))
63        return value;
64  
65      HttpSessionBindingEvent event=new HttpSessionBindingEvent(getSession(), name, value);
66      ((HttpSessionBindingListener)value).valueBound(event);
67      event=null;
68  
69      return value;
70    }
71  
72    // if we knew whether there were any HttpSessionAttributeListeners
73    // registered with our Manager and the DistributedState knew whether
74    // the oldValue was an HttpSessionBindingListener then we could make
75    // the decision in the e.g. EJB tier as to whether to return the
76    // oldValue or not. Unfortunately, all attributes are preserialised
77    // in the Web Tier, in case the EJB tier doesn't have their class,
78    // so this interceptor would have to mark relevant attributes on
79    // their way into the EJB tier, so it would know whether to return
80    // them in a set/removeAttribute situation later... - How can this
81    // be done efficiently ?
82  
83    /**
84     * <code>setAttribute</code> is overriden in order to notify
85     * HttpSessionAttribute and HttpSessionBindingListeners of relative
86     * Attribute changes.
87     *
88     * @param name a <code>String</code> value
89     * @param value an <code>Object</code> value
90     * @return an <code>Object</code> value
91     * @exception RemoteException if an error occurs
92     */
93    public Object
94      setAttribute(String name, Object value, boolean returnValue)
95      throws RemoteException
96    {
97      // assert(name!=null);
98      // assert(value!=null);
99  
100     boolean needOldValue=true;
101 
102     // we want the old binding back if it was an HttpSessionBindingListener
103     Object oldValue=super.setAttribute(name, value, true);
104 
105     // send binding notifications
106 
107     try
108     {
109       if (oldValue!=null)
110   notifyValueUnbound(name, oldValue);
111 
112       notifyValueBound(name, value);
113 
114       // send attribute notifications
115       if (oldValue!=null)
116   getManager().notifyAttributeReplaced(getSession(), name, oldValue);
117       else
118   getManager().notifyAttributeAdded(getSession(), name, value);
119     }
120     catch (Throwable t)
121     {
122       _log.error("error in user owned Listener - notifications may be incomplete", t);
123     }
124 
125     return oldValue;
126   }
127 
128   /**
129    * <code>removeAttribute</code> is overriden in order to notify
130    * HttpSessionAttribute and HttpSessionBindingListeners of relative
131    * Attribute changes.
132    *
133    * @param name a <code>String</code> value
134    * @return an <code>Object</code> value
135    * @exception RemoteException if an error occurs
136    */
137   public Object
138     removeAttribute(String name, boolean returnValue)
139     throws RemoteException
140   {
141     // we want the old binding back if it was an HttpSessionBindingListener
142     Object oldValue=super.removeAttribute(name, true);
143 
144     if (oldValue!=null)
145     {
146       try
147       {
148   notifyValueUnbound(name, oldValue);
149   getManager().notifyAttributeRemoved(getSession(), name, oldValue);
150       }
151       catch (Throwable t)
152       {
153   _log.error("error in user owned Listener - notifications may be incomplete", t);
154       }
155     }
156 
157     return oldValue;
158   }
159 
160   //  public Object clone() { return null; } // Stateful
161 }