KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nemesis > forum > impl > DbForum


1 /*
2  * NEMESIS-FORUM.
3  * Copyright (C) 2002 David Laurent(lithium2@free.fr). All rights reserved.
4  *
5  * Copyright (c) 2000 The Apache Software Foundation. All rights reserved.
6  *
7  * Copyright (C) 2001 Yasna.com. All rights reserved.
8  *
9  * Copyright (C) 2000 CoolServlets.com. All rights reserved.
10  *
11  * NEMESIS-FORUM. is free software; you can redistribute it and/or
12  * modify it under the terms of the Apache Software License, Version 1.1,
13  * or (at your option) any later version.
14  *
15  * NEMESIS-FORUM core framework, NEMESIS-FORUM backoffice, NEMESIS-FORUM frontoffice
16  * application are parts of NEMESIS-FORUM and are distributed under
17  * same terms of licence.
18  *
19  *
20  * NEMESIS-FORUM includes software developed by the Apache Software Foundation (http://www.apache.org/)
21  * and software developed by CoolServlets.com (http://www.coolservlets.com).
22  * and software developed by Yasna.com (http://www.yasna.com).
23  *
24  */

25 package org.nemesis.forum.impl;
26
27 import java.io.ByteArrayOutputStream JavaDoc;
28 import java.io.ObjectInputStream JavaDoc;
29 import java.io.ObjectOutputStream JavaDoc;
30 import java.sql.Connection JavaDoc;
31 import java.sql.PreparedStatement JavaDoc;
32 import java.sql.ResultSet JavaDoc;
33 import java.sql.SQLException JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.Date JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Properties JavaDoc;
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42 import org.nemesis.forum.Authorization;
43 import org.nemesis.forum.Forum;
44 import org.nemesis.forum.ForumPermissions;
45 import org.nemesis.forum.ForumThread;
46 import org.nemesis.forum.Group;
47 import org.nemesis.forum.Message;
48 import org.nemesis.forum.MessageFilter;
49 import org.nemesis.forum.User;
50 import org.nemesis.forum.config.Constants;
51 import org.nemesis.forum.exception.ForumMessageNotFoundException;
52 import org.nemesis.forum.exception.ForumNotFoundException;
53 import org.nemesis.forum.exception.ForumThreadNotFoundException;
54 import org.nemesis.forum.exception.UnauthorizedException;
55 import org.nemesis.forum.filter.FilterHtml;
56 import org.nemesis.forum.filter.FilterNewline;
57 import org.nemesis.forum.proxy.ForumThreadProxy;
58 import org.nemesis.forum.proxy.MessageProxy;
59 import org.nemesis.forum.util.cache.Cache;
60 import org.nemesis.forum.util.cache.CacheSizes;
61 import org.nemesis.forum.util.cache.Cacheable;
62 import org.nemesis.forum.util.jdbc.DbConnectionManager;
63 /**
64  * Database implementation of the Forum interface. It loads and stores forum
65  * information from a a database.
66  *
67  * @see Forum
68  */

