org.sakaiproject.umem.tool.ui.UserListBean.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.umem.tool.ui.UserListBean.java

Source

/**********************************************************************************
 * $URL: https://source.sakaiproject.org/contrib/ufp/usermembership/trunk/tool/src/java/org/sakaiproject/umem/tool/ui/UserListBean.java $
 * $Id: UserListBean.java 4381 2007-03-21 11:25:54Z nuno@ufp.pt $
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **********************************************************************************/

package org.sakaiproject.umem.tool.ui;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.Collator;
import java.text.ParseException;
import java.text.RuleBasedCollator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
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.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.db.api.SqlService;
import org.sakaiproject.tool.api.ToolManager;
import org.sakaiproject.umem.api.Authz;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.ResourceLoader;

/**
 * @author <a href="mailto:nuno@ufp.pt">Nuno Fernandes</a>
 */
public class UserListBean {
    private static final long serialVersionUID = 1L;
    private static final String USER_TYPE_ALL = "All";
    private static final String USER_TYPE_NONE = "(no type)";
    private static final String USER_AUTH_ALL = "All";
    private static final String USER_AUTH_INTERNAL = "Internal";
    private static final String USER_AUTH_EXTERNAL = "External";
    private static final String SORT_USER_NAME = "name";
    private static final String SORT_USER_ID = "id";
    private static final String SORT_USER_EMAIL = "email";
    private static final String SORT_USER_TYPE = "type";
    private static final String SORT_USER_AUTHORITY = "authority";
    private static final String SORT_USER_CREATED_ON = "createdOn";
    private static final String SORT_USER_MODIFIED_ON = "modifiedOn";
    private static final String SORT_INTERNAL_USER_ID = "internalUserId";
    private static final String NO_NAME_USER = "";
    private static final String CFG_USER_TYPE_LIMIT_TO_SELF = "userType.limitToSelf";
    private static final String CFG_USER_TYPE_LIMIT_TO_LIST = "userType.limitToList";

    /** Our log (commons). */
    private static Log LOG = LogFactory.getLog(UserListBean.class);

    /** Resource bundle */
    private transient ResourceLoader msgs = new ResourceLoader("org.sakaiproject.umem.tool.bundle.Messages");

    /** Controller fields */
    private List<UserRow> userRows;

    /** Getter vars */
    private boolean allowed = false;
    private boolean refreshQuery = false;
    private boolean renderTable = false;
    private boolean renderPager = true;
    private boolean renderClearSearch = false;
    private int totalItems = -1;
    private int firstItem = 0;
    private int pageSize = 20;
    private String searchKeyword = null;
    private boolean userSortAscending = true;
    private String userSortColumn = SORT_USER_NAME;
    private List userTypes = null;
    private List userAuthorities = null;
    private String selectedUserType = null;
    private String selectedAuthority = USER_AUTH_ALL;
    private String newUserType = null;
    private String newAuthority = USER_AUTH_ALL;

    /** Private vars */
    private static RuleBasedCollator collator; // use
    private String message = "";
    // system
    /** Sakai services vars */
    private transient UserDirectoryService M_uds = (UserDirectoryService) ComponentManager
            .get(UserDirectoryService.class.getName());
    private transient ToolManager M_tm = (ToolManager) ComponentManager.get(ToolManager.class.getName());
    private transient SqlService M_sql = (SqlService) ComponentManager.get(SqlService.class.getName());
    private transient Authz authz = (Authz) ComponentManager.get(Authz.class.getName());

    // ######################################################################################
    // UserRow, UserSitesRow CLASS
    // ######################################################################################
    public static class UserRow implements Serializable {
        private static final long serialVersionUID = 1L;
        private String userID;
        private String userEID;
        private String userDisplayId;
        private String userName;
        private String userEmail;
        private String userType;
        private String authority;
        private String createdOn;
        private String modifiedOn;

        static {
            try {
                collator = new RuleBasedCollator(((RuleBasedCollator) Collator.getInstance()).getRules()
                        .replaceAll("<'\u005f'", "<' '<'\u005f'"));
            } catch (ParseException e) {
                collator = (RuleBasedCollator) Collator.getInstance();
            }
        }

