001: /**
002: * Copyright (C) 2001 Yasna.com. All rights reserved.
003: *
004: * ===================================================================
005: * The Apache Software License, Version 1.1
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by
022: * Yasna.com (http://www.yasna.com)."
023: * Alternately, this acknowledgment may appear in the software itself,
024: * if and wherever such third-party acknowledgments normally appear.
025: *
026: * 4. The names "Yazd" and "Yasna.com" must not be used to
027: * endorse or promote products derived from this software without
028: * prior written permission. For written permission, please
029: * contact yazd@yasna.com.
030: *
031: * 5. Products derived from this software may not be called "Yazd",
032: * nor may "Yazd" appear in their name, without prior written
033: * permission of Yasna.com.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL YASNA.COM OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of Yasna.com. For more information
051: * on Yasna.com, please see <http://www.yasna.com>.
052: */package com.Yasna.forum.database;
053:
054: import com.Yasna.forum.*;
055: import com.Yasna.util.Cacheable;
056: import com.Yasna.util.CacheSizes;
057:
058: import java.util.Iterator;
059: import java.util.ArrayList;
060: import java.sql.*;
061:
062: /**
063: * Database implementation of the Group interface.
064: *
065: * @see Group
066: */
067: public class DbGroup implements Group, Cacheable {
068:
069: /** DATABASE QUERIES **/
070: private static final String ADD_ADMIN = "INSERT INTO yazdGroupUser(groupID,userID,administrator) VALUES(?,?,1)";
071: private static final String REMOVE_ADMIN = "DELETE FROM yazdGroupUser WHERE groupID=? AND userID=? AND administrator=1";
072: private static final String ADD_USER = "INSERT INTO yazdGroupUser(groupID,userID,administrator) VALUES(?,?,0)";
073: private static final String REMOVE_USER = "DELETE FROM yazdGroupUser WHERE groupID=? AND userID=? AND administrator=0";
074: private static final String ADMIN_TEST = "SELECT userID FROM yazdGroupUser WHERE groupID=? AND userID=? AND "
075: + "administrator=1";
076: private static final String MEMBER_TEST = "SELECT userID FROM yazdGroupUser WHERE groupID=? AND userID=?";
077: private static final String ADMIN_COUNT = "SELECT count(*) FROM yazdGroupUser WHERE groupID=? "
078: + "AND administrator=1";
079: private static final String MEMBER_COUNT = "SELECT DISTINCT count(userID) FROM yazdGroupUser "
080: + "WHERE groupID=?";
081: private static final String LOAD_ADMINS = "SELECT userID FROM yazdGroupUser WHERE administrator=1 AND groupID=?";
082: private static final String LOAD_USERS = "SELECT userID FROM yazdGroupUser WHERE groupID=?";
083: private static final String LOAD_GROUP_BY_ID = "SELECT * FROM yazdGroup WHERE groupID=?";
084: private static final String LOAD_GROUP_BY_NAME = "SELECT * FROM yazdGroup WHERE name=?";
085: private static final String INSERT_GROUP = "INSERT INTO yazdGroup(name,description,groupID,automember) VALUES(?,?,?,0)";
086: private static final String SAVE_GROUP = "UPDATE yazdGroup SET name=?, description=?,automember=? WHERE groupID=?";
087:
088: private int id;
089: private String name = null;
090: private String description = "";
091: private boolean automembership = false;
092:
093: private ProfileManager profileManager;
094: private DbForumFactory factory;
095:
096: /**
097: * Creates a new group.
098: *
099: * @param the name of the group.
100: * @param profileManager a ProfileManager that can be used to perform user
101: * and group operations.
102: */
103: protected DbGroup(String name, DbForumFactory factory) {
104: this .name = name;
105: this .factory = factory;
106: this .profileManager = factory.getProfileManager();
107: this .id = DbSequenceManager.nextID("Group");
108: insertIntoDb();
109: }
110:
111: /**
112: * Loads a group from the database based on its id.
113: *
114: * @param id the id of the group to load.
115: * @param profileManager a ProfileManager that can be used to perform user
116: * and group operations.
117: */
118: protected DbGroup(int id, DbForumFactory factory)
119: throws GroupNotFoundException {
120: this .id = id;
121: this .factory = factory;
122: this .profileManager = factory.getProfileManager();
123: loadFromDb();
124: }
125:
126: /**
127: * Loads a group from the database based on its name. The implementation
128: * of this method is rather hackish since it includes a fake parameter just
129: * so that it can have a different method signature than the first
130: * constructor. Even so, this methodology makes this class behave more like
131: * our other classes, so we're gleefully leaving it this way. :)
132: *
133: * @param name the name of the group to load.
134: * @param fake a fake paramater that can always be null.
135: * @param profileManager a ProfileManager that can be used to perform user
136: * and group operations.
137: */
138: protected DbGroup(String name, Object fake, DbForumFactory factory)
139: throws GroupNotFoundException {
140: this .name = name;
141: this .factory = factory;
142: this .profileManager = factory.getProfileManager();
143: loadFromDb();
144: }
145:
146: //FROM THE USER INTERFACE//
147:
148: public int getID() {
149: return id;
150: }
151:
152: public String getName() {
153: return name;
154: }
155:
156: public boolean getAutoGroupMembership() {
157: return automembership;
158: }
159:
160: public void setAutoGroupMembership(boolean param)
161: throws UnauthorizedException {
162: this .automembership = param;
163: saveToDb();
164: }
165:
166: public void setName(String name) throws UnauthorizedException {
167: this .name = name;
168: saveToDb();
169: }
170:
171: public String getDescription() {
172: return description;
173: }
174:
175: public void setDescription(String description)
176: throws UnauthorizedException {
177: this .description = description;
178: saveToDb();
179: }
180:
181: public void addAdministrator(User user)
182: throws UnauthorizedException {
183: Connection con = null;
184: PreparedStatement pstmt = null;
185: try {
186: con = DbConnectionManager.getConnection();
187: pstmt = con.prepareStatement(ADD_ADMIN);
188: pstmt.setInt(1, id);
189: pstmt.setInt(2, user.getID());
190: pstmt.execute();
191: } catch (SQLException sqle) {
192: sqle.printStackTrace();
193: } finally {
194: try {
195: pstmt.close();
196: } catch (Exception e) {
197: e.printStackTrace();
198: }
199: try {
200: con.close();
201: } catch (Exception e) {
202: e.printStackTrace();
203: }
204: }
205:
206: //Now, remove the user from the USER_PERM_CACHE since being in the
207: //group could affect their permissions.
208: DbCacheManager cacheManager = factory.getCacheManager();
209: cacheManager.removeUserPerm(new Integer(user.getID()));
210: }
211:
212: public void removeAdministrator(User user)
213: throws UnauthorizedException {
214: Connection con = null;
215: PreparedStatement pstmt = null;
216: try {
217: con = DbConnectionManager.getConnection();
218: pstmt = con.prepareStatement(REMOVE_ADMIN);
219: pstmt.setInt(1, id);
220: pstmt.setInt(2, user.getID());
221: pstmt.execute();
222: } catch (SQLException sqle) {
223: sqle.printStackTrace();
224: } finally {
225: try {
226: pstmt.close();
227: } catch (Exception e) {
228: e.printStackTrace();
229: }
230: try {
231: con.close();
232: } catch (Exception e) {
233: e.printStackTrace();
234: }
235: }
236:
237: //Now, remove the user from the USER_PERM_CACHE since being in the
238: //group could affect their permissions.
239: DbCacheManager cacheManager = factory.getCacheManager();
240: cacheManager.removeUserPerm(new Integer(user.getID()));
241: }
242:
243: public void addMember(User user) throws UnauthorizedException {
244: Connection con = null;
245: PreparedStatement pstmt = null;
246: try {
247: con = DbConnectionManager.getConnection();
248: pstmt = con.prepareStatement(ADD_USER);
249: pstmt.setInt(1, id);
250: pstmt.setInt(2, user.getID());
251: pstmt.execute();
252: } catch (SQLException sqle) {
253: sqle.printStackTrace();
254: } finally {
255: try {
256: pstmt.close();
257: } catch (Exception e) {
258: e.printStackTrace();
259: }
260: try {
261: con.close();
262: } catch (Exception e) {
263: e.printStackTrace();
264: }
265: }
266:
267: //Now, remove the user from the USER_PERM_CACHE since being in the
268: //group could affect their permissions.
269: DbCacheManager cacheManager = factory.getCacheManager();
270: cacheManager.removeUserPerm(new Integer(user.getID()));
271: }
272:
273: public void removeMember(User user) throws UnauthorizedException {
274: Connection con = null;
275: PreparedStatement pstmt = null;
276: try {
277: con = DbConnectionManager.getConnection();
278: pstmt = con.prepareStatement(REMOVE_USER);
279: pstmt.setInt(1, id);
280: pstmt.setInt(2, user.getID());
281: pstmt.execute();
282: } catch (SQLException sqle) {
283: sqle.printStackTrace();
284: } finally {
285: try {
286: pstmt.close();
287: } catch (Exception e) {
288: e.printStackTrace();
289: }
290: try {
291: con.close();
292: } catch (Exception e) {
293: e.printStackTrace();
294: }
295: }
296:
297: //Now, remove the user from the USER_PERM_CACHE since being in the
298: //group could affect their permissions.
299: DbCacheManager cacheManager = factory.getCacheManager();
300: cacheManager.removeUserPerm(new Integer(user.getID()));
301: }
302:
303: public boolean isAdministrator(User user) {
304: boolean answer = false;
305: Connection con = null;
306: PreparedStatement pstmt = null;
307: try {
308: con = DbConnectionManager.getConnection();
309: pstmt = con.prepareStatement(ADMIN_TEST);
310: pstmt.setInt(1, id);
311: pstmt.setInt(2, user.getID());
312: ResultSet rs = pstmt.executeQuery();
313: if (rs.next()) {
314: answer = true;
315: }
316: } catch (SQLException sqle) {
317: sqle.printStackTrace();
318: } finally {
319: try {
320: pstmt.close();
321: } catch (Exception e) {
322: e.printStackTrace();
323: }
324: try {
325: con.close();
326: } catch (Exception e) {
327: e.printStackTrace();
328: }
329: }
330: return answer;
331: }
332:
333: public boolean isMember(User user) {
334: boolean answer = false;
335: Connection con = null;
336: PreparedStatement pstmt = null;
337: try {
338: con = DbConnectionManager.getConnection();
339: pstmt = con.prepareStatement(MEMBER_TEST);
340: pstmt.setInt(1, id);
341: pstmt.setInt(2, user.getID());
342: ResultSet rs = pstmt.executeQuery();
343: if (rs.next()) {
344: answer = true;
345: }
346: } catch (SQLException sqle) {
347: sqle.printStackTrace();
348: } finally {
349: try {
350: pstmt.close();
351: } catch (Exception e) {
352: e.printStackTrace();
353: }
354: try {
355: con.close();
356: } catch (Exception e) {
357: e.printStackTrace();
358: }
359: }
360: return answer;
361: }
362:
363: public int getAdministratorCount() {
364: int count = 0;
365: boolean answer = false;
366: Connection con = null;
367: PreparedStatement pstmt = null;
368: try {
369: con = DbConnectionManager.getConnection();
370: pstmt = con.prepareStatement(ADMIN_COUNT);
371: pstmt.setInt(1, id);
372: ResultSet rs = pstmt.executeQuery();
373: if (rs.next()) {
374: count = rs.getInt(1);
375: }
376: } catch (SQLException sqle) {
377: sqle.printStackTrace();
378: } finally {
379: try {
380: pstmt.close();
381: } catch (Exception e) {
382: e.printStackTrace();
383: }
384: try {
385: con.close();
386: } catch (Exception e) {
387: e.printStackTrace();
388: }
389: }
390: return count;
391: }
392:
393: public int getMemberCount() {
394: int count = 0;
395: boolean answer = false;
396: Connection con = null;
397: PreparedStatement pstmt = null;
398: try {
399: con = DbConnectionManager.getConnection();
400: pstmt = con.prepareStatement(MEMBER_COUNT);
401: pstmt.setInt(1, id);
402: ResultSet rs = pstmt.executeQuery();
403: if (rs.next()) {
404: count = rs.getInt(1);
405: }
406: } catch (SQLException sqle) {
407: sqle.printStackTrace();
408: } finally {
409: try {
410: pstmt.close();
411: } catch (Exception e) {
412: e.printStackTrace();
413: }
414: try {
415: con.close();
416: } catch (Exception e) {
417: e.printStackTrace();
418: }
419: }
420: return count;
421: }
422:
423: public Iterator members() {
424: ArrayList admins = new ArrayList();
425: //Load list of group admins from db.
426: Connection con = null;
427: PreparedStatement pstmt = null;
428:
429: try {
430: con = DbConnectionManager.getConnection();
431: pstmt = con.prepareStatement(LOAD_USERS);
432: pstmt.setInt(1, id);
433: ResultSet rs = pstmt.executeQuery();
434: User user = null;
435: while (rs.next()) {
436: try {
437: user = profileManager.getUser(rs.getInt("userID"));
438: } catch (UserNotFoundException unfe) {
439: unfe.printStackTrace(System.out);
440: }
441: admins.add(user);
442: }
443: } catch (SQLException sqle) {
444: System.err.println("SQLException in DbGroup.java:"
445: + "users():reading group data " + sqle);
446: sqle.printStackTrace();
447: } finally {
448: try {
449: pstmt.close();
450: } catch (Exception e) {
451: e.printStackTrace();
452: }
453: try {
454: con.close();
455: } catch (Exception e) {
456: e.printStackTrace();
457: }
458: }
459: return admins.iterator();
460: }
461:
462: public Iterator administrators() {
463: ArrayList admins = new ArrayList();
464: //Load list of group admins from db.
465: Connection con = null;
466: PreparedStatement pstmt = null;
467:
468: try {
469: con = DbConnectionManager.getConnection();
470: pstmt = con.prepareStatement(LOAD_ADMINS);
471: pstmt.setInt(1, id);
472: ResultSet rs = pstmt.executeQuery();
473: User user = null;
474: while (rs.next()) {
475: try {
476: user = profileManager.getUser(rs.getInt("userID"));
477: } catch (UserNotFoundException unfe) {
478: unfe.printStackTrace(System.out);
479: }
480: admins.add(user);
481: }
482: } catch (SQLException sqle) {
483: System.err.println("SQLException in DbGroup.java:"
484: + "administrators():reading group data " + sqle);
485: sqle.printStackTrace();
486: } finally {
487: try {
488: pstmt.close();
489: } catch (Exception e) {
490: e.printStackTrace();
491: }
492: try {
493: con.close();
494: } catch (Exception e) {
495: e.printStackTrace();
496: }
497: }
498: return admins.iterator();
499: }
500:
501: public ForumPermissions getPermissions(Authorization authorization) {
502: int userID = authorization.getUserID();
503: try {
504: User user = profileManager.getUser(userID);
505: if (isAdministrator(user)) {
506: return new ForumPermissions(false, false, false, false,
507: true, false, false, false);
508: }
509: } catch (Exception e) {
510: }
511:
512: return ForumPermissions.none();
513: }
514:
515: public boolean hasPermission(int type) {
516: return true;
517: }
518:
519: //FROM THE CACHEABLE INTERFACE//
520:
521: public int getSize() {
522: //Approximate the size of the object in bytes by calculating the size
523: //of each field.
524: int size = 0;
525: size += CacheSizes.sizeOfObject(); //overhead of object
526: size += CacheSizes.sizeOfInt(); //id
527: size += CacheSizes.sizeOfString(name); //name
528: size += CacheSizes.sizeOfString(description); //description
529: size += CacheSizes.sizeOfObject(); //profile manager ref.
530: size += CacheSizes.sizeOfObject(); //forum factory ref.
531:
532: return size;
533: }
534:
535: //OTHER METHODS
536:
537: /**
538: * Returns a String representation of the Group object using the group name.
539: *
540: * @return a String representation of the Group object.
541: */
542: public String toString() {
543: return name;
544: }
545:
546: public int hashCode() {
547: return id;
548: }
549:
550: public boolean equals(Object object) {
551: if (this == object) {
552: return true;
553: }
554: if (object != null && object instanceof DbGroup) {
555: return id == ((DbGroup) object).getID();
556: } else {
557: return false;
558: }
559: }
560:
561: /**
562: * Load the group data from the database.
563: */
564: private synchronized void loadFromDb()
565: throws GroupNotFoundException {
566: String query;
567: if (name == null) {
568: query = LOAD_GROUP_BY_ID;
569: } else {
570: query = LOAD_GROUP_BY_NAME;
571: }
572: Connection con = null;
573: PreparedStatement pstmt = null;
574: try {
575: con = DbConnectionManager.getConnection();
576: pstmt = con.prepareStatement(query);
577: if (name == null) {
578: pstmt.setInt(1, id);
579: } else {
580: pstmt.setString(1, name);
581: }
582: ResultSet rs = pstmt.executeQuery();
583: if (!rs.next()) {
584: throw new GroupNotFoundException();
585: }
586: this .id = rs.getInt("groupID");
587: this .name = rs.getString("name");
588: this .description = rs.getString("description");
589: this .automembership = (rs.getInt("automember") == 1) ? true
590: : false;
591: } catch (SQLException sqle) {
592: System.err.println("SQLException in DbGroup.java:"
593: + "loadFromDb():reading group data " + sqle);
594: throw new GroupNotFoundException();
595: } finally {
596: try {
597: pstmt.close();
598: } catch (Exception e) {
599: e.printStackTrace();
600: }
601: try {
602: con.close();
603: } catch (Exception e) {
604: e.printStackTrace();
605: }
606: }
607: }
608:
609: /**
610: * Inserts a new record into the database.
611: */
612: private void insertIntoDb() {
613: StringBuffer insert = new StringBuffer();
614: Connection con = null;
615: PreparedStatement pstmt = null;
616: try {
617: con = DbConnectionManager.getConnection();
618: pstmt = con.prepareStatement(INSERT_GROUP);
619: pstmt.setString(1, name);
620: pstmt.setString(2, description);
621: pstmt.setInt(3, id);
622: pstmt.executeUpdate();
623: } catch (SQLException sqle) {
624: System.err.println("Error in DbGroup:insertIntoDb()-"
625: + sqle);
626: sqle.printStackTrace();
627: } finally {
628: try {
629: pstmt.close();
630: } catch (Exception e) {
631: e.printStackTrace();
632: }
633: try {
634: con.close();
635: } catch (Exception e) {
636: e.printStackTrace();
637: }
638: }
639: }
640:
641: /**
642: * Saves group data to the db.
643: */
644: private synchronized void saveToDb() {
645: Connection con = null;
646: PreparedStatement pstmt = null;
647: try {
648: con = DbConnectionManager.getConnection();
649: pstmt = con.prepareStatement(SAVE_GROUP);
650: pstmt.setString(1, name);
651: pstmt.setString(2, description);
652: pstmt.setInt(3, (automembership ? 1 : 0));
653: pstmt.setInt(4, id);
654: pstmt.executeUpdate();
655: } catch (SQLException sqle) {
656: System.err
657: .println("SQLException in DbGroup.java:saveToDb(): "
658: + sqle);
659: sqle.printStackTrace();
660: } finally {
661: try {
662: pstmt.close();
663: } catch (Exception e) {
664: e.printStackTrace();
665: }
666: try {
667: con.close();
668: } catch (Exception e) {
669: e.printStackTrace();
670: }
671: }
672: }
673: }
|