69 public class DbForum implements Forum, Cacheable {
70     
71 static protected Log log = LogFactory.getLog(DbForum.class);
72     /** DATABASE QUERIES **/
73     private static final String JavaDoc ADD_THREAD = "UPDATE yazdThread set forumID=? WHERE threadID=?";
74     protected static final String JavaDoc DELETE_THREAD = "DELETE FROM yazdThread WHERE threadID=?";
75     private static final String JavaDoc THREAD_COUNT = "SELECT count(*) FROM yazdThread WHERE forumID=?";
76     private static final String JavaDoc MESSAGE_COUNT = "SELECT count(*) FROM yazdThread, yazdMessage WHERE " + "yazdThread.forumID=? AND yazdThread.threadID=yazdMessage.threadID";
77     private static final String JavaDoc ADD_USER_PERM = "INSERT INTO yazdUserPerm(forumID,userID,permission) VALUES(?,?,?)";
78     private static final String JavaDoc REMOVE_USER_PERM = "DELETE FROM yazdUserPerm WHERE forumID=? AND userID=? AND permission=?";
79     private static final String JavaDoc USERS_WITH_PERM = "SELECT DISTINCT userID FROM yazdUserPerm WHERE forumID=? AND permission=?";
80     private static final String JavaDoc ADD_GROUP_PERM = "INSERT INTO yazdGroupPerm(forumID,groupID,permission) VALUES(?,?,?)";
81     private static final String JavaDoc REMOVE_GROUP_PERM = "DELETE FROM yazdGroupPerm WHERE forumID=? AND groupID=? AND permission=?";
82     private static final String JavaDoc GROUPS_WITH_PERM = "SELECT DISTINCT groupID FROM yazdGroupPerm WHERE forumID=? AND permission=?";
83     private static final String JavaDoc LOAD_FILTERS = "SELECT filterObject, filterIndex FROM yazdFilter WHERE forumID=? ORDER BY filterIndex ASC";
84     private static final String JavaDoc DELETE_FILTERS = "DELETE FROM yazdFilter WHERE forumID=?";
85     private static final String JavaDoc ADD_FILTER = "INSERT INTO yazdFilter(forumID,filterIndex,filterObject) VALUES(?,?,?)";
86     private static final String JavaDoc LOAD_PROPERTIES = "SELECT name, propValue FROM yazdForumProp WHERE forumID=?";
87     private static final String JavaDoc DELETE_PROPERTIES = "DELETE FROM yazdForumProp WHERE forumID=?";
88     private static final String JavaDoc INSERT_PROPERTY = "INSERT INTO yazdForumProp(forumID,name,propValue) VALUES(?,?,?)";
89     private static final String JavaDoc LOAD_FORUM_BY_ID = "SELECT forumID, name, description, creationDate, modifiedDate, moderated FROM yazdForum WHERE forumID=?";
90     private static final String JavaDoc LOAD_FORUM_BY_NAME = "SELECT forumID, name, description, creationDate, modifiedDate, moderated FROM yazdForum WHERE name=?";
91     private static final String JavaDoc ADD_FORUM = "INSERT INTO yazdForum(forumID, name, description, creationDate, " + "modifiedDate, moderated) VALUES (?,?,?,?,?,?)";
92     private static final String JavaDoc SAVE_FORUM = "UPDATE yazdForum SET name=?, description=?, creationDate=?, " + "modifiedDate=?, moderated=? WHERE forumID=?";
93     private static final String JavaDoc UPDATE_FORUM_MODIFIED_DATE = "UPDATE yazdForum SET modifiedDate=? WHERE forumID=?";
94
95     private static final String JavaDoc APPROVED_MESSAGE_COUNT = "SELECT count(*) FROM yazdThread, yazdMessage WHERE " + "yazdThread.forumID=? AND yazdMessage.approved=? AND yazdThread.threadID=yazdMessage.threadID";
96     private static final String JavaDoc APPROVED_THREAD_COUNT = "SELECT count(*) FROM yazdThread WHERE forumID=? AND approved=? ";
97     
98     
99     private int id = -1;
100     private String JavaDoc name;
101     private String JavaDoc description;
102     private java.util.Date JavaDoc creationDate;
103     private java.util.Date JavaDoc modifiedDate;
104     private int moderation = 0;
105     private MessageFilter[] filters;
106     private Properties JavaDoc properties;
107     //Lock for saving state to database.
108
private Object JavaDoc saveLock = new Object JavaDoc();
109
110     private DbForumFactory factory;
111
112     /**
113      * Creates a new forum with the specified name and description.
114      *
115      * @param name the name of the forum.
116      * @param description the description of the forum.
117      * @param factory the DbForumFactory the forum is a part of.
118      */

119     protected DbForum(String JavaDoc name, String JavaDoc description, DbForumFactory factory) {
120         this.id = DbSequenceManager.nextID("Forum");
121         this.name = name;
122         this.description = description;
123         long now = System.currentTimeMillis();
124         creationDate = new java.util.Date JavaDoc(now);
125         modifiedDate = new java.util.Date JavaDoc(now);
126         this.factory = factory;
127         insertIntoDb();
128         properties = new Properties JavaDoc();
129         //Forums should start with an html filter by default for
130
//security purposes.
131
filters = new MessageFilter[2];
132         filters[0] = new FilterHtml();
133         filters[1] = new FilterNewline();
134         saveFiltersToDb();
135         //**Commenting out below since it doesn't seem to work for some reason.
136
//try {
137
// addForumMessageFilter(new FilterHtml(), 0);
138
// addForumMessageFilter(new FilterNewline(), 1);
139
//}
140
//catch (UnauthorizedException ue) {
141
//
142
//}
143
}
144
145     /**
146      * Loads a forum with the specified id.
147      */

148     protected DbForum(int id, DbForumFactory factory) throws ForumNotFoundException {
149         this.id = id;
150         this.factory = factory;
151         loadFromDb();
152         loadFiltersFromDb();
153         loadProperties();
154     }
155
156     /**
157      * Loads a forum with the specified name.
158      */

159     protected DbForum(String JavaDoc name, DbForumFactory factory) throws ForumNotFoundException {
160         this.name = name;
161         this.factory = factory;
162         loadFromDb();
163         loadFiltersFromDb();
164         loadProperties();
165     }
166
167     //FROM THE FORUM INTERFACE//
168

169     
170     public int getModerationType(){
171             return moderation;
172     }
173
174     public void setModerationType(int type) throws UnauthorizedException {
175         this.moderation=type;
176         saveToDb();
177     }
178     
179
180     public int getID() {
181         return id;
182     }
183
184     public String JavaDoc getName() {
185         return name;
186     }
187
188     public void setName(String JavaDoc name) throws UnauthorizedException {
189         this.name = name;
190         saveToDb();
191     }
192
193     public String JavaDoc getDescription() {
194         return description;
195     }
196
197     public void setDescription(String JavaDoc description) throws UnauthorizedException {
198         this.description = description;
199         saveToDb();
200     }
201
202     public java.util.Date JavaDoc getCreationDate() {
203         return creationDate;
204     }
205
206     public void setCreationDate(java.util.Date JavaDoc creationDate) throws UnauthorizedException {
207         this.creationDate = creationDate;
208         saveToDb();
209     }
210
211     public java.util.Date JavaDoc getModifiedDate() {
212         return modifiedDate;
213     }
214
215     public void setModifiedDate(java.util.Date JavaDoc modifiedDate) throws UnauthorizedException {
216         this.modifiedDate = modifiedDate;
217         saveToDb();
218     }
219
220     public String JavaDoc getProperty(String JavaDoc name) {
221         return (String JavaDoc) properties.get(name);
222     }
223
224     public void setProperty(String JavaDoc name, String JavaDoc value) throws UnauthorizedException {
225         properties.put(name, value);
226         saveProperties();
227     }
228
229     public Enumeration JavaDoc propertyNames() {
230         return properties.keys();
231     }
232
233     
234
235
236     public ForumThread createThread(Message rootMessage) throws UnauthorizedException {
237         //If the forum is 'THREAD OR MESSAGE' moderated, the message is not automatically
238
//approved.
239
boolean approved = !(getModerationType()==Constants.MODERATION_MESSAGE || getModerationType()==Constants.MODERATION_THREAD);
240          // message is root -->force moderation,architecture violation @see messageproxy !!!
241
((MessageProxy)rootMessage).setApproved2(approved);
242         return new DbForumThread(rootMessage, approved, this, factory);
243     }
244
245     public Message createMessage(User user) throws UnauthorizedException {
246         //If the forum is 'MESSAGE' moderated, the message is not automatically
247
//approved.
248
boolean approved = getModerationType()!=Constants.MODERATION_MESSAGE ;
249         return new DbForumMessage(user, approved, factory);//---------:ICI:
250
}
251
252     public void addThread(ForumThread thread) throws UnauthorizedException {
253         boolean abortTransaction = false;
254         boolean supportsTransactions = false;
255         //Add message to db
256
Connection JavaDoc con = null;
257         PreparedStatement JavaDoc pstmt = null;
258         try {
259             con = DbConnectionManager.getConnection();
260             supportsTransactions = con.getMetaData().supportsTransactions();
261             if (supportsTransactions) {
262                 con.setAutoCommit(false);
263             }
264
265             pstmt = con.prepareStatement(ADD_THREAD);
266             pstmt.setInt(1, id);
267             pstmt.setInt(2, thread.getID());
268             pstmt.executeUpdate();
269             pstmt.close();
270
271             //Now, insert the thread into the database.
272
((ForumThreadProxy) thread).insertIntoDb(con);
273         } catch (Exception JavaDoc e) {
274             log.error("",e);
275             abortTransaction = true;
276             return;
277         } finally {
278             try {
279                 if (supportsTransactions) {
280                     if (abortTransaction == true) {
281                         con.rollback();
282                     } else {
283                         con.commit();
284                     }
285                 }
286             } catch (Exception JavaDoc e) {
287                 log.error("",e);
288             }
289             try {
290                 if (supportsTransactions) {
291                     con.setAutoCommit(true);
292                 }
293                 con.close();
294             } catch (Exception JavaDoc e) {
295                 log.error("",e);
296             }
297         }
298
299         //Since we added a thread, update the modified date of this thread.
300
updateModifiedDate(thread.getModifiedDate());
301     }
302
303     public ForumThread getThread(int threadID) throws ForumThreadNotFoundException {
304         return factory.getThread(threadID, this);
305     }
306     
307     public Message getMessage(int messageID) throws ForumMessageNotFoundException {
308             return factory.getMessage(messageID);
309         }
310
311     public void deleteThread(ForumThread thread) throws UnauthorizedException {
312         //Delete all messages from the thread. Deleting the root
313
//message will delete all submessages.
314
Message message = thread.getRootMessage();
315         thread.deleteMessage(message);
316     }
317
318     protected void deleteThreadRecord(int threadID) {
319
320         //Delete the actual thread
321
Connection JavaDoc con = null;
322         PreparedStatement JavaDoc pstmt = null;
323         try {
324             con = DbConnectionManager.getConnection();
325             pstmt = con.prepareStatement(DELETE_THREAD);
326             pstmt.setInt(1, threadID);
327             pstmt.execute();
328         } catch (Exception JavaDoc sqle) {
329             log.error("Error in DbForum:deleteThread()-" + sqle);
330         } finally {
331             try {
332                 pstmt.close();
333             } catch (Exception JavaDoc e) {
334                 log.error("",e);
335             }
336             try {
337                 con.close();
338             } catch (Exception JavaDoc e) {
339                 log.error("",e);
340             }
341         }
342
343         //Now, delete from cache
344
Integer JavaDoc threadIDInteger = new Integer JavaDoc(threadID);
345         factory.getCacheManager().remove(DbCacheManager.THREAD_CACHE, threadIDInteger);
346     }
347
348     public void moveThread(ForumThread thread, Forum forum) throws UnauthorizedException {
349         //Ensure that thread belongs to this forum
350
if (thread.getForum().getID() != this.id) {
351             throw new IllegalArgumentException JavaDoc("The thread does not belong to this forum.");
352         }
353
354         //Modify the SQL record. Only the thread table has information about
355
//forumID, so we only need to modify that record. The message records
356
//underneath the thread can be left alone.
357
Connection JavaDoc con = null;
358         PreparedStatement JavaDoc pstmt = null;
359         try {
360             con = DbConnectionManager.getConnection();
361             pstmt = con.prepareStatement(ADD_THREAD);
362             pstmt.setInt(1, forum.getID());
363             pstmt.setInt(2, thread.getID());
364             pstmt.executeUpdate();
365             pstmt.close();
366         } catch (SQLException JavaDoc sqle) {
367             log.error("Error in DbForum:addThread()-" , sqle);
368             return;
369         } finally {
370             try {
371                 pstmt.close();
372             } catch (Exception JavaDoc e) {
373                 log.error("",e);
374             }
375             try {
376                 con.close();
377             } catch (Exception JavaDoc e) {
378                 log.error("",e);
379             }
380         }
381
382         DbCacheManager cacheManager = factory.getCacheManager();
383         //SearchIndexer indexer = factory.getSearchIndexer();
384

385         //Remove both forums from cache.
386
Integer JavaDoc key = new Integer JavaDoc(this.id);
387         cacheManager.remove(DbCacheManager.FORUM_CACHE, key);
388         key = new Integer JavaDoc(forum.getID());
389         cacheManager.remove(DbCacheManager.FORUM_CACHE, key);
390
391         //Remove thread from cache.
392
key = new Integer JavaDoc(thread.getID());
393         cacheManager.remove(DbCacheManager.THREAD_CACHE, key);
394
395         //Loop through all messages in thread
396
Iterator JavaDoc messages = thread.messages();
397         while (messages.hasNext()) {
398             Message message = (Message) messages.next();
399             //Remove each message from cache.
400
key = new Integer JavaDoc(message.getID());
401             cacheManager.remove(DbCacheManager.MESSAGE_CACHE, key);
402             //Remove and re-add every message to the search index.
403
// indexer.removeFromIndex(message);
404
// indexer.addToIndex(message);
405
}
406
407         // Update the modified date of thread
408
Date JavaDoc now = new Date JavaDoc();
409         thread.setModifiedDate(now);
410         // Update the modified date of forum thread is now in
411
forum.setModifiedDate(now);
412     }
413
414     public Iterator JavaDoc threads() {
415         return new DbForumIterator(this, factory);
416     }
417
418     public Iterator JavaDoc threads(int startIndex, int numResults) {
419         return new DbForumIterator(this, factory, startIndex, numResults);
420     }
421     
422     public Iterator JavaDoc threads(boolean approved) {
423         return new DbForumIterator(this, factory,approved);
424     }
425
426     public Iterator JavaDoc threads(boolean approved,int startIndex, int numResults) {
427         return new DbForumIterator(this, factory, startIndex, numResults,approved);
428     }
429
430     public int getThreadCount() {
431         int threadCount = 0;
432         // Based on the id in the object, get the thread data from the database:
433
Connection JavaDoc con = null;
434         PreparedStatement JavaDoc pstmt = null;
435         try {
436             con = DbConnectionManager.getConnection();
437             pstmt = con.prepareStatement(THREAD_COUNT);
438             pstmt.setInt(1, id);
439             ResultSet JavaDoc rs = pstmt.executeQuery();
440             rs.next();
441             threadCount = rs.getInt(1 /*"threadCount"*/
442             );
443         } catch (SQLException JavaDoc sqle) {
444             log.error("DbForum:getThreadCount() failed: " , sqle);
445         } finally {
446             try {
447                 pstmt.close();
448             } catch (Exception JavaDoc e) {
449                 log.error("",e);
450             }
451             try {
452                 con.close();
453             } catch (Exception JavaDoc e) {
454                 log.error("",e);
455             }
456         }
457         return threadCount;
458     }
459     
460     public int getThreadCount(boolean approved) {
461             int threadCount = 0;
462             // Based on the id in the object, get the thread data from the database:
463
Connection JavaDoc con = null;
464             PreparedStatement JavaDoc pstmt = null;
465             try {
466                 con = DbConnectionManager.getConnection();
467                 pstmt = con.prepareStatement(APPROVED_THREAD_COUNT);
468                 pstmt.setInt(1, id);
469                 pstmt.setInt(2, approved?1:0);
470                 ResultSet JavaDoc rs = pstmt.executeQuery();
471                 rs.next();
472                 threadCount = rs.getInt(1 /*"threadCount"*/
473                 );
474             } catch (SQLException JavaDoc sqle) {
475                 log.error("DbForum:getThreadCount() failed: " , sqle);
476             } finally {
477                 try {
478                     pstmt.close();
479                 } catch (Exception JavaDoc e) {
480                     log.error("",e);
481                 }
482                 try {
483                     con.close();
484                 } catch (Exception JavaDoc e) {
485                     log.error("",e);
486                 }
487             }
488             return threadCount;
489         }
490
491     public int getMessageCount() {
492         int messageCount = 0;
493         Connection JavaDoc con = null;
494         PreparedStatement JavaDoc pstmt = null;
495         try {
496             con = DbConnectionManager.getConnection();
497             pstmt = con.prepareStatement(MESSAGE_COUNT);
498             pstmt.setInt(1, id);
499             ResultSet JavaDoc rs = pstmt.executeQuery();
500             rs.next();
501             messageCount = rs.getInt(1 /*"messageCount"*/
502             );
503         } catch (SQLException JavaDoc sqle) {
504             log.error("DbForum:getMessageCount() failed: " , sqle);
505         } finally {
506             try {
507                 pstmt.close();
508             } catch (Exception JavaDoc e) {
509                 log.error("",e);
510             }
511             try {
512                 con.close();
513             } catch (Exception JavaDoc e) {
514                 log.error("",e);
515             }
516         }
517         return messageCount;
518     }
519     
520     public int getMessageCount(boolean approved) {
521             int messageCount = 0;
522             Connection JavaDoc con = null;
523             PreparedStatement JavaDoc pstmt = null;
524             try {
525                 con = DbConnectionManager.getConnection();
526                 pstmt = con.prepareStatement(APPROVED_MESSAGE_COUNT);
527                 pstmt.setInt(1, id);
528                 pstmt.setInt(2, approved? 1:0);
529                 ResultSet JavaDoc rs = pstmt.executeQuery();
530                 rs.next();
531                 messageCount = rs.getInt(1 /*"messageCount"*/
532                 );
533             } catch (SQLException JavaDoc sqle) {
534                 log.error("DbForum:getMessageCount() failed: " , sqle);
535             } finally {
536                 try {
537                     pstmt.close();
538                 } catch (Exception JavaDoc e) {
539                     log.error("",e);
540                 }
541                 try {
542                     con.close();
543                 } catch (Exception JavaDoc e) {
544                     log.error("",e);
545                 }
546             }
547             return messageCount;
548         }
549
550
551
552     public void addUserPermission(User user, int permissionType) throws UnauthorizedException {
553         Connection JavaDoc con = null;
554         PreparedStatement JavaDoc pstmt = null;
555         try {
556             con = DbConnectionManager.getConnection();
557             pstmt = con.prepareStatement(ADD_USER_PERM);
558             pstmt.setInt(1, id);
559             pstmt.setInt(2, user.getID());
560             pstmt.setInt(3, permissionType);
561             pstmt.execute();
562             //Remove user permissions from cache since they've changed.
563
factory.getCacheManager().removeUserPerm(new Integer JavaDoc(user.getID()), new Integer JavaDoc(id));
564         } catch (SQLException JavaDoc sqle) {
565             log.error("Error in DbForum.java:" , sqle);
566         } finally {
567             try {
568                 pstmt.close();
569             } catch (Exception JavaDoc e) {
570                 log.error("",e);
571             }
572             try {
573                 con.close();
574             } catch (Exception JavaDoc e) {
575                 log.error("",e);
576             }
577         }
578     }
579
580     public void removeUserPermission(User user, int permissionType) throws UnauthorizedException {
581         Connection JavaDoc con = null;
582         PreparedStatement JavaDoc pstmt = null;
583         try {
584             con = DbConnectionManager.getConnection();
585             pstmt = con.prepareStatement(REMOVE_USER_PERM);
586             pstmt.setInt(1, id);
587             pstmt.setInt(2, user.getID());
588             pstmt.setInt(3, permissionType);
589             pstmt.execute();
590             //Remove user permissions from cache since they've changed.
591
factory.getCacheManager().removeUserPerm(new Integer JavaDoc(user.getID()), new Integer JavaDoc(id));
592         } catch (SQLException JavaDoc sqle) {
593             log.error("Error in DbForum.java:", sqle);
594         } finally {
595             try {
596                 pstmt.close();
597             } catch (Exception JavaDoc e) {
598                 log.error("Error in DbForum.java:", e);
599             }
600             try {
601                 con.close();
602             } catch (Exception JavaDoc e) {
603                 log.error("Error in DbForum.java:", e);
604             }
605         }
606     }
607
608     public int[] usersWithPermission(int permissionType) throws UnauthorizedException {
609         int[] users = new int[0];
610         Connection JavaDoc con = null;
611         PreparedStatement JavaDoc pstmt = null;
612         try {
613             con = DbConnectionManager.getConnection();
614             pstmt = con.prepareStatement(USERS_WITH_PERM);
615             pstmt.setInt(1, id);
616             pstmt.setInt(2, permissionType);
617             ResultSet JavaDoc rs = pstmt.executeQuery();
618             ArrayList JavaDoc userList = new ArrayList JavaDoc();
619             while (rs.next()) {
620                 userList.add(new Integer JavaDoc(rs.getInt("userID")));
621             }
622             users = new int[userList.size()];
623             for (int i = 0; i < users.length; i++) {
624                 users[i] = ((Integer JavaDoc) userList.get(i)).intValue();
625             }
626         } catch (SQLException JavaDoc sqle) {
627             log.error("Error in DbForum.java:" , sqle);
628             
629         } finally {
630             try {
631                 pstmt.close();
632             } catch (Exception JavaDoc e) {
633                 log.error("Error in DbForum.java:", e);
634             }
635             try {
636                 con.close();
637             } catch (Exception JavaDoc e) {
638                 log.error("Error in DbForum.java:", e);
639             }
640         }
641         return users;
642     }
643
644     public void addGroupPermission(Group group, int permissionType) throws UnauthorizedException {
645         Connection JavaDoc con = null;
646         PreparedStatement JavaDoc pstmt = null;
647         try {
648             con = DbConnectionManager.getConnection();
649             pstmt = con.prepareStatement(ADD_GROUP_PERM);
650             pstmt.setInt(1, id);
651             pstmt.setInt(2, group.getID());
652             pstmt.setInt(3, permissionType);
653             pstmt.execute();
654             //Remove user permissions from cache since they've changed. Because
655
//of the way that user perm cache is handled, it is easiest to
656
//simply remove all the user perm cache for the forum. This is ok
657
//since happens infrequently.
658
factory.getCacheManager().remove(DbCacheManager.USER_PERMS_CACHE, new Integer JavaDoc(id));
659         } catch (SQLException JavaDoc sqle) {
660             log.error("Error in DbForum.java:" , sqle);
661         } finally {
662             try {
663                 pstmt.close();
664             } catch (Exception JavaDoc e) {
665                 log.error("Error in DbForum.java:", e);
666             }
667             try {
668                 con.close();
669             } catch (Exception JavaDoc e) {
670                 log.error("Error in DbForum.java:",e);
671             }
672         }
673     }
674
675     public void removeGroupPermission(Group group, int permissionType) throws UnauthorizedException {
676         Connection JavaDoc con = null;
677         PreparedStatement JavaDoc pstmt = null;
678         try {
679             con = DbConnectionManager.getConnection();
680             pstmt = con.prepareStatement(REMOVE_GROUP_PERM);
681             pstmt.setInt(1, id);
682             pstmt.setInt(2, group.getID());
683             pstmt.setInt(3, permissionType);
684             pstmt.execute();
685             //Remove user permissions from cache since they've changed. Because
686
//of the way that user perm cache is handled, it is easiest to
687
//simply remove all the user perm cache for the forum. This is ok
688
//since happens infrequently.
689
factory.getCacheManager().remove(DbCacheManager.USER_PERMS_CACHE, new Integer JavaDoc(id));
690         } catch (SQLException JavaDoc sqle) {
691             log.error("Error in DbForum.java:" , sqle);
692             
693         } finally {
694             try {
695                 pstmt.close();
696             } catch (Exception JavaDoc e) {
697                 log.error("Error in DbForum.java:",e);
698             }
699             try {
700                 con.close();
701             } catch (Exception JavaDoc e) {
702                 log.error("Error in DbForum.java:",e);
703             }
704         }
705     }
706
707     public int[] groupsWithPermission(int permissionType) throws UnauthorizedException {
708         int[] groups = new int[0];
709         Connection JavaDoc con = null;
710         PreparedStatement JavaDoc pstmt = null;
711         try {
712             con = DbConnectionManager.getConnection();
713             pstmt = con.prepareStatement(GROUPS_WITH_PERM);
714             pstmt.setInt(1, id);
715             pstmt.setInt(2, permissionType);
716             ResultSet JavaDoc rs = pstmt.executeQuery();
717             ArrayList JavaDoc groupList = new ArrayList JavaDoc();
718             while (rs.next()) {
719                 groupList.add(new Integer JavaDoc(rs.getInt("groupID")));
720             }
721             groups = new int[groupList.size()];
722             for (int i = 0; i < groups.length; i++) {
723                 groups[i] = ((Integer JavaDoc) groupList.get(i)).intValue();
724             }
725         } catch (SQLException JavaDoc sqle) {
726             log.error("Error in DbForum.groupsWithPermission:" , sqle);
727             
728         } finally {
729             try {
730                 pstmt.close();
731             } catch (Exception JavaDoc e) {
732                 log.error("Error in DbForum.java:",e);
733             }
734             try {
735                 con.close();
736             } catch (Exception JavaDoc e) {
737                 log.error("Error in DbForum.java:",e);
738             }
739         }
740         return groups;
741     }
742
743     public Message applyFilters(Message message) {
744         //Loop through filters and apply them
745
for (int i = 0; i < filters.length; i++) {
746             message = filters[i].clone(message);
747         }
748         return message;
749     }
750
751     public MessageFilter[] getForumMessageFilters() throws UnauthorizedException {
752         MessageFilter[] dbFilters = new MessageFilter[filters.length];
753         for (int i = 0; i < filters.length; i++) {
754             dbFilters[i] = new DbForumMessageFilter((Message) filters[i], this);
755         }
756         return dbFilters;
757     }
758
759     public void addForumMessageFilter(MessageFilter filter) throws UnauthorizedException {
760         ArrayList JavaDoc newFilters = new ArrayList JavaDoc(filters.length + 1);
761         for (int i = 0; i < filters.length; i++) {
762             newFilters.add(filters[i]);
763         }
764         newFilters.add(filter);
765         MessageFilter[] newArray = new MessageFilter[newFilters.size()];
766         for (int i = 0; i < newArray.length; i++) {
767             newArray[i] = (MessageFilter) newFilters.get(i);
768         }
769         //Finally, overwrite filters with the new array
770
filters = newArray;
771         saveFiltersToDb();
772     }
773
774     public void addForumMessageFilter(MessageFilter filter, int index) throws UnauthorizedException {
775         ArrayList JavaDoc newFilters = new ArrayList JavaDoc(filters.length + 1);
776         for (int i = 0; i < filters.length; i++) {
777             newFilters.add(filters[i]);
778         }
779         newFilters.add(index, filter);
780         MessageFilter[] newArray = new MessageFilter[newFilters.size()];
781         for (int i = 0; i < newArray.length; i++) {
782             newArray[i] = (MessageFilter) newFilters.get(i);
783         }
784         //Finally, overwrite filters with the new array
785
filters = newArray;
786         saveFiltersToDb();
787     }
788
789     public void removeForumMessageFilter(int index) throws UnauthorizedException {
790         ArrayList JavaDoc newFilters = new ArrayList JavaDoc(filters.length);
791         for (int i = 0; i < filters.length; i++) {
792             newFilters.add(filters[i]);
793         }
794         newFilters.remove(index);
795         MessageFilter[] newArray = new MessageFilter[newFilters.size()];
796         for (int i = 0; i < newArray.length; i++) {
797             newArray[i] = (MessageFilter) newFilters.get(i);
798         }
799         //Finally, overwrite filters with the new array
800
filters = newArray;
801         saveFiltersToDb();
802     }
803
804     public ForumPermissions getPermissions(Authorization authorization) {
805         int userID = authorization.getUserID();
806
807         //Get the user perm cache for this forum
808
Cache userPermCache = (Cache) factory.getCacheManager().get(DbCacheManager.USER_PERMS_CACHE, new Integer JavaDoc(id));
809
810         //Simple case: if cache is turned on and the user is already cached,
811
//we can simply return the cached permissions.
812
if (userPermCache != null) {
813             ForumPermissions permissions = (ForumPermissions) userPermCache.get(new Integer JavaDoc(userID));
814             if (permissions != null) {
815                 return permissions;
816             }
817         }
818
819         //Not so simple case: cache is not turned on or the user permissions
820
//have not been cached yet.
821
boolean isAnonymous = (userID == -1);
822         boolean isUser = !isAnonymous;
823
824         ForumPermissions finalPermissions = ForumPermissions.none();
825
826         //Step 1 - Get permissions for the User. This includes anonymous
827
//perms, "special user" perms, and the specific perms for the user.
828
if (isUser) {
829             ForumPermissions userPermissions = factory.getUserPermissions(userID, id);
830             //Combine permissions
831
finalPermissions = new ForumPermissions(finalPermissions, userPermissions);
832         }
833         //Add in anonymous perms.
834
ForumPermissions anonyPermissions = null;
835         if (userPermCache != null) {
836             anonyPermissions = (ForumPermissions) userPermCache.get(new Integer JavaDoc(-1));
837         }
838         //Otherwise, do our own lookup.
839
if (anonyPermissions == null) {
840             anonyPermissions = factory.getUserPermissions(-1, id);
841             //Add to cache so it will be there next time.
842
if (userPermCache != null) {
843                 userPermCache.add(new Integer JavaDoc(-1), anonyPermissions);
844             }
845         }
846         //Combine permissions
847
finalPermissions = new ForumPermissions(finalPermissions, anonyPermissions);
848
849         //If they are a valid user, figure out "any user" permissions.
850
if (isUser) {
851             ForumPermissions specialUserPermissions = null;
852             //Check for cache
853
if (userPermCache != null) {
854                 specialUserPermissions = (ForumPermissions) userPermCache.get(new Integer JavaDoc(0));
855             }
856             //Otherwise, do our own lookup.
857
if (specialUserPermissions == null) {
858                 specialUserPermissions = factory.getUserPermissions(0, id);
859                 //Add to cache so it will be there next time.
860
if (userPermCache != null) {
861                     userPermCache.add(new Integer JavaDoc(0), specialUserPermissions);
862                 }
863             }
864             //Combine permissions
865
finalPermissions = new ForumPermissions(finalPermissions, specialUserPermissions);
866         }
867
868         //Step 2 -- get Permissions for all groups the user is in.
869
int[] groups = ((DbProfileManager) factory.getProfileManager()).getUserGroups(userID);
870         for (int i = 0; i < groups.length; i++) {
871             ForumPermissions groupPermissions = factory.getGroupPermissions(groups[i], id);
872             finalPermissions = new ForumPermissions(finalPermissions, groupPermissions);
873         }
874
875         //Finally, add user to cache so it will be there next time.
876
if (isUser && userPermCache != null) {
877             userPermCache.add(new Integer JavaDoc(userID), finalPermissions);
878         }
879
880         return finalPermissions;
881     }
882
883     public boolean hasPermission(int type) {
884         return true;
885     }
886
887     //FROM THE CACHEABLE INTERFACE//
888

889     public int getSize() {
890         //Approximate the size of the object in bytes by calculating the size
891
//of each field.
892
int size = 0;
893         size += CacheSizes.sizeOfObject(); //overhead of object
894
size += CacheSizes.sizeOfInt(); //id
895
size += CacheSizes.sizeOfString(name); //name
896
size += CacheSizes.sizeOfString(description); //description
897
size += CacheSizes.sizeOfDate(); //creation date
898
size += CacheSizes.sizeOfDate(); //modified date
899
size += CacheSizes.sizeOfInt(); //moderated
900
size += filters.length * 8; //each filter is 8 bytes
901
size += CacheSizes.sizeOfProperties(properties); //properties object
902
size += CacheSizes.sizeOfObject(); //save lock
903

904         return size;
905     }
906
907     //OTHER METHODS
908

909     /**
910      * Returns a String representation of the Forum object using the forum name.
911      *
912      * @return a String representation of the Forum object.
913      */

914     public String JavaDoc toString() {
915         return name;
916     }
917
918     public int hashCode() {
919         return id;
920     }
921
922     public boolean equals(Object JavaDoc object) {
923         if (this == object) {
924             return true;
925         }
926         if (object != null && object instanceof DbForum) {
927             return id == ((DbForum) object).getID();
928         } else {
929             return false;
930         }
931     }
932
933     /**
934      * Updates the modified date but doesn't require a security check since
935      * it is a protected method.
936      */

937     protected void updateModifiedDate(java.util.Date JavaDoc modifiedDate) {
938         this.modifiedDate = modifiedDate;
939         Connection JavaDoc con = null;
940         PreparedStatement JavaDoc pstmt = null;
941         try {
942             con = DbConnectionManager.getConnection();
943             pstmt = con.prepareStatement(UPDATE_FORUM_MODIFIED_DATE);
944             pstmt.setString(1, "" + modifiedDate.getTime());
945             pstmt.setInt(2, id);
946             pstmt.executeUpdate();
947         } catch (SQLException JavaDoc sqle) {
948             log.error("Error in DbForum:updateModifiedDate()-" , sqle);
949             
950         } finally {
951             try {
952                 pstmt.close();
953             } catch (Exception JavaDoc e) {
954                 log.error("Error in DbForum.java:",e);
955             }
956             try {
957                 con.close();
958             } catch (Exception JavaDoc e) {
959                 log.error("Error in DbForum.java:",e);
960             }
961         }
962     }
963
964     /**
965      * Loads forum properties from the database.
966      */

967     private void loadProperties() {
968         synchronized (saveLock) {
969             Properties JavaDoc newProps = new Properties JavaDoc();
970             Connection JavaDoc con = null;
971             PreparedStatement JavaDoc pstmt = null;
972             try {
973                 con = DbConnectionManager.getConnection();
974                 pstmt = con.prepareStatement(LOAD_PROPERTIES);
975                 pstmt.setInt(1, id);
976                 ResultSet JavaDoc rs = pstmt.executeQuery();
977                 while (rs.next()) {
978                     String JavaDoc name = rs.getString("name");
979                     String JavaDoc value = rs.getString("propValue");
980                     newProps.put(name, value);
981                 }
982             } catch (SQLException JavaDoc sqle) {
983                 log.error("Error in DbForum:loadProperties():" , sqle);
984                 
985             } finally {
986                 try {
987                     pstmt.close();
988                 } catch (Exception JavaDoc e) {
989                     log.error("Error in DbForum.java:",e);
990                 }
991                 try {
992                     con.close();
993                 } catch (Exception JavaDoc e) {
994                     log.error("Error in DbForum.java:",e);
995                 }
996             }
997             this.properties = newProps;
998         }
999     }
1000
1001    /**
1002     * Saves forum properties to the database.
1003     */

1004    private void saveProperties() {
1005        synchronized (saveLock) {
1006            Connection JavaDoc con = null;
1007            PreparedStatement JavaDoc pstmt = null;
1008            try {
1009                con = DbConnectionManager.getConnection();
1010                //Delete all old values.
1011
pstmt = con.prepareStatement(DELETE_PROPERTIES);
1012                pstmt.setInt(1, id);
1013                pstmt.execute();
1014                pstmt.close();
1015                //Now insert new values.
1016
pstmt = con.prepareStatement(INSERT_PROPERTY);
1017                Enumeration JavaDoc e = properties.keys();
1018                while (e.hasMoreElements()) {
1019                    String JavaDoc name = (String JavaDoc) e.nextElement();
1020                    String JavaDoc value = (String JavaDoc) properties.get(name);
1021                    pstmt.setInt(1, id);
1022                    pstmt.setString(2, name);
1023                    pstmt.setString(3, value);
1024                    pstmt.executeUpdate();
1025                }
1026            } catch (SQLException JavaDoc sqle) {
1027                log.error("saveProperties",sqle);
1028            } finally {
1029                try {
1030                    pstmt.close();
1031                } catch (Exception JavaDoc e) {
1032                    log.error("",e);
1033                }
1034                try {
1035                    con.close();
1036                } catch (Exception JavaDoc e) {
1037                    log.error("",e);
1038                }
1039            }
1040        }
1041    }
1042
1043    /**
1044     * Loads filters from the database.
1045     */

1046    private void loadFiltersFromDb() {
1047        ArrayList JavaDoc newFilters = new ArrayList JavaDoc();
1048        Connection JavaDoc con = null;
1049        PreparedStatement JavaDoc pstmt = null;
1050        try {
1051            con = DbConnectionManager.getConnection();
1052            pstmt = con.prepareStatement(LOAD_FILTERS);
1053            pstmt.setInt(1, id);
1054            ResultSet JavaDoc rs = pstmt.executeQuery();
1055            while (rs.next()) {
1056                try {
1057                    ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(rs.getBinaryStream("filterObject"));
1058                    newFilters.add(in.readObject());
1059                } catch (ClassCastException JavaDoc cce) {
1060                    //ignore for now since the filter might be updated. we
1061
//need a solution for this. probably custom class loading
1062
//of filter classes to protect against failure like this.
1063
} catch (Exception JavaDoc e) {
1064                    log.error("",e);
1065                }
1066            }
1067        } catch (SQLException JavaDoc sqle) {
1068            log.error("",sqle);
1069        } finally {
1070            try {
1071                pstmt.close();
1072            } catch (Exception JavaDoc e) {
1073                log.error("",e);
1074            }
1075            try {
1076                con.close();
1077            } catch (Exception JavaDoc e) {
1078                log.error("",e);
1079            }
1080        }
1081        filters = new MessageFilter[newFilters.size()];
1082        for (int i = 0; i < filters.length; i++) {
1083            filters[i] = (MessageFilter) newFilters.get(i);
1084        }
1085        //Finally, save filters back to Db. Effectively, this deletes filters
1086
//from the database that failed to load. See note above.
1087
//saveFiltersToDb(); <<-- commenting out to try to fix filters bug.
1088
}
1089
1090    /**
1091     * Saves filters to the database. Filter saving works by serializing
1092     * each filter to a byte stream and then inserting that stream into
1093     * the database.
1094     */

1095    protected void saveFiltersToDb() {
1096        boolean abort = false;
1097        boolean supportsTransactions = false;
1098        synchronized (saveLock) {
1099            Connection JavaDoc con = null;
1100            PreparedStatement JavaDoc pstmt = null;
1101            try {
1102                con = DbConnectionManager.getConnection();
1103
1104                supportsTransactions = con.getMetaData().supportsTransactions();
1105                if (supportsTransactions) {
1106                    con.setAutoCommit(false);
1107                }
1108
1109                pstmt = con.prepareStatement(DELETE_FILTERS);
1110                pstmt.setInt(1, id);
1111                pstmt.execute();
1112                //Now insert new list of filters.
1113
pstmt.close();
1114                pstmt = con.prepareStatement(ADD_FILTER);
1115                for (int i = 0; i < filters.length; i++) {
1116                    try {
1117                        ByteArrayOutputStream JavaDoc byteOut = new ByteArrayOutputStream JavaDoc();
1118                        ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(byteOut);
1119                        out.writeObject(filters[i]);
1120                        pstmt.setInt(1, id);
1121                        pstmt.setInt(2, i);
1122                        pstmt.setBytes(3, byteOut.toByteArray());
1123                        pstmt.execute();
1124                    } catch (Exception JavaDoc e) {
1125                        abort = true;
1126                        log.error("",e);
1127                    }
1128                }
1129                pstmt.close();
1130            } catch (SQLException JavaDoc sqle) {
1131                abort = true;
1132                log.error("",sqle);
1133            } finally {
1134                try {
1135                    if (supportsTransactions) {
1136                        if (abort == true) {
1137                            con.rollback();
1138                        } else {
1139                            con.commit();
1140                        }
1141                    }
1142                } catch (Exception JavaDoc e) {
1143                    log.error("",e);
1144                }
1145                try {
1146                    if (supportsTransactions) {
1147                        con.setAutoCommit(true);
1148                    }
1149                } catch (Exception JavaDoc e) {
1150                    log.error("",e);
1151                }
1152                try {
1153                    con.close();
1154                } catch (Exception JavaDoc e) {
1155                    log.error("",e);
1156                }
1157            }
1158        }
1159    }
1160
1161    /**
1162     * Loads forum data from the database.
1163     */

1164    private void loadFromDb() throws ForumNotFoundException {
1165        Connection JavaDoc con = null;
1166        PreparedStatement JavaDoc pstmt = null;
1167        try {
1168            con = DbConnectionManager.getConnection();
1169            //See if we should load by forumID or by name
1170
if (id == -1) {
1171                pstmt = con.prepareStatement(LOAD_FORUM_BY_NAME);
1172                pstmt.setString(1, name);
1173            } else {
1174                pstmt = con.prepareStatement(LOAD_FORUM_BY_ID);
1175                pstmt.setInt(1, id);
1176            }
1177            ResultSet JavaDoc rs = pstmt.executeQuery();
1178            if (!rs.next()) {
1179                throw new ForumNotFoundException("Forum " + getID() + " could not be loaded from the database.");
1180            }
1181            id = rs.getInt("forumID");
1182            name = rs.getString("name");
1183            description = rs.getString("description");
1184            this.creationDate = new java.util.Date JavaDoc(Long.parseLong(rs.getString("creationDate").trim()));
1185            this.modifiedDate = new java.util.Date JavaDoc(Long.parseLong(rs.getString("modifiedDate").trim()));
1186            moderation = rs.getInt("moderated");
1187        } catch (SQLException JavaDoc sqle) {
1188            log.error("",sqle);
1189            throw new ForumNotFoundException("Forum " + getID() + " could not be loaded from the database.");
1190        } catch (NumberFormatException JavaDoc nfe) {
1191            log.error(
1192                "WARNING: In DbForum.loadFromDb() -- there "
1193                    + "was an error parsing the dates returned from the database. Ensure "
1194                    + "that they're being stored correctly.");
1195        } finally {
1196            try {
1197                pstmt.close();
1198            } catch (Exception JavaDoc e) {
1199                log.error("",e);
1200            }
1201            try {
1202                con.close();
1203            } catch (Exception JavaDoc e) {
1204                log.error("",e);
1205            }
1206        }
1207    }
1208
1209    /**
1210     * Inserts a new record into the database.
1211     */

1212    private void insertIntoDb() {
1213        Connection JavaDoc con = null;
1214        PreparedStatement JavaDoc pstmt = null;
1215        try {
1216            con = DbConnectionManager.getConnection();
1217            pstmt = con.prepareStatement(ADD_FORUM);
1218            pstmt.setInt(1, id);
1219            pstmt.setString(2, name);
1220            pstmt.setString(3, description);
1221            pstmt.setString(4, Long.toString(creationDate.getTime()));
1222            pstmt.setString(5, Long.toString(modifiedDate.getTime()));
1223            pstmt.setInt(6, moderation);
1224            pstmt.executeUpdate();
1225        } catch (SQLException JavaDoc sqle) {
1226            log.error("Error in DbForum:insertIntoDb()-" , sqle);
1227            
1228        } finally {
1229            try {
1230                pstmt.close();
1231            } catch (Exception JavaDoc e) {
1232                log.error("",e);
1233            }
1234            try {
1235                con.close();
1236            } catch (Exception JavaDoc e) {
1237                log.error("",e);
1238            }
1239        }
1240    }
1241
1242    /**
1243     * Saves forum data to the database.
1244     */

1245    private synchronized void saveToDb() {
1246        Connection JavaDoc con = null;
1247        PreparedStatement JavaDoc pstmt = null;
1248        try {
1249            con = DbConnectionManager.getConnection();
1250            pstmt = con.prepareStatement(SAVE_FORUM);
1251            pstmt.setString(1, name);
1252            pstmt.setString(2, description);
1253            pstmt.setString(3, Long.toString(creationDate.getTime()));
1254            pstmt.setString(4, Long.toString(modifiedDate.getTime()));
1255            pstmt.setInt(5, moderation);
1256            pstmt.setInt(6, id);
1257            pstmt.executeUpdate();
1258        } catch (SQLException JavaDoc sqle) {
1259            log.error("Error in DbForum:saveToDb()-" , sqle);
1260            
1261        } finally {
1262            try {
1263                pstmt.close();
1264            } catch (Exception JavaDoc e) {
1265                log.error("",e);
1266            }
1267            try {
1268                con.close();
1269            } catch (Exception JavaDoc e) {
1270                log.error("",e);
1271            }
1272        }
1273    }
1274}
1275
Popular Tags