        public UserRow() {
        }

        public UserRow(String userID, String userEID, String userDisplayId, String userName, String userEmail,
                String userType, String authority, String createdOn, String modifiedOn) {
            this.userID = userID;
            this.userEID = userEID;
            this.userDisplayId = userDisplayId;
            this.userName = userName;
            this.userEmail = userEmail;
            this.userType = userType;
            this.authority = authority;
            this.createdOn = createdOn;
            this.modifiedOn = modifiedOn;
        }

        public String getUserEmail() {
            return this.userEmail;
        }

        public String getUserID() {
            return this.userID;
        }

        public String getUserEID() {
            return this.userEID;
        }

        public String getUserDisplayId() {
            return this.userDisplayId;
        }

        public String getUserName() {
            return this.userName;
        }

        public String getUserType() {
            return (this.userType == null) ? "" : this.userType;
        }

        public String getAuthority() {
            return this.authority;
        }

        public String getCreatedOn() {
            return createdOn;
        }

        public String getModifiedOn() {
            return modifiedOn;
        }

        public void setUserRow(UserRow row, String authority) {
            this.userID = row.getUserID();
            this.userEID = row.getUserEID();
            this.userDisplayId = row.getUserDisplayId();
            this.userName = row.getUserName();
            this.userEmail = row.getUserEmail();
            this.userType = row.getUserType();
            this.authority = authority;
            this.createdOn = row.createdOn;
            this.modifiedOn = row.modifiedOn;
        }

        public UserRow getUserRow() {
            return this;
        }
    }

