001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/contrib/ufp/usermembership/trunk/tool/src/java/org/sakaiproject/umem/tool/ui/UserListBean.java $
003: * $Id: UserListBean.java 4381 2007-03-21 11:25:54Z nuno@ufp.pt $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006, 2007 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.umem.tool.ui;
021:
022: import java.io.Serializable;
023: import java.sql.Connection;
024: import java.sql.ResultSet;
025: import java.sql.SQLException;
026: import java.sql.Statement;
027: import java.text.Collator;
028: import java.util.ArrayList;
029: import java.util.Collections;
030: import java.util.Comparator;
031: import java.util.Iterator;
032: import java.util.List;
033:
034: import javax.faces.application.FacesMessage;
035: import javax.faces.context.FacesContext;
036: import javax.faces.event.ActionEvent;
037: import javax.faces.event.ValueChangeEvent;
038: import javax.faces.model.SelectItem;
039:
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042: import org.sakaiproject.component.cover.ComponentManager;
043: import org.sakaiproject.db.api.SqlService;
044: import org.sakaiproject.tool.api.ToolManager;
045: import org.sakaiproject.umem.api.Authz;
046: import org.sakaiproject.user.api.User;
047: import org.sakaiproject.user.api.UserDirectoryService;
048: import org.sakaiproject.util.ResourceLoader;
049:
050: /**
051: * @author <a href="mailto:nuno@ufp.pt">Nuno Fernandes</a>
052: */
053: public class UserListBean {
054: private static final long serialVersionUID = 1L;
055: private static final String USER_TYPE_ALL = "All";
056: private static final String USER_TYPE_NONE = "(no type)";
057: private static final String USER_AUTH_ALL = "All";
058: private static final String USER_AUTH_INTERNAL = "Internal";
059: private static final String USER_AUTH_EXTERNAL = "External";
060: private static final String SORT_USER_NAME = "name";
061: private static final String SORT_USER_ID = "id";
062: private static final String SORT_USER_EMAIL = "email";
063: private static final String SORT_USER_TYPE = "type";
064: private static final String SORT_USER_AUTHORITY = "authority";
065: private static final String NO_NAME_USER = "";
066:
067: /** Our log (commons). */
068: private static Log LOG = LogFactory.getLog(UserListBean.class);
069:
070: /** Resource bundle */
071: private transient ResourceLoader msgs = new ResourceLoader(
072: "org.sakaiproject.umem.tool.bundle.Messages");
073:
074: /** Controller fields */
075: private List userRows;
076:
077: /** Getter vars */
078: private boolean allowed = false;
079: private boolean refreshQuery = false;
080: private boolean renderTable = false;
081: private boolean renderPager = true;
082: private boolean renderClearSearch = false;
083: private int totalItems = -1;
084: private int firstItem = 0;
085: private int pageSize = 20;
086: private String searchKeyword = null;
087: private boolean userSortAscending = true;
088: private String userSortColumn = SORT_USER_NAME;
089: private List userTypes = null;
090: private List userAuthorities = null;
091: private String selectedUserType = null;
092: private String selectedAuthority = USER_AUTH_ALL;
093: private String newUserType = null;
094: private String newAuthority = USER_AUTH_ALL;
095:
096: /** Private vars */
097: private transient Collator collator = Collator.getInstance(); // use
098: private String message = "";
099: // system
100: /** Sakai services vars */
101: private transient UserDirectoryService M_uds = (UserDirectoryService) ComponentManager
102: .get(UserDirectoryService.class.getName());
103: private transient ToolManager M_tm = (ToolManager) ComponentManager
104: .get(ToolManager.class.getName());
105: private transient SqlService M_sql = (SqlService) ComponentManager
106: .get(SqlService.class.getName());
107: private transient Authz authz = (Authz) ComponentManager
108: .get(Authz.class.getName());
109:
110: // ######################################################################################
111: // UserRow, UserSitesRow CLASS
112: // ######################################################################################
113: public class UserRow implements Serializable {
114: private static final long serialVersionUID = 1L;
115: private String userID;
116: private String userEID;
117: private String userName;
118: private String userEmail;
119: private String userType;
120: private String authority;
121:
122: public UserRow() {
123: }
124:
125: public UserRow(String userID, String userEID, String userName,
126: String userEmail, String userType, String authority) {
127: this .userID = userID;
128: this .userEID = userEID;
129: this .userName = userName;
130: this .userEmail = userEmail;
131: this .userType = userType;
132: this .authority = authority;
133: }
134:
135: public String getUserEmail() {
136: return this .userEmail;
137: }
138:
139: public String getUserID() {
140: return this .userID;
141: }
142:
143: public String getUserEID() {
144: return this .userEID;
145: }
146:
147: public String getUserName() {
148: return this .userName;
149: }
150:
151: public String getUserType() {
152: return (this .userType == null) ? "" : this .userType;
153: }
154:
155: public String getAuthority() {
156: return this .authority;
157: }
158:
159: public void setUserRow(UserRow row, String authority) {
160: this .userID = row.getUserID();
161: this .userEID = row.getUserEID();
162: this .userName = row.getUserName();
163: this .userEmail = row.getUserEmail();
164: this .userType = row.getUserType();
165: this .authority = authority;
166: }
167:
168: public UserRow getUserRow() {
169: return this ;
170: }
171: }
172:
173: public static final Comparator getUserRowComparator(
174: final String fieldName, final boolean sortAscending,
175: final Collator collator) {
176: return new Comparator() {
177:
178: public int compare(Object o1, Object o2) {
179: if (o1 instanceof UserRow && o2 instanceof UserRow) {
180: UserRow r1 = (UserRow) o1;
181: UserRow r2 = (UserRow) o2;
182: try {
183: if (fieldName.equals(SORT_USER_NAME)) {
184: String s1 = r1.getUserName();
185: String s2 = r2.getUserName();
186: int res = collator.compare(s1 != null ? s1
187: .toLowerCase() : "",
188: s2 != null ? s2.toLowerCase() : "");
189: if (sortAscending)
190: return res;
191: else
192: return -res;
193: } else if (fieldName.equals(SORT_USER_ID)) {
194: String s1 = r1.getUserEID().toLowerCase();
195: String s2 = r2.getUserEID();
196: int res = collator.compare(s1 != null ? s1
197: .toLowerCase() : "",
198: s2 != null ? s2.toLowerCase() : "");
199: if (sortAscending)
200: return res;
201: else
202: return -res;
203: } else if (fieldName.equals(SORT_USER_EMAIL)) {
204: String s1 = r1.getUserEmail();
205: String s2 = r2.getUserEmail();
206: int res = collator.compare(s1 != null ? s1
207: .toLowerCase() : "",
208: s2 != null ? s2.toLowerCase() : "");
209: if (sortAscending)
210: return res;
211: else
212: return -res;
213: } else if (fieldName.equals(SORT_USER_TYPE)) {
214: String s1 = r1.getUserType();
215: String s2 = r2.getUserType();
216: int res = collator.compare(s1 != null ? s1
217: .toLowerCase() : "",
218: s2 != null ? s2.toLowerCase() : "");
219: if (sortAscending)
220: return res;
221: else
222: return -res;
223: } else if (fieldName
224: .equals(SORT_USER_AUTHORITY)) {
225: String s1 = r1.getAuthority();
226: String s2 = r2.getAuthority();
227: int res = collator.compare(s1 != null ? s1
228: .toLowerCase() : "",
229: s2 != null ? s2.toLowerCase() : "");
230: if (sortAscending)
231: return res;
232: else
233: return -res;
234: }
235: } catch (Exception e) {
236: LOG.warn("Error occurred while sorting by: "
237: + fieldName, e);
238: }
239: }
240: return 0;
241: }
242: };
243: }
244:
245: // ######################################################################################
246: // Main methods
247: // ######################################################################################
248: public String getInitValues() {
249: if (searchKeyword == null) {
250: renderClearSearch = false;
251: searchKeyword = msgs.getString("bar_input_search_inst");
252: } else
253: renderClearSearch = true;
254:
255: if (isAllowed() && renderTable && refreshQuery) {
256: doSearch();
257: refreshQuery = false;
258: }
259:
260: if (userRows != null) {
261: // Sort resulting list
262: Collections.sort(userRows, getUserRowComparator(
263: userSortColumn, userSortAscending, collator));
264: }
265:
266: return "";
267: }
268:
269: private void doSearch() {
270: /**
271: * 1. Query internal users from SAKAI_USER (filter by type and search)
272: * 2. Query external users from SAKAI_REALM_RL_GR
273: * 3. Get info and filter external users from UserDirectoryProvider
274: * 4. Sort resulting list
275: * 5. Update pager
276: */
277: LOG.debug("Refreshing query...");
278: selectedUserType = newUserType;
279: selectedAuthority = newAuthority;
280: searchKeyword = searchKeyword.trim();
281: boolean filtering = (selectedUserType != null
282: && userTypes != null && !selectedUserType
283: .equals(((SelectItem) getUserTypes().get(0)).getLabel()));
284: boolean searching = (searchKeyword != null
285: && !searchKeyword.equals("") && !searchKeyword
286: .equals(msgs.getString("bar_input_search_inst")));
287: userRows = new ArrayList();
288:
289: try {
290: if (selectedAuthority.equals(USER_AUTH_ALL)
291: || selectedAuthority.equals(USER_AUTH_INTERNAL)) {
292: // 1. Query internal users from SAKAI_USER
293: String sql = "SELECT SAKAI_USER.USER_ID,EID,EMAIL,FIRST_NAME,LAST_NAME,TYPE FROM SAKAI_USER "
294: + "LEFT JOIN SAKAI_USER_ID_MAP "
295: + "ON SAKAI_USER.USER_ID=SAKAI_USER_ID_MAP.USER_ID";
296: if (searching || filtering) {
297: sql += " WHERE ";
298: if (searching)
299: sql += " (EID LIKE '%" + searchKeyword
300: + "%' OR SAKAI_USER.USER_ID LIKE '%"
301: + searchKeyword
302: + "%' OR FIRST_NAME LIKE '%"
303: + searchKeyword
304: + "%' OR LAST_NAME LIKE '%"
305: + searchKeyword + "%' OR EMAIL LIKE '%"
306: + searchKeyword + "%') ";
307: if (filtering && searching)
308: sql += " AND ";
309: if (filtering) {
310: if (selectedUserType.equals(USER_TYPE_NONE))
311: sql += " (TYPE='' or TYPE IS NULL) ";
312: else
313: sql += " (TYPE='" + selectedUserType
314: + "') ";
315: }
316: }
317:
318: try {
319: Connection c = M_sql.borrowConnection();
320: Statement st = c.createStatement();
321: ResultSet rs = st.executeQuery(sql);
322: while (rs.next()) {
323: String id = rs.getString("USER_ID");
324: String eid = rs.getString("EID");
325: eid = eid == null ? id : eid;
326: String e = rs.getString("EMAIL");
327: String f = rs.getString("FIRST_NAME");
328: String l = rs.getString("LAST_NAME");
329: String t = rs.getString("TYPE");
330: userRows.add(new UserRow(id, eid, getFullName(
331: f, l), e, t, USER_AUTH_INTERNAL));
332: }
333: rs.close();
334: st.close();
335: M_sql.returnConnection(c);
336: } catch (SQLException e) {
337: LOG
338: .error("SQL error occurred while retrieving list of internal users: "
339: + e.getMessage());
340: }
341: }
342: } catch (Exception e) {
343: LOG
344: .warn("Exception occurred while querying internal users: "
345: + e.getMessage());
346: e.printStackTrace();
347: }
348:
349: // 2. Query external users from SAKAI_REALM_RL_GR
350: try {
351: if (selectedAuthority.equals(USER_AUTH_ALL)
352: || selectedAuthority.equals(USER_AUTH_EXTERNAL)) {
353: List eUsers = new ArrayList();
354: try {
355: Connection c = M_sql.borrowConnection();
356: String sqlE = "SELECT DISTINCT USER_ID FROM SAKAI_REALM_RL_GR WHERE USER_ID NOT IN (SELECT USER_ID FROM SAKAI_USER)";
357: Statement st = c.createStatement();
358: ResultSet rs = st.executeQuery(sqlE);
359: while (rs.next()) {
360: String id = rs.getString("USER_ID");
361: eUsers.add(id);
362: }
363: rs.close();
364: st.close();
365: M_sql.returnConnection(c);
366: } catch (SQLException e) {
367: LOG
368: .error("SQL error occurred while retrieving list of external users: "
369: + e.getMessage());
370: }
371:
372: // 3. Get info and filter external users from UserDirectoryProvider
373: String id;
374: String eid;
375: String e;
376: String n;
377: String t;
378: String regexp = null;
379: List pUsers = M_uds.getUsers(eUsers);
380: Iterator it = pUsers.iterator();
381: if (searching)
382: regexp = ".*" + searchKeyword.toLowerCase() + ".*";
383: while (it.hasNext()) {
384: User u = (User) it.next();
385: id = u.getId();
386: eid = u.getEid();
387: e = u.getEmail();
388: n = getFullName(u.getFirstName(), u.getLastName());
389: t = u.getType();
390: t = (t == null) ? "" : t;
391: if (!t.equals(""))
392: addExtraUserType(t);
393:
394: boolean add = false;
395: if (filtering && !searching) {
396: if ((!selectedUserType.equals(USER_TYPE_NONE) && t
397: .equals(selectedUserType))
398: || (selectedUserType
399: .equals(USER_TYPE_NONE) && t
400: .equals("")))
401: add = true;
402: } else if (!filtering && searching) {
403: if (n.toLowerCase().matches(regexp)
404: || e.toLowerCase().matches(regexp)
405: || id.toLowerCase().matches(regexp))
406: add = true;
407: } else if (filtering && searching) {
408: if ((!selectedUserType.equals(USER_TYPE_NONE) && t
409: .equals(selectedUserType))
410: || (selectedUserType
411: .equals(USER_TYPE_NONE) && t
412: .equals(""))) {
413: if (n.toLowerCase().matches(regexp)
414: || e.toLowerCase().matches(regexp)
415: || id.toLowerCase().matches(regexp))
416: add = true;
417: }
418: } else {
419: add = true;
420: }
421: if (add)
422: userRows.add(new UserRow(id, eid, n, e, t,
423: USER_AUTH_EXTERNAL));
424: }
425: }
426: } catch (Exception e) {
427: LOG
428: .warn("Exception occurred while querying external users: "
429: + e.getMessage());
430: e.printStackTrace();
431: }
432:
433: // 4. Update pager
434: this .totalItems = userRows.size();
435: if (totalItems > 0)
436: renderPager = true;
437: else
438: renderPager = false;
439: // if(totalItems <= pageSize){
440: // renderPager = false;
441: // }
442: // else renderPager = true;
443: firstItem = 0;
444: }
445:
446: private String getFullName(String fName, String lName) {
447: fName = fName == null ? "" : fName;
448: lName = lName == null ? "" : lName;
449: String firstName = fName.equals("") ? "" : fName;
450: return lName.equals("") ? firstName : (fName.equals("") ? lName
451: : lName + ", " + fName);
452: }
453:
454: // ######################################################################################
455: // ActionListener methods
456: // ######################################################################################
457: public String processActionSearch() {
458: renderTable = true;
459: refreshQuery = true;
460: return "userlist";
461: }
462:
463: public String processActionClearSearch() {
464: this .selectedUserType = ((SelectItem) getUserTypes().get(0))
465: .getLabel();
466: this .selectedAuthority = ((SelectItem) getUserAuthorities()
467: .get(0)).getLabel();
468: searchKeyword = null;
469: renderTable = false;
470: refreshQuery = false;
471: return "userlist";
472: }
473:
474: public void processActionSearchChangeListener(ValueChangeEvent event) {
475: String newValue = (String) event.getNewValue();
476: newValue = (newValue == null) ? "" : newValue;
477: searchKeyword = (searchKeyword == null) ? "" : searchKeyword
478: .trim();
479: }
480:
481: // ######################################################################################
482: // Generic get/set methods
483: // ######################################################################################
484: public boolean isAllowed() {
485: allowed = authz.isUserAbleToViewUmem(M_tm.getCurrentPlacement()
486: .getContext());
487:
488: if (!allowed) {
489: FacesContext fc = FacesContext.getCurrentInstance();
490: message = msgs.getString("unauthorized");
491: fc.addMessage("allowed", new FacesMessage(
492: FacesMessage.SEVERITY_FATAL, message, null));
493: allowed = false;
494: }
495: return allowed;
496: }
497:
498: public boolean isEmptyUserList() {
499: return renderTable
500: && ((userRows == null) || (userRows.size() <= 0));
501: }
502:
503: public List getUserRows() {
504: return userRows;
505: }
506:
507: public int getRowsNumber() {
508: if (totalItems <= pageSize) {
509: return totalItems;
510: }
511: return pageSize;
512: }
513:
514: public int getFirstItem() {
515: return firstItem;
516: }
517:
518: public void setFirstItem(int firstItem) {
519: this .firstItem = firstItem;
520: }
521:
522: public int getPageSize() {
523: // if(totalItems <= pageSize){
524: // return totalItems;
525: // }
526: return pageSize;
527: }
528:
529: public void setPageSize(int pageSize) {
530: this .pageSize = pageSize;
531: }
532:
533: public int getTotalItems() {
534: return this .totalItems;
535: }
536:
537: public void setTotalItems(int totalItems) {
538: this .totalItems = totalItems;
539: }
540:
541: public boolean isRenderPager() {
542: return renderTable && renderPager;
543: }
544:
545: public boolean isRenderTable() {
546: return renderTable && userRows != null && userRows.size() > 0;
547: }
548:
549: public boolean isRenderClearSearch() {
550: return renderClearSearch;
551: }
552:
553: public String getSearchKeyword() {
554: return searchKeyword;
555: }
556:
557: public void setSearchKeyword(String searchKeyword) {
558: this .searchKeyword = searchKeyword;
559: }
560:
561: public void setUserSortAscending(boolean sortAscending) {
562: this .userSortAscending = sortAscending;
563: }
564:
565: public boolean getUserSortAscending() {
566: return this .userSortAscending;
567: }
568:
569: public String getUserSortColumn() {
570: return this .userSortColumn;
571: }
572:
573: public void setUserSortColumn(String sortColumn) {
574: this .userSortColumn = sortColumn;
575: }
576:
577: private void addExtraUserType(String newType) {
578: boolean found = false;
579: Iterator it = userTypes.iterator();
580: while (it.hasNext()) {
581: if (((SelectItem) it.next()).getLabel().equals(newType))
582: found = true;
583: }
584: if (!found) {
585: if (userTypes == null)
586: getUserTypes();
587: userTypes
588: .add(userTypes.size() - 1, new SelectItem(newType));
589: }
590: }
591:
592: public List getUserTypes() {
593: if (userTypes == null) {
594: userTypes = new ArrayList();
595: userTypes.add(new SelectItem(USER_TYPE_ALL));
596: try {
597: Connection c = M_sql.borrowConnection();
598: String vendor = M_sql.getVendor();
599: String sql = null;
600: if (vendor.equalsIgnoreCase("oracle")) {
601: sql = "select distinct TYPE from SAKAI_USER where TYPE is not null";
602: } else {
603: sql = "select distinct TYPE from SAKAI_USER where TYPE!='' and TYPE is not null;";
604: }
605: Statement st = c.createStatement();
606: ResultSet rs = st.executeQuery(sql);
607: while (rs.next()) {
608: String type = rs.getString(1);
609: userTypes.add(new SelectItem(type));
610: }
611: rs.close();
612: st.close();
613: M_sql.returnConnection(c);
614: } catch (SQLException e) {
615: LOG.error(
616: "SQL error occurred while retrieving user types: "
617: + e.getMessage(), e);
618: }
619: userTypes.add(new SelectItem(USER_TYPE_NONE));
620: }
621: return userTypes;
622: }
623:
624: public String getSelectedUserType() {
625: if (this .selectedUserType != null)
626: return this .selectedUserType;
627: else {
628: this .selectedUserType = ((SelectItem) getUserTypes().get(0))
629: .getLabel();
630: return this .selectedUserType;
631: }
632: }
633:
634: public void setSelectedUserType(String type) {
635: //this.selectedUserType = type;
636: this .newUserType = type;
637: }
638:
639: public List getUserAuthorities() {
640: userAuthorities = new ArrayList();
641: userAuthorities.add(new SelectItem(USER_AUTH_ALL));
642: userAuthorities.add(new SelectItem(USER_AUTH_INTERNAL));
643: userAuthorities.add(new SelectItem(USER_AUTH_EXTERNAL));
644: return userAuthorities;
645: }
646:
647: public String getSelectedAuthority() {
648: if (this .selectedAuthority != null)
649: return this .selectedAuthority;
650: else {
651: this .selectedAuthority = ((SelectItem) getUserAuthorities()
652: .get(0)).getLabel();
653: return this .selectedAuthority;
654: }
655: }
656:
657: public void setSelectedAuthority(String type) {
658: //this.selectedAuthority = type;
659: this .newAuthority = type;
660: }
661:
662: public String getNoName() {
663: return NO_NAME_USER;
664: }
665:
666: // ######################################################################################
667: // CSV export
668: // ######################################################################################
669: public void exportAsCsv(ActionEvent event) {
670: String prefix = new String("UserListing");
671: Export.writeAsCsv(getAsCsv(userRows), prefix);
672: FacesContext faces = FacesContext.getCurrentInstance();
673: }
674:
675: private String getAsCsv(List list) {
676: StringBuffer sb = new StringBuffer();
677:
678: // Add the headers
679: Export.appendQuoted(sb, msgs.getString("user_id"));
680: sb.append(",");
681: Export.appendQuoted(sb, msgs.getString("user_name"));
682: sb.append(",");
683: Export.appendQuoted(sb, msgs.getString("user_email"));
684: sb.append(",");
685: Export.appendQuoted(sb, msgs.getString("user_type"));
686: sb.append(",");
687: Export.appendQuoted(sb, msgs.getString("user_authority"));
688: sb.append("\n");
689:
690: // Add the data
691: Iterator i = list.iterator();
692: while (i.hasNext()) {
693: UserRow usr = (UserRow) i.next();
694: // user name
695: Export.appendQuoted(sb, usr.getUserEID());
696: sb.append(",");
697: Export.appendQuoted(sb, usr.getUserName());
698: sb.append(",");
699: Export.appendQuoted(sb, usr.getUserEmail());
700: sb.append(",");
701: Export.appendQuoted(sb, usr.getUserType());
702: sb.append(",");
703: Export.appendQuoted(sb, usr.getAuthority());
704: sb.append("\n");
705: }
706: return sb.toString();
707: }
708: }
|