/*
* (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.ecm.webapp.security;
import static org.jboss.seam.ScopeType.SESSION;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.model.SelectItem;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.NuxeoPrincipal;
import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
import org.nuxeo.ecm.directory.SizeLimitExceededException;
import org.nuxeo.ecm.platform.usermanager.UserManager;
import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
/**
* POJO class that extracts and holds the list of the users from backend.
*
* @author Razvan Caraghin
* @author <a href="mailto:tmartins@nuxeo.com">Thierry Martins</a>
*/
@Name("principalListManager")
@Scope(SESSION)
public class PrincipalListManager implements Serializable {
public static final String USER_TYPE = "USER_TYPE";
public static final String GROUP_TYPE = "GROUP_TYPE";
public static final String USER_GROUP_TYPE = "USER_GROUP_TYPE";
public static final String USER_ICON = "/icons/user.png";
public static final String GROUP_ICON = "/icons/group.png";
public static final String USER_ICON_ALT = "user.png";
public static final String GROUP_ICON_ALT = "group.png";
public static final int MAX_SEARCH_RESULTS = 20;
private static final long serialVersionUID = 1859670282887307916L;
private static final Log log = LogFactory.getLog(PrincipalListManager.class);
public final Map<String, String> iconPath;
public final Map<String, String> iconAlt;
@In(create = true, required = false)
protected transient CoreSession documentManager;
@In(create = true)
protected transient UserManager userManager;
@In(create = true)
protected transient ResourcesAccessor resourcesAccessor;
protected SelectItem[] availablePrincipals;
protected Map<String, String> principalTypes = new HashMap<String, String>();
protected String selectedPrincipal;
protected String searchType;
protected List<String> selectedUsers;
@In(required = false)
String searchFilter;
private boolean searchOverflow;
// cache of previous results
protected transient List<Map<String, Object>> previousSuggestedEntries;
// previous search filter
protected transient String previousSearchFilter;
// previous search type
protected transient String previousSearchType;
// previous search overflow
protected transient boolean previousSearchOverflow;
public PrincipalListManager() {
iconPath = new HashMap<String, String>();
iconAlt = new HashMap<String, String>();
iconPath.put(USER_TYPE, USER_ICON);
iconPath.put(GROUP_TYPE, GROUP_ICON);
iconAlt.put(USER_TYPE, USER_ICON_ALT);
iconAlt.put(GROUP_TYPE, GROUP_ICON_ALT);
searchType = USER_GROUP_TYPE;
}
public String getSearchFilter() {
return searchFilter;
}
public void setSearchFilter(String searchFilter) {
Context pageContext = Contexts.getPageContext();
if (pageContext != null) {
pageContext.set("searchFilter", searchFilter);
}
this.searchFilter = searchFilter;
}
public String getSelectedPrincipal() {
return selectedPrincipal;
}
public String getPrincipalType(String name) throws ClientException {
// happens when used in NXMethodResults in A4JCalls !!!
if (name == null) {
return null;
}
if (principalTypes == null) {
principalTypes = new HashMap<String, String>();
}
String type = principalTypes.get(name);
if (type == null) {
if (userManager.getGroup(name) != null) {
type = GROUP_TYPE;
} else {
type = USER_TYPE;
}
principalTypes.put(name, type);
}
return type;
}
public void setSelectedPrincipal(String selectedPrincipal) {
this.selectedPrincipal = selectedPrincipal;
}
protected DocumentModelList getSuggestedUsers() {
if (searchFilter == null || searchFilter.length() == 0) {
return new DocumentModelListImpl();
}
DocumentModelList result;
try {
result = userManager.searchUsers(searchFilter);
} catch (SizeLimitExceededException e) {
searchOverflow = true;
return new DocumentModelListImpl();
} catch (ClientException e) {
// XXX: this exception should not be catched
log.error("error searching for principals: " + e.getMessage());
return new DocumentModelListImpl();
}
if (result.size() > MAX_SEARCH_RESULTS) {
searchOverflow = true;
return new DocumentModelListImpl();
}
return result;
}
protected DocumentModelList getSuggestedGroups() {
if (searchFilter == null || searchFilter.length() == 0) {
return new DocumentModelListImpl();
}
DocumentModelList result;
try {
result = userManager.searchGroups(searchFilter);
} catch (SizeLimitExceededException e) {
searchOverflow = true;
return new DocumentModelListImpl();
} catch (ClientException e) {
log.error("error searching for groups: " + e.getMessage());
return new DocumentModelListImpl();
}
if (result.size() > MAX_SEARCH_RESULTS) {
searchOverflow = true;
return new DocumentModelListImpl();
}
return result;
}
public List<Map<String, Object>> getSuggestedEntries() {
if (searchFilter == null || searchFilter.length() == 0) {
return Collections.emptyList();
}
if (searchFilter.equals(previousSearchFilter)
&& searchType.equals(previousSearchType)) {
searchOverflow = previousSearchOverflow;
return previousSuggestedEntries;
}
searchOverflow = false;
DocumentModelList users;
if (USER_TYPE.equals(searchType) || USER_GROUP_TYPE.equals(searchType)
|| StringUtils.isEmpty(searchType)) {
users = getSuggestedUsers();
} else {
users = new DocumentModelListImpl();
}
DocumentModelList groups;
if (GROUP_TYPE.equals(searchType) || USER_GROUP_TYPE.equals(searchType)
|| StringUtils.isEmpty(searchType)) {
groups = getSuggestedGroups();
} else {
groups = new DocumentModelListImpl();
}
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(
users.size() + groups.size());
for (DocumentModel user : users) {
if (user == null) {
continue;
}
try {
NuxeoPrincipal principal = userManager.getPrincipal(user.getId());
String name = principal.getName();
StringBuilder label = new StringBuilder(name).append(" (");
if (principal.getFirstName() != null) {
label.append(principal.getFirstName());
}
if (principal.getLastName() != null) {
label.append(' ').append(principal.getLastName());
}
label.append(')');
Map<String, Object> entry = new HashMap<String, Object>();
entry.put("label", label.toString());
entry.put("id", name);
entry.put("icon", "icons/user.png");
result.add(entry);
} catch (ClientException e) {
log.info("Unable to get Principal from " + user.getId());
log.debug(e);
}
}
for (DocumentModel group : groups) {
Map<String, Object> entry = new HashMap<String, Object>();
try {
entry.put("label", group.getProperty(
userManager.getGroupSchemaName(), userManager.getGroupLabelField()));
} catch (ClientException e) {
log.warn("Unable to get group label of " + group.getId());
log.debug(e);
entry.put("label", group.getId());
}
entry.put("id", group.getId());
entry.put("icon", "icons/group.png");
result.add(entry);
}
// put in cache
previousSuggestedEntries = result;
previousSearchOverflow = searchOverflow;
previousSearchType = searchType;
previousSearchFilter = searchFilter;
return result;
}
public boolean getDisplaySearchResults() {
return searchFilter != null && searchFilter.length() != 0;
}
public void resetSearchFilter() {
searchFilter = null;
}
public String addToSelectedUsers(String userName) {
if (selectedUsers == null) {
selectedUsers = new ArrayList<String>();
}
if (!selectedUsers.contains(userName)) {
selectedUsers.add(userName);
}
return null;
}
public String removeFromSelectedUsers(String userName) {
if (selectedUsers == null) {
selectedUsers = new ArrayList<String>();
}
if (selectedUsers.contains(userName)) {
selectedUsers.remove(userName);
}
return null;
}
public List<String> getSelectedUsers() {
if (selectedUsers == null) {
return new ArrayList<String>();
}
return selectedUsers;
}
public void setSelectedUsers(List<String> selectedUsers) {
this.selectedUsers = selectedUsers;
}
public boolean getSelectedUserListEmpty() {
return selectedUsers == null || selectedUsers.isEmpty();
}
public void resetSelectedUserList() {
selectedUsers = null;
}
public boolean getSearchOverflow() {
return searchOverflow;
}
public String getSearchType() {
return searchType;
}
public void setSearchType(String searchType) {
if (searchType == null) {
searchType = USER_GROUP_TYPE;
}
this.searchType = searchType;
}
}