    public static final Comparator<UserRow> getUserRowComparator(final String fieldName,
            final boolean sortAscending, final Collator collator) {
        return new Comparator<UserRow>() {

            public int compare(UserRow o1, UserRow o2) {
                UserRow r1 = (UserRow) o1;
                UserRow r2 = (UserRow) o2;
                try {
                    if (fieldName.equals(SORT_USER_NAME)) {
                        String s1 = r1.getUserName();
                        String s2 = r2.getUserName();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_ID)) {
                        String s1 = r1.getUserEID();
                        String s2 = r2.getUserEID();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_EMAIL)) {
                        String s1 = r1.getUserEmail();
                        String s2 = r2.getUserEmail();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_TYPE)) {
                        String s1 = r1.getUserType();
                        String s2 = r2.getUserType();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_AUTHORITY)) {
                        String s1 = r1.getAuthority();
                        String s2 = r2.getAuthority();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_CREATED_ON)) {
                        String s1 = r1.getCreatedOn();
                        String s2 = r2.getCreatedOn();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_USER_MODIFIED_ON)) {
                        String s1 = r1.getModifiedOn();
                        String s2 = r2.getModifiedOn();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    } else if (fieldName.equals(SORT_INTERNAL_USER_ID)) {
                        String s1 = r1.getUserID();
                        String s2 = r2.getUserID();
                        int res = collator.compare(s1 != null ? s1.toLowerCase() : "",
                                s2 != null ? s2.toLowerCase() : "");
                        if (sortAscending)
                            return res;
                        else
                            return -res;
                    }
                } catch (Exception e) {
                    LOG.warn("Error occurred while sorting by: " + fieldName, e);
                }
                return 0;
            }
        };
    }

    // ######################################################################################
    // Main methods
    // ######################################################################################
    public String getInitValues() {
        if (searchKeyword == null) {
            renderClearSearch = false;
            searchKeyword = msgs.getString("bar_input_search_inst");
        } else
            renderClearSearch = true;

        if (isAllowed() && renderTable && refreshQuery) {
            doSearch();
            refreshQuery = false;
        }

        if (userRows != null) {
            // Sort resulting list
            Collections.sort(userRows, getUserRowComparator(userSortColumn, userSortAscending, collator));
        }

        return "";
    }

    private void doSearch() {
        LOG.debug("Refreshing query...");
        selectedUserType = newUserType;
        selectedAuthority = newAuthority;
        searchKeyword = searchKeyword.trim();
        userRows = new ArrayList<UserRow>();

        if (LOG.isDebugEnabled()) {
            LOG.debug("selectedUserType: " + selectedUserType);
            LOG.debug("selectedAuthority: " + selectedAuthority);
            LOG.debug("searchKeyword: " + searchKeyword);
        }

        // 1. Search internal users (Sakai DB)
        if (selectedAuthority.equalsIgnoreCase(USER_AUTH_ALL)
                || selectedAuthority.equalsIgnoreCase(USER_AUTH_INTERNAL)) {

            if (LOG.isDebugEnabled()) {
                LOG.debug("Searching internal users...");
            }

            try {

                //SAK-20857 if empty search, return all users, otherwise only those that match.
                List<User> users;
                if (StringUtils.isBlank(searchKeyword)) {
                    users = M_uds.getUsers();
                } else {
                    users = M_uds.searchUsers(searchKeyword, 1, Integer.MAX_VALUE);
                }

                for (User u : users) {
                    // filter user type
                    if (userTypeMatches(u.getType())) {
                        userRows.add(new UserRow(u.getId(), u.getEid(), u.getDisplayId(), u.getDisplayName(),
                                u.getEmail(), u.getType(), msgs.getString("user_auth_internal"),
                                (u.getCreatedTime() == null) ? "" : u.getCreatedTime().toStringLocalDate(),
                                (u.getModifiedTime() == null) ? "" : u.getModifiedTime().toStringLocalDate()));
                    }
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Internal search results: " + users.size());
                }
            } catch (Exception e) {
                LOG.warn("Exception occurred while searching internal users: " + e.getMessage());
                e.printStackTrace();
            }
        }

        // 2. Search users on external user providers
        if (selectedAuthority.equalsIgnoreCase(USER_AUTH_ALL)
                || selectedAuthority.equalsIgnoreCase(USER_AUTH_EXTERNAL)) {

            if (LOG.isDebugEnabled()) {
                LOG.debug("Searching external users...");
            }

            try {
                List<User> users = M_uds.searchExternalUsers(searchKeyword, -1, -1);
                for (User u : users) {
                    // filter user type
                    if (userTypeMatches(u.getType())) {
                        userRows.add(new UserRow(u.getId(), u.getEid(), u.getDisplayId(), u.getDisplayName(),
                                u.getEmail(), u.getType(), msgs.getString("user_auth_external"),
                                (u.getCreatedTime() == null) ? "" : u.getCreatedTime().toStringLocalDate(),
                                (u.getModifiedTime() == null) ? "" : u.getModifiedTime().toStringLocalDate()));
                    }
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("External search results: " + users.size());
                }
            } catch (RuntimeException e) {
                LOG.warn("Exception occurred while searching external users: " + e.getMessage(), e);
            }
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("Total results: " + userRows.size());
        }

        // 4. Update pager
        this.totalItems = userRows.size();
        renderPager = false;
        firstItem = 0;

        if (totalItems > 0) {
            renderPager = true;
        }

    }

    private boolean userTypeMatches(String userType) {
        return USER_TYPE_ALL.equals(selectedUserType)
                || (!USER_TYPE_NONE.equals(selectedUserType) && StringUtils.equals(userType, selectedUserType))
                || (USER_TYPE_NONE.equals(selectedUserType) && StringUtils.isEmpty(userType));
    }

    // ######################################################################################
    // ActionListener methods
    // ######################################################################################
    public String processActionSearch() {
        renderTable = true;
        refreshQuery = true;
        return "userlist";
    }

    public String processActionClearSearch() throws SQLException {
        this.selectedUserType = ((SelectItem) getUserTypes().get(0)).getLabel();
        this.selectedAuthority = ((SelectItem) getUserAuthorities().get(0)).getLabel();
        searchKeyword = null;
        renderTable = false;
        refreshQuery = false;
        return "userlist";
    }

    public void processActionSearchChangeListener(ValueChangeEvent event) {
        searchKeyword = (searchKeyword == null) ? "" : searchKeyword.trim();
    }

    // ######################################################################################
    // Generic get/set methods
    // ######################################################################################
    public boolean isAllowed() {
        allowed = authz.isUserAbleToViewUmem(M_tm.getCurrentPlacement().getContext());

        if (!allowed) {
            FacesContext fc = FacesContext.getCurrentInstance();
            message = msgs.getString("unauthorized");
            fc.addMessage("allowed", new FacesMessage(FacesMessage.SEVERITY_FATAL, message, null));
            allowed = false;
        }
        return allowed;
    }

    public boolean isEmptyUserList() {
        return renderTable && ((userRows == null) || (userRows.size() <= 0));
    }

    public List getUserRows() {
        return userRows;
    }

    public int getRowsNumber() {
        if (totalItems <= pageSize) {
            return totalItems;
        }
        return pageSize;
    }

    public int getFirstItem() {
        return firstItem;
    }

    public void setFirstItem(int firstItem) {
        this.firstItem = firstItem;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalItems() {
        return this.totalItems;
    }

    public void setTotalItems(int totalItems) {
        this.totalItems = totalItems;
    }

    public boolean isRenderPager() {
        return renderTable && renderPager;
    }

    public boolean isRenderTable() {
        return renderTable && userRows != null && userRows.size() > 0;
    }

    public boolean isRenderClearSearch() {
        return renderClearSearch;
    }

    public String getSearchKeyword() {
        return searchKeyword;
    }

    public void setSearchKeyword(String searchKeyword) {
        this.searchKeyword = searchKeyword;
    }

    public void setUserSortAscending(boolean sortAscending) {
        this.userSortAscending = sortAscending;
    }

    public boolean getUserSortAscending() {
        return this.userSortAscending;
    }

    public String getUserSortColumn() {
        return this.userSortColumn;
    }

    public void setUserSortColumn(String sortColumn) {
        this.userSortColumn = sortColumn;
    }

    private void addExtraUserType(String newType) throws SQLException {
        boolean found = false;
        if (userTypes == null)
            userTypes = getUserTypes();
        Iterator it = userTypes.iterator();
        while (it.hasNext()) {
            if (((SelectItem) it.next()).getLabel().equals(newType))
                found = true;
        }
        if (!found) {
            userTypes.add(userTypes.size() - 1, new SelectItem(newType));
        }
    }

    public List getUserTypes() throws SQLException {
        if (userTypes == null) {
            Properties config = M_tm.getCurrentPlacement().getConfig();
            Boolean userTypeLimitToSelf = Boolean
                    .parseBoolean(config.getProperty(CFG_USER_TYPE_LIMIT_TO_SELF, "false"));
            String userTypeLimitToListStr = config.getProperty(CFG_USER_TYPE_LIMIT_TO_LIST, "");
            String[] userTypeLimitToList = null;
            userTypes = new ArrayList();

            if (userTypeLimitToSelf) {
                userTypes.add(new SelectItem(M_uds.getCurrentUser().getType()));
            } else if (!"".equals(userTypeLimitToListStr)) {
                userTypeLimitToList = userTypeLimitToListStr.split(",");
                StringBuilder all = new StringBuilder();
                for (int i = 0; i < userTypeLimitToList.length; i++) {
                    userTypes.add(new SelectItem(userTypeLimitToList[i]));
                    all.append("'");
                    all.append(userTypeLimitToList[i]);
                    all.append("'");
                    if (i < userTypeLimitToList.length - 1)
                        all.append(",");
                }
                userTypes.add(0, new SelectItem(all.toString(), msgs.getString("user_type_all")));
            } else {
                userTypes.add(new SelectItem(USER_TYPE_ALL, msgs.getString("user_type_all")));
                Connection c = null;
                Statement st = null;
                ResultSet rs = null;
                try {
                    c = M_sql.borrowConnection();
                    String vendor = M_sql.getVendor();
                    String sql = null;
                    if (vendor.equalsIgnoreCase("oracle")) {
                        sql = "select distinct TYPE from SAKAI_USER where TYPE is not null order by TYPE";
                    } else {
                        sql = "select distinct TYPE from SAKAI_USER where TYPE!='' and TYPE is not null order by TYPE;";
                    }
                    st = c.createStatement();
                    rs = st.executeQuery(sql);
                    while (rs.next()) {
                        String type = rs.getString(1);
                        userTypes.add(new SelectItem(type));
                    }
                } catch (SQLException e) {
                    LOG.error("SQL error occurred while retrieving user types: " + e.getMessage(), e);
                } finally {
                    try {
                        if (rs != null)
                            rs.close();
                    } finally {
                        try {
                            if (st != null)
                                st.close();
                        } finally {
                            if (c != null)
                                M_sql.returnConnection(c);
                        }
                    }
                }
                userTypes.add(new SelectItem(USER_TYPE_NONE, msgs.getString("user_type_none")));
            }
        }

        return userTypes;
    }

    public String getSelectedUserType() throws SQLException {
        if (this.selectedUserType != null)
            return this.selectedUserType;
        else {
            this.selectedUserType = ((SelectItem) getUserTypes().get(0)).getLabel();
            return this.selectedUserType;
        }
    }

    public void setSelectedUserType(String type) {
        this.newUserType = type;
    }

    public List getUserAuthorities() {
        userAuthorities = new ArrayList();
        userAuthorities.add(new SelectItem(USER_AUTH_ALL, msgs.getString("user_auth_all")));
        userAuthorities.add(new SelectItem(USER_AUTH_INTERNAL, msgs.getString("user_auth_internal")));
        userAuthorities.add(new SelectItem(USER_AUTH_EXTERNAL, msgs.getString("user_auth_external")));
        return userAuthorities;
    }

    public String getSelectedAuthority() {
        if (this.selectedAuthority != null)
            return this.selectedAuthority;
        else {
            this.selectedAuthority = ((SelectItem) getUserAuthorities().get(0)).getLabel();
            return this.selectedAuthority;
        }
    }

    public void setSelectedAuthority(String type) {
        this.newAuthority = type;
    }

    public String getNoName() {
        return NO_NAME_USER;
    }

    // ######################################################################################
    // CSV export
    // ######################################################################################
    public void exportAsCsv(ActionEvent event) {
        Export.writeAsCsv(buildDataTable(userRows), "UserListing");
    }

    /**
     * Export the data in this user list to the response stream as an Excel workbook
     * @param event
     */
    public void exportAsXls(ActionEvent event) {
        Export.writeAsXls(buildDataTable(userRows), "UserListing");
    }

    /**
     * Build a generic tabular representation of the user membership data export.
     * 
     * @param userRows The content of the table
     * @return
     *    A table of data suitable to be exported
     */
    private List<List<Object>> buildDataTable(List<UserRow> userRows) {
        List<List<Object>> table = new LinkedList<List<Object>>();

        //add header row
        List<Object> header = new ArrayList<Object>();
        header.add(msgs.getString("user_id"));
        header.add(msgs.getString("internal_user_id"));
        header.add(msgs.getString("user_name"));
        header.add(msgs.getString("user_email"));
        header.add(msgs.getString("user_type"));
        header.add(msgs.getString("user_authority"));
        header.add(msgs.getString("user_created_on"));
        header.add(msgs.getString("user_modified_on"));
        table.add(header);

        //add data rows
        for (UserRow userRow : userRows) {
            List<Object> currentRow = new ArrayList<Object>();
            currentRow.add(userRow.getUserEID());
            currentRow.add(userRow.getUserID());
            currentRow.add(userRow.getUserName());
            currentRow.add(userRow.getUserEmail());
            currentRow.add(userRow.getUserType());
            currentRow.add(userRow.getAuthority());
            currentRow.add(userRow.getCreatedOn());
            currentRow.add(userRow.getModifiedOn());
            table.add(currentRow);
        }

        return table;
    }
}