View Javadoc

1   //
2   // Copyright (c) 2003-2005, Caltha - Gajda, Krzewski, Mach, Potempski Sp.J. 
3   // All rights reserved. 
4   //
5   // Redistribution and use in source and binary forms, with or without modification,  
6   // are permitted provided that the following conditions are met: 
7   //
8   // * Redistributions of source code must retain the above copyright notice,  
9   //   this list of conditions and the following disclaimer. 
10  // * Redistributions in binary form must reproduce the above copyright notice,  
11  //   this list of conditions and the following disclaimer in the documentation  
12  //   and/or other materials provided with the distribution. 
13  // * Neither the name of the Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.  
14  //   nor the names of its contributors may be used to endorse or promote products  
15  //   derived from this software without specific prior written permission. 
16  //
17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  
18  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  
19  // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
20  // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,  
21  // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  
22  // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
23  // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
24  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  
25  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  
26  // POSSIBILITY OF SUCH DAMAGE.
27  //
28  package org.objectledge.authentication;
29  
30  import java.security.Principal;
31  import java.util.Date;
32  import java.util.HashMap;
33  import java.util.HashSet;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import javax.servlet.http.HttpSession;
38  import javax.servlet.http.HttpSessionBindingEvent;
39  import javax.servlet.http.HttpSessionBindingListener;
40  
41  import org.objectledge.context.Context;
42  import org.objectledge.pipeline.ProcessingException;
43  import org.objectledge.pipeline.Valve;
44  import org.objectledge.web.HttpContext;
45  
46  /***
47   * A valve that 
48   * 
49   * @version $Id: UserTrackingValve.java,v 1.1 2005/07/26 09:25:47 rafal Exp $
50   * @author <a href="mailto:rafal@caltha.pl">Rafal Krzewski</a>
51   */
52  public class UserTrackingValve
53      implements Valve
54  {
55      private final Map<Principal,PunchCard> cardRack = new HashMap<Principal,PunchCard>();
56      
57      /***
58       * {@inheritDoc}
59       */
60      public void process(Context context)
61          throws ProcessingException
62      {
63          AuthenticationContext authContext = AuthenticationContext.getAuthenticationContext(context);
64          if(authContext != null && authContext.isUserAuthenticated())
65          {
66              synchronized(cardRack)
67              {
68                  Principal principal = authContext.getUserPrincipal();
69                  PunchCard card = cardRack.get(principal);
70                  if(card == null)
71                  {
72                      card =  new PunchCard(principal);
73                      cardRack.put(principal, card);
74                      HttpContext httpContext = HttpContext.getHttpContext(context);
75                      HttpSession session = httpContext.getRequest().getSession();
76                      session.setAttribute(PunchCard.class.getName(), card);
77                  }
78                  else
79                  {
80                      card.touch();
81                  }
82              }
83          }
84      }
85  
86      /***
87       * Returns the principals of all users that have an active session.
88       * 
89       * @return a set of principal objects.
90       */
91      public Set<Principal> getLoggedInUsers()
92      {
93          synchronized(cardRack)
94          {
95              return new HashSet<Principal>(cardRack.keySet());
96          }
97      }
98      
99      /***
100      * Returns the timestamp of user's most recent click.
101      * 
102      * @param principal the users's principal.
103      * @return the timestamp of user's most recent click, or null if user is not logged in.
104      */
105     public Date getLastClickTime(Principal principal)
106     {
107         synchronized(cardRack)
108         {
109             PunchCard card = cardRack.get(principal);
110             if(card != null)
111             {
112                 return card.getLastClickTime();
113             }
114             else
115             {
116                 return null;
117             }
118         }
119     }
120     
121     void checkOut(PunchCard card)
122     {
123         synchronized(cardRack)
124         {
125             cardRack.remove(card.getPrincipal());
126         }        
127     }
128     
129     /***
130      * A user's puch card.
131      */
132     private class PunchCard 
133         implements HttpSessionBindingListener
134     {
135         private final Principal principal;
136         
137         private Date lastClickTime;
138 
139         public PunchCard(Principal principal) {
140             this.principal = principal;
141             this.lastClickTime = new Date();
142         }
143         
144         public Principal getPrincipal() {
145             return principal;
146         }
147         
148         public void touch() {
149             lastClickTime = new Date();
150         }
151         
152         public Date getLastClickTime() {
153             return lastClickTime;
154         }                
155 
156         /***
157          * {@inheritDoc}
158          */
159         public void valueBound(HttpSessionBindingEvent arg0)
160         {
161             // ingnore
162         }
163 
164         /***
165          * {@inheritDoc}
166          */
167         public void valueUnbound(HttpSessionBindingEvent event)
168         {
169             if(event.getValue() instanceof PunchCard)
170             {
171                 checkOut((PunchCard)event.getValue());
172             }
173         }
174     }
175 }