View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.layout.impl;
18  
19  import java.security.Principal;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.prefs.BackingStoreException;
27  import java.util.prefs.Preferences;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jetspeed.JetspeedActions;
32  import org.apache.jetspeed.ajax.AJAXException;
33  import org.apache.jetspeed.ajax.AjaxAction;
34  import org.apache.jetspeed.ajax.AjaxBuilder;
35  import org.apache.jetspeed.container.session.PortalSessionsManager;
36  import org.apache.jetspeed.request.RequestContext;
37  import org.apache.jetspeed.security.SecurityException;
38  import org.apache.jetspeed.security.SecurityHelper;
39  import org.apache.jetspeed.security.User;
40  import org.apache.jetspeed.security.UserManager;
41  import org.apache.jetspeed.security.UserPrincipal;
42  import org.apache.jetspeed.statistics.PortalStatistics;
43  import org.apache.jetspeed.statistics.UserStats;
44  
45  /***
46   * Returns the list of currently logged in users
47   * and optionally also the offline users and
48   * number of guest user sessions
49   * 
50   * AJAX action:
51   * 		action: getuserlist
52   * 
53   * AJAX Parameters: 
54   * 		guest:	whether we should return also the guest sessions
55   * 			   	true | false (default)
56   *      userinfo: whether we should include also userinfo
57   *      		true | false (default)
58   *      offline: whether we should include offline users
59   *      		true | false (default)
60   *      all: 	return every bits and piece there is
61   *      		true | false (default)
62   * @author <a href="mailto:mikko.wuokko@evtek.fi">Mikko Wuokko</a>
63   * @version $Id: $
64   */
65  public class GetUserListAction 
66      extends BaseUserAction 
67      implements AjaxAction, AjaxBuilder, Constants
68  {
69      protected Log log = LogFactory.getLog(GetUserListAction.class);
70      private PortalStatistics pstats = null;
71      private PortalSessionsManager psm = null;
72      // By default the protection is set to all
73      private String protectionScope = "all";
74  
75      private final String PARAM_GUEST = "guest";
76      private final String PARAM_USERINFO = "userinfo";
77      private final String PARAM_OFFILE = "offline";
78      private final String PARAM_ALL = "all";
79      
80      public GetUserListAction(String template, 
81                              String errorTemplate, 
82                              UserManager um,
83                              PortalStatistics pstats,
84                              PortalSessionsManager psm)
85      {
86          this(template, errorTemplate, um, pstats, psm, null); 
87      }
88      
89      public GetUserListAction(String template, 
90              String errorTemplate, 
91              UserManager um,
92              PortalStatistics pstats,
93              PortalSessionsManager psm, 
94              RolesSecurityBehavior securityBehavior)
95      {
96      	super(template, errorTemplate, um, securityBehavior); 
97      	this.pstats = pstats;
98      	this.psm = psm;
99      }
100     
101     public GetUserListAction(String template, 
102             String errorTemplate, 
103             UserManager um,
104             PortalStatistics pstats,
105             PortalSessionsManager psm, 
106             RolesSecurityBehavior securityBehavior,
107             String protectionScope)
108     {
109     	super(template, errorTemplate, um, securityBehavior); 
110     	this.pstats = pstats;
111     	this.psm = psm;
112     	this.protectionScope = protectionScope;
113     }
114     
115     public boolean run(RequestContext requestContext, Map resultMap)
116             throws AJAXException
117     {
118         boolean success = true;
119         String status = "success";
120         
121     	boolean includeGuests;
122     	boolean includeUserInfo;
123         boolean includeOffline;
124         boolean includeAll = isTrue(getActionParameter(requestContext, PARAM_ALL));
125         
126         // Set everything true if "all" is set to true
127         if(includeAll){
128         	includeGuests = true;
129         	includeUserInfo = true;
130         	includeOffline = true;
131         }
132         else
133         {        
134         	includeOffline = isTrue(getActionParameter(requestContext, PARAM_OFFILE));
135         	includeGuests = isTrue(getActionParameter(requestContext, PARAM_GUEST));
136         	includeUserInfo = isTrue(getActionParameter(requestContext, PARAM_USERINFO));
137         }
138         
139     	// Do a security check if a behavior is set
140     	if(securityBehavior != null)
141     	{
142     		// If protection is set to "none", everything will be allowed
143     		if(!checkAccess(requestContext, JetspeedActions.EDIT) && !this.protectionScope.equals("none"))
144     		{
145     			// If we have set protection to private only and security check failed,
146     			// will return basic information still
147     			if(this.protectionScope.equals("private-offline"))
148     			{
149     				// If private and offline information is protected, disable that and offline users.
150     				includeUserInfo = false;
151     				includeOffline = false;
152     			}
153     			else if(this.protectionScope.equals("private"))
154     			{
155     				// Only private information is protected.
156     				includeUserInfo = false;
157     			}
158     			else
159     			{
160     				
161 	    			success = false;
162 	                resultMap.put(REASON, "Insufficient access see user details.");                
163 	                return success;
164     			}
165     		}
166     	}
167         
168         int numberOfCurrentUsers = 0;
169         int numberOfCurrentLoggedInUsers = 0;
170         
171         Collection users = new ArrayList();
172         Collection loggedInUsers = new ArrayList();
173         Collection offlineUsers = new ArrayList();
174 
175         try
176         {
177             resultMap.put(ACTION, "getuserlist");
178             // Check that the statistics is not disabled 
179         	if(pstats != null)
180         	{
181         		// Get the user counts
182         		numberOfCurrentUsers = psm.sessionCount();
183         		numberOfCurrentLoggedInUsers = pstats.getNumberOfLoggedInUsers();
184 
185         		/*
186         		 * An helper to track the users that have already been added to the resultMap 
187         		 * as logged in users, so there wouldn't be an offline duplicate. Trying
188         		 * to prevent some overhead with this.
189         		 * Needs some more thinking, maybe some helper functions to portal statistics
190         		 * to get just the names of the logged in users for contains comparison.
191         		 */ 
192         		List addedUserNames = new ArrayList();
193         		
194         		// If no logged in users, nothing to do
195         		if(numberOfCurrentLoggedInUsers > 0)
196         		{
197 
198         			// Logged in users is a list of UserStats objects
199         			Iterator usersIter = pstats.getListOfLoggedInUsers().iterator();
200         			while(usersIter.hasNext())
201         			{
202         				Map userMap = (Map)usersIter.next();
203         				if(userMap != null && userMap.size() > 0)
204         				{
205         					Iterator userKeyIter = userMap.keySet().iterator();
206         					while(userKeyIter.hasNext())
207         					{
208         						String userStatKey = String.valueOf(userKeyIter.next());
209         						UserStats userStat = (UserStats)userMap.get(userStatKey);
210         						
211         						Map singleUserMap = new HashMap();
212         						singleUserMap.put(USERNAME, userStat.getUsername());
213                                 singleUserMap.put(SESSIONS, new Integer(userStat.getNumberOfSessions()));
214         						singleUserMap.put(STATUS, ONLINE);
215         						singleUserMap.put(IPADDRESS, userStat.getInetAddress().getHostAddress());
216         						if(includeUserInfo)
217         						{
218         							singleUserMap.put(USERINFO, getUserInfo(userStat.getUsername()));
219         						}
220         						
221         						// Add user to the helper if not added yet
222         						if(!addedUserNames.contains(userStat.getUsername()))
223         							addedUserNames.add(userStat.getUsername());
224         						
225         						loggedInUsers.add(singleUserMap);
226         					}
227         					        					
228         				}
229         			}
230         			
231         			// Adding online users to the collection
232         			users.addAll(loggedInUsers);
233                 }
234         		
235         		// Check whether we should iterate through all of the users or just logged in ones
236     			if(includeOffline)
237     			{
238     				Iterator allUusers = userManager.getUsers("");
239     				while(allUusers.hasNext())
240         			{
241         				User user = (User)allUusers.next();
242         				Principal userPrincipal = SecurityHelper.getPrincipal(user.getSubject(), UserPrincipal.class);
243         				if(userPrincipal != null)
244         				{
245         					// Check if this users is already added as online user
246         					if(!addedUserNames.contains(userPrincipal.getName()))
247         					{
248         						Map userMap = new HashMap();
249         						userMap.put(USERNAME, userPrincipal.getName());
250         						userMap.put(STATUS, OFFLINE);
251         						if(includeUserInfo)
252         						{
253         							userMap.put(USERINFO, getUserInfo(userPrincipal.getName()));        						}
254 
255         						offlineUsers.add(userMap);
256         					}
257         				}
258         			}
259     				
260         			// Adding online users to the collection
261         			users.addAll(offlineUsers);
262     			}
263         		
264         		// Add the logged in users to resultMap
265                 resultMap.put(USERS, users);
266                 
267         		if(includeGuests)        			
268         		{
269         			// Add number of guest accounts to resultMap
270         			int guestUserCount = numberOfCurrentUsers - numberOfCurrentLoggedInUsers;
271                     resultMap.put(GUESTUSERS, new Integer(guestUserCount));
272         		}
273                 	
274         	}
275         	else
276         	{
277         		status = "failure";
278         		resultMap.put(REASON, "Statistics not available");
279         		return false;
280         	}
281             resultMap.put(STATUS, status);
282         } 
283         catch (Exception e)
284         {
285             log.error("exception statistics access", e);
286             resultMap.put(REASON, e.toString());
287             success = false;
288         }
289         return success;
290     }    
291 
292     
293     /***
294      * Helper method to get the user information of an user as Map.
295      * 
296      * @param username Name of the user of request
297      * @return Map containing the user information keyed by the name of the attribute.
298      * @throws SecurityException
299      * @throws BackingStoreException
300      */
301     private Map getUserInfo(String username) throws SecurityException, BackingStoreException
302     {
303     	Map userInfo = new HashMap();
304     	User user =  userManager.getUser(username);
305 		if(user != null)
306 		{
307         	Preferences userPrefs = user.getUserAttributes();
308         	String[] userPrefKeys = userPrefs.keys();
309         
310         	for(int i = 0; i<userPrefKeys.length; i++)
311         	{
312         		userInfo.put(userPrefKeys[i], userPrefs.get(userPrefKeys[i], "No value"));                		
313         	}
314 		}
315 		
316 		return userInfo;
317     }
318     
319 }