001: /*
002: * NEMESIS-FORUM.
003: * Copyright (C) 2002 David Laurent(lithium2@free.fr). All rights reserved.
004: *
005: * Copyright (c) 2000 The Apache Software Foundation. All rights reserved.
006: *
007: * Copyright (C) 2001 Yasna.com. All rights reserved.
008: *
009: * Copyright (C) 2000 CoolServlets.com. All rights reserved.
010: *
011: * NEMESIS-FORUM. is free software; you can redistribute it and/or
012: * modify it under the terms of the Apache Software License, Version 1.1,
013: * or (at your option) any later version.
014: *
015: * NEMESIS-FORUM core framework, NEMESIS-FORUM backoffice, NEMESIS-FORUM frontoffice
016: * application are parts of NEMESIS-FORUM and are distributed under
017: * same terms of licence.
018: *
019: *
020: * NEMESIS-FORUM includes software developed by the Apache Software Foundation (http://www.apache.org/)
021: * and software developed by CoolServlets.com (http://www.coolservlets.com).
022: * and software developed by Yasna.com (http://www.yasna.com).
023: *
024: */
025: package org.nemesis.forum.impl;
026:
027: import java.sql.Connection;
028: import java.sql.PreparedStatement;
029: import java.sql.ResultSet;
030: import java.sql.SQLException;
031: import java.util.Date;
032: import java.util.Iterator;
033: import java.util.Vector;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.nemesis.forum.Forum;
038: import org.nemesis.forum.ForumThread;
039: import org.nemesis.forum.Message;
040: import org.nemesis.forum.TreeWalker;
041: import org.nemesis.forum.proxy.MessageProxy;
042: import org.nemesis.forum.event.ForumEvent;
043: import org.nemesis.forum.event.ForumListener;
044: import org.nemesis.forum.exception.ForumMessageNotFoundException;
045: import org.nemesis.forum.exception.ForumThreadNotFoundException;
046: import org.nemesis.forum.exception.UnauthorizedException;
047: import org.nemesis.forum.util.cache.CacheSizes;
048: import org.nemesis.forum.util.cache.Cacheable;
049: import org.nemesis.forum.util.jdbc.DbConnectionManager;
050:
051: /**
052: * Database implementation of the ForumThread interface.
053: *
054: * @see ForumThread
055: */
056: public class DbForumThread implements ForumThread, Cacheable {
057: static protected Log log = LogFactory.getLog(DbForumThread.class);
058: /** DATABASE QUERIES **/
059: private static final String MESSAGE_COUNT = "SELECT count(*) FROM yazdMessage WHERE threadID=?";
060: private static final String ADD_MESSAGE = "INSERT INTO yazdMessageTree(parentID,childID) VALUES(?,?)";
061: private static final String MOVE_MESSAGE = "UPDATE yazdMessageTree SET parentID=? WHERE childID=?";
062: private static final String CHANGE_MESSAGE_THREAD = "UPDATE yazdMessage SET threadID=? WHERE messageID=?";
063: private static final String UPDATE_THREAD_MODIFIED_DATE = "UPDATE yazdThread SET modifiedDate=? WHERE threadID=?";
064: private static final String DELETE_MESSAGE1 = "DELETE FROM yazdMessageTree WHERE childID=?";
065: private static final String DELETE_MESSAGE2 = "DELETE FROM yazdMessage WHERE messageID=?";
066: private static final String DELETE_MESSAGE_PROPERTIES = "DELETE FROM yazdMessageProp WHERE messageID=?";
067:
068: private static final String LOAD_THREAD = "SELECT rootMessageID, creationDate, modifiedDate,approved FROM yazdThread WHERE threadID=?";
069: private static final String INSERT_THREAD = "INSERT INTO yazdThread(threadID,forumID, rootMessageID,creationDate, modifiedDate,approved) VALUES(?,?,?,?,?,?)";
070: private static final String SAVE_THREAD = "UPDATE yazdThread SET rootMessageID=?, creationDate=?, modifiedDate=?, approved=? WHERE threadID=?";
071:
072: private static final String APPROVED_MESSAGE_COUNT = "SELECT count(*) FROM yazdMessage WHERE threadID=? AND approved=?";
073:
074: private int id = -1;
075: //Temporary object reference for when inserting new record.
076: private Message rootMessage;
077: private int rootMessageID;
078: private java.util.Date creationDate;
079: private java.util.Date modifiedDate;
080: private boolean approved;
081:
082: /**
083: * Indicates if the object is ready to be saved or not. An object is not
084: * ready to be saved if it has just been created and has not yet been added
085: * to its container. For example, a message added to a thread, etc.
086: */
087: private boolean isReadyToSave = false;
088:
089: /**
090: * The forum allows us access to the message filters.
091: */
092: private DbForum forum;
093:
094: /**
095: * The factory provides services such as db connections and logging.
096: */
097: private DbForumFactory factory;
098:
099: /**
100: * Creates a new DbForumThread. The supplied message object is used to
101: * derive the name of the thread (subject of message), as well as the
102: * creation date and modified date of thread.
103: *
104: * @param rootMessage the root message of the thread.
105: */
106: protected DbForumThread(Message rootMessage, boolean approved,
107: DbForum forum, DbForumFactory factory)
108: throws UnauthorizedException {
109: this .id = DbSequenceManager.nextID("ForumThread");
110: this .forum = forum;
111: this .factory = factory;
112: this .rootMessage = rootMessage;
113: this .rootMessageID = rootMessage.getID();
114: //Set the creation and modified dates to be the same as those of
115: //root message.
116: long rootMessageTime = rootMessage.getCreationDate().getTime();
117: this .creationDate = new java.util.Date(rootMessageTime);
118: this .modifiedDate = new java.util.Date(rootMessageTime);
119: this .approved = approved;
120: }
121:
122: /**
123: * Loads a DbForumThread from the database based on its id.
124: *
125: * @param id in unique id of the ForumThread to load.
126: * @param forum the Forum that the thread belongs to.
127: * @param factory a ForumFactory to use for loading.
128: */
129: protected DbForumThread(int id, DbForum forum,
130: DbForumFactory factory) throws ForumThreadNotFoundException {
131: this .id = id;
132: this .forum = forum;
133: this .factory = factory;
134: loadFromDb();
135: isReadyToSave = true;
136: }
137:
138: //FROM THE FORUMMESSAGE INTERFACE//
139: public boolean isApproved() {
140: return approved;
141: }
142:
143: public void setApproved(boolean approved)
144: throws UnauthorizedException {
145: this .approved = approved;
146: //Only save to the db if the object is read
147: if (!isReadyToSave) {
148: return;
149: }
150: saveToDb();
151: }
152:
153: public int getID() {
154: return id;
155: }
156:
157: public String getName() {
158: return getRootMessage().getSubject();
159: }
160:
161: public java.util.Date getCreationDate() {
162: return creationDate;
163: }
164:
165: public void setCreationDate(java.util.Date creationDate)
166: throws UnauthorizedException {
167: this .creationDate = creationDate;
168: //Only save to the db if the object is ready
169: if (!isReadyToSave) {
170: return;
171: }
172: saveToDb();
173: }
174:
175: public java.util.Date getModifiedDate() {
176: return modifiedDate;
177: }
178:
179: public void setModifiedDate(java.util.Date modifiedDate)
180: throws UnauthorizedException {
181: this .modifiedDate = modifiedDate;
182: //Only save to the db if the object is ready
183: if (!isReadyToSave) {
184: return;
185: }
186: saveToDb();
187: }
188:
189: public Forum getForum() {
190: return forum;
191: }
192:
193: public Message getMessage(int messageID)
194: throws ForumMessageNotFoundException {
195: Message message = factory.getMessage(messageID);
196:
197: //Apply filters to message.
198: message = forum.applyFilters(message);
199: return message;
200: }
201:
202: public Message getRootMessage() {
203: try {
204: return getMessage(rootMessageID);
205: } catch (ForumMessageNotFoundException e) {
206: log.error("Could not load root message with id "
207: + rootMessageID);
208: return null;
209: }
210: /*DbForumMessage message = (DbForumMessage)factory.cacheManager.get(
211: DbCacheManager.MESSAGE_CACHE,
212: new Integer(rootMessageID)
213: );
214: if (message == null) {
215: //Load and add to cache
216: try {
217: message = new DbForumMessage(rootMessageID, factory);
218: factory.cacheManager.add(DbCacheManager.MESSAGE_CACHE, new Integer(rootMessageID), message);
219: }
220: catch (ForumMessageNotFoundException e) {
221: log("Could not load root message with id " + rootMessageID);
222:
223: }
224: }
225: return message;
226: */
227: }
228:
229: public int getMessageCount() {
230: int messageCount = 0;
231: Connection con = null;
232: PreparedStatement pstmt = null;
233: try {
234: con = DbConnectionManager.getConnection();
235: pstmt = con.prepareStatement(MESSAGE_COUNT);
236: pstmt.setInt(1, id);
237: ResultSet rs = pstmt.executeQuery();
238: rs.next();
239: messageCount = rs.getInt(1);
240: } catch (SQLException sqle) {
241: log.error("DbForumThread:getMessageCount() failed: ", sqle);
242: } finally {
243: try {
244: pstmt.close();
245: } catch (Exception e) {
246: log.error("", e);
247: }
248: try {
249: con.close();
250: } catch (Exception e) {
251: log.error("", e);
252: }
253: }
254: return messageCount;
255: }
256:
257: public int getMessageCount(boolean approved) {
258: int messageCount = 0;
259: Connection con = null;
260: PreparedStatement pstmt = null;
261: try {
262: con = DbConnectionManager.getConnection();
263: pstmt = con.prepareStatement(APPROVED_MESSAGE_COUNT);
264: pstmt.setInt(1, id);
265: pstmt.setInt(2, approved ? 1 : 0);
266: ResultSet rs = pstmt.executeQuery();
267: rs.next();
268: messageCount = rs.getInt(1);
269: } catch (SQLException sqle) {
270: log.error("DbForumThread:getMessageCount() failed: ", sqle);
271: } finally {
272: try {
273: pstmt.close();
274: } catch (Exception e) {
275: log.error("", e);
276: }
277: try {
278: con.close();
279: } catch (Exception e) {
280: log.error("", e);
281: }
282: }
283: return messageCount;
284: }
285:
286: public void addMessage(Message parentMessage, Message newMessage) {
287: boolean abortTransaction = false;
288: boolean supportsTransactions = false;
289: //Add message to db
290: Connection con = null;
291: PreparedStatement pstmt = null;
292: try {
293: con = DbConnectionManager.getConnection();
294: supportsTransactions = con.getMetaData()
295: .supportsTransactions();
296: if (supportsTransactions) {
297: con.setAutoCommit(false);
298: }
299:
300: //Now, insert the message into the database.
301: //Now, insert the message into the database.
302: ((MessageProxy) newMessage).insertIntoDb(con, this );
303:
304: pstmt = con.prepareStatement(ADD_MESSAGE);
305: pstmt.setInt(1, parentMessage.getID());
306: pstmt.setInt(2, newMessage.getID());
307: pstmt.executeUpdate();
308: pstmt.close();
309: } catch (Exception e) {
310: log.error("", e);
311: abortTransaction = true;
312: return;
313: } finally {
314: try {
315: if (supportsTransactions) {
316: if (abortTransaction == true) {
317: con.rollback();
318: } else {
319: con.commit();
320: }
321: }
322: } catch (Exception e) {
323: log.error("", e);
324: }
325: try {
326: if (supportsTransactions) {
327: con.setAutoCommit(true);
328: }
329: con.close();
330: } catch (Exception e) {
331: log.error("", e);
332: }
333: }
334:
335: //Added new message, so update the modified date of this thread
336: updateModifiedDate(newMessage.getModifiedDate());
337: //Also, update the modified date of the forum
338: DbForum dbForum = (DbForum) factory.cacheManager.get(
339: DbCacheManager.FORUM_CACHE, new Integer(forum.getID()));
340: if (dbForum != null) {
341: dbForum.updateModifiedDate(modifiedDate);
342: } else {
343: forum.updateModifiedDate(modifiedDate);
344: }
345: }
346:
347: public void deleteMessage(Message message)
348: throws UnauthorizedException {
349: //Skip null messages or the case that we're already deleting the thread.
350: if (message == null) {
351: return;
352: }
353: //If the message does not belong to this thread, don't perform delete.
354: if (message.getForumThread().getID() != this .id) {
355: throw new IllegalArgumentException("Message "
356: + message.getID()
357: + " could not be deleted. It belongs to thread "
358: + message.getForumThread().getID()
359: + ", and not thread " + this .id + ".");
360: }
361:
362: Connection con = null;
363: PreparedStatement pstmt = null;
364: try {
365: con = DbConnectionManager.getConnection();
366: //Delete the message from the parent/child table
367: pstmt = con.prepareStatement(DELETE_MESSAGE1);
368: pstmt.setInt(1, message.getID());
369: pstmt.execute();
370: } catch (SQLException sqle) {
371: log.error("Error in DbForumThread:deleteMessage()-", sqle);
372: } finally {
373: try {
374: pstmt.close();
375: } catch (Exception e) {
376: log.error("", e);
377: }
378: try {
379: con.close();
380: } catch (Exception e) {
381: log.error("", e);
382: }
383: }
384:
385: //Recursively delete all children
386: TreeWalker walker = treeWalker();
387: int childCount = walker.getChildCount(message);
388: for (int i = childCount - 1; i >= 0; i--) {
389: Message childMessage = walker.getChild(message, i);
390: if (childMessage == null) {
391: log.error("child message was null -- index " + i);
392: }
393: deleteMessage(childMessage);
394: }
395:
396: try {
397: //Delete the actual message.
398: con = DbConnectionManager.getConnection();
399: pstmt = con.prepareStatement(DELETE_MESSAGE2);
400: pstmt.setInt(1, message.getID());
401: pstmt.execute();
402: pstmt.close();
403:
404: //Delete any message properties.
405: pstmt = con.prepareStatement(DELETE_MESSAGE_PROPERTIES);
406: pstmt.setInt(1, message.getID());
407: pstmt.execute();
408:
409: ForumEvent event = new ForumEvent(message);
410: for (int i = 0; i < listeners.size(); i++) {
411: ((ForumListener) listeners.get(i)).objectDeleted(event);
412: }
413:
414: } catch (SQLException sqle) {
415: log.error("Error in DbForumThread:deleteMessage()-", sqle);
416: } finally {
417: try {
418: pstmt.close();
419: } catch (Exception e) {
420: log.error("", e);
421: }
422: try {
423: con.close();
424: } catch (Exception e) {
425: log.error("", e);
426: }
427: }
428:
429: //Now, delete from the cache.
430: factory.getCacheManager().remove(DbCacheManager.MESSAGE_CACHE,
431: new Integer(message.getID()));
432:
433: //Finally, delete it from the search index
434: //factory.getSearchIndexer().removeFromIndex(message);
435:
436: //Now, make sure that the message being deleted isn't the root message
437: //of this thread. If it is, the whole thread should just be deleted.
438: if (message.getID() == this .rootMessageID) {
439: forum.deleteThreadRecord(this .id);
440: }
441: }
442:
443: public void moveMessage(Message message, ForumThread newThread,
444: Message parentMessage) throws UnauthorizedException,
445: IllegalArgumentException {
446: if (message.getForumThread().getID() != this .id
447: || parentMessage.getForumThread().getID() != newThread
448: .getID()) {
449: throw new IllegalArgumentException(
450: "The messages and threads did not match.");
451: }
452:
453: // Save the mesageID of message to move
454: int messageID = message.getID();
455: // Original message thread rootMessageID
456: int oldRootMessageID = getRootMessage().getID();
457:
458: // Move the children of this message to the new thread
459: TreeWalker walker = treeWalker();
460: int childCount = walker.getChildCount(message);
461: for (int i = 0; i < childCount; i++) {
462: Message childMessage = walker.getChild(message, i);
463: changeMessageThread(childMessage, newThread);
464: }
465:
466: //Move the message to the new thread.
467: changeMessageThread(message, newThread);
468:
469: //Make message a child of parentMessage
470: Connection con = null;
471: PreparedStatement pstmt = null;
472: try {
473: con = DbConnectionManager.getConnection();
474:
475: if (oldRootMessageID != messageID) {
476: pstmt = con.prepareStatement(MOVE_MESSAGE);
477: pstmt.setInt(1, parentMessage.getID());
478: pstmt.setInt(2, messageID);
479: } else {
480: pstmt = con.prepareStatement(ADD_MESSAGE);
481: pstmt.setInt(1, parentMessage.getID());
482: pstmt.setInt(2, messageID);
483: }
484:
485: pstmt.executeUpdate();
486: pstmt.close();
487: } catch (SQLException sqle) {
488: log.error("Error in DbForumThread:moveMessage()-", sqle);
489: } finally {
490: try {
491: pstmt.close();
492: } catch (Exception e) {
493: log.error("", e);
494: }
495: try {
496: con.close();
497: } catch (Exception e) {
498: log.error("", e);
499: }
500: }
501:
502: //Update the modified date of newThread
503: Date now = new Date();
504: newThread.setModifiedDate(now);
505: //Update the modified date of newThread forum
506: newThread.getForum().setModifiedDate(now);
507:
508: //Thread has been modified, invalidate the cache
509: DbCacheManager cacheManager = factory.getCacheManager();
510: Integer key = new Integer(this .id);
511: cacheManager.remove(DbCacheManager.THREAD_CACHE, key);
512:
513: //If we moved the root message of this thread, the thread should be
514: //deleted. Normally, deleting a thread will delete all of it's messages.
515: //However, we've already adjusted the thread/message relationship at the
516: //SQL level and removed the thread from cache. That should mean we're safe.
517: if (getRootMessage().getID() == messageID) {
518: //rootMessage = null;
519: this .getForum().deleteThread(this );
520: }
521: }
522:
523: public TreeWalker treeWalker() {
524: return new DbTreeWalker(this , factory);
525: }
526:
527: public TreeWalker treeWalker(boolean approved) {
528: return new DbTreeWalker(approved, this , factory);
529: }
530:
531: public Iterator messages() {
532: return new DbThreadIterator(this );
533: }
534:
535: public Iterator messages(int startIndex, int numResults) {
536: return new DbThreadIterator(this , startIndex, numResults);
537: }
538:
539: public Iterator messages(boolean approved) {
540: return new DbThreadIterator(approved, this );
541: }
542:
543: public Iterator messages(boolean approved, int startIndex,
544: int numResults) {
545: return new DbThreadIterator(approved, this , startIndex,
546: numResults);
547: }
548:
549: public boolean hasPermission(int type) {
550: return true;
551: }
552:
553: //FROM THE CACHEABLE INTERFACE//
554:
555: public int getSize() {
556: //Approximate the size of the object in bytes by calculating the size
557: //of each field.
558: int size = 0;
559: size += CacheSizes.sizeOfObject(); //overhead of object
560: size += CacheSizes.sizeOfInt(); //id
561: size += CacheSizes.sizeOfDate(); //creation date
562: size += CacheSizes.sizeOfDate(); //modified date
563: size += CacheSizes.sizeOfBoolean(); //approved
564: size += CacheSizes.sizeOfObject(); //ref to rootMessage
565: size += CacheSizes.sizeOfObject(); //ref to forum
566: size += CacheSizes.sizeOfObject(); //ref to factory
567: size += CacheSizes.sizeOfBoolean(); //ready save var
568: size += CacheSizes.sizeOfBoolean(); //deleting var
569:
570: return size;
571: }
572:
573: //OTHER METHODS//
574:
575: /**
576: * Converts the object to a String by returning the name of the thread.
577: * This functionality is primarily for Java applications that might be
578: * accessing objects through a GUI.
579: */
580: public String toString() {
581: return getName();
582: }
583:
584: public int hashCode() {
585: return id;
586: }
587:
588: public boolean equals(Object object) {
589: if (this == object) {
590: return true;
591: }
592: if (object != null && object instanceof DbForumThread) {
593: return id == ((DbForumThread) object).getID();
594: } else {
595: return false;
596: }
597: }
598:
599: /**
600: * Updates the modified date but doesn't require a security check since
601: * it is a protected method.
602: */
603: protected void updateModifiedDate(java.util.Date modifiedDate) {
604: this .modifiedDate = modifiedDate;
605: Connection con = null;
606: PreparedStatement pstmt = null;
607: try {
608: con = DbConnectionManager.getConnection();
609: pstmt = con.prepareStatement(UPDATE_THREAD_MODIFIED_DATE);
610: pstmt.setString(1, "" + modifiedDate.getTime());
611: pstmt.setInt(2, id);
612: pstmt.executeUpdate();
613: } catch (SQLException sqle) {
614: log.error("Error in DbForumThread:updateModifiedDate()-",
615: sqle);
616:
617: } finally {
618: try {
619: pstmt.close();
620: } catch (Exception e) {
621: log.error("", e);
622: }
623: try {
624: con.close();
625: } catch (Exception e) {
626: log.error("", e);
627: }
628: }
629: }
630:
631: /**
632: * Moves a message to a new thread by modifying the message table threadID
633: * column.
634: *
635: * @param message the message to move.
636: * @param newThread the thread to move the message to.
637: */
638: private void changeMessageThread(Message message,
639: ForumThread newThread) throws UnauthorizedException {
640: //Remove message from the search index
641: //factory.getSearchIndexer().removeFromIndex(message);
642:
643: //Remove message from cache.
644: DbCacheManager cacheManager = factory.getCacheManager();
645: Integer key = new Integer(message.getID());
646: cacheManager.remove(DbCacheManager.MESSAGE_CACHE, key);
647:
648: Connection con = null;
649: PreparedStatement pstmt = null;
650: try {
651: con = DbConnectionManager.getConnection();
652: pstmt = con.prepareStatement(CHANGE_MESSAGE_THREAD);
653: pstmt.setInt(1, newThread.getID());
654: pstmt.setInt(2, key.intValue());
655: pstmt.executeUpdate();
656: } catch (SQLException sqle) {
657: log.error("", sqle);
658: }
659:
660: // Add message back to search index and update modified date
661: try {
662: Message movedMessage = newThread.getMessage(key.intValue());
663: //factory.getSearchIndexer().addToIndex(movedMessage);
664: movedMessage.setModifiedDate(new Date());
665: } catch (ForumMessageNotFoundException e) {
666: log.error("Error in DbForumThread:changeMessageThread()-"
667: + "messageID=" + key.intValue() + "newThreadID="
668: + newThread.getID());
669: } finally {
670: try {
671: pstmt.close();
672: } catch (Exception e) {
673: log.error("", e);
674: }
675: try {
676: con.close();
677: } catch (Exception e) {
678: log.error("", e);
679: }
680: }
681: }
682:
683: /**
684: * Loads a ForumThread from the database.
685: */
686: private void loadFromDb() throws ForumThreadNotFoundException {
687: Connection con = null;
688: PreparedStatement pstmt = null;
689: try {
690: con = DbConnectionManager.getConnection();
691: pstmt = con.prepareStatement(LOAD_THREAD);
692: pstmt.setInt(1, id);
693: ResultSet rs = pstmt.executeQuery();
694: if (!rs.next()) {
695: throw new ForumThreadNotFoundException("Thread " + id
696: + " could not be loaded from the database.");
697: }
698: //try {
699: rootMessageID = rs.getInt("rootMessageID");
700: //}
701: //catch (ForumMessageNotFoundException fmnfe) {
702: // log("Error: could not load root message of thread "
703: // + id + ". The database record could be corrupt.");
704: //
705: //}
706: creationDate = new java.util.Date(Long.parseLong(rs
707: .getString("creationDate").trim()));
708: modifiedDate = new java.util.Date(Long.parseLong(rs
709: .getString("modifiedDate").trim()));
710: approved = rs.getInt("approved") == 1;
711: pstmt.close();
712: } catch (SQLException sqle) {
713: log.error("load", sqle);
714: throw new ForumThreadNotFoundException("Thread " + id
715: + " could not be loaded from the database.");
716: } catch (NumberFormatException nfe) {
717: log
718: .error("WARNING: In DbForumThread.loadFromDb() -- there "
719: + "was an error parsing the dates returned from the database. Ensure "
720: + "that they're being stored correctly.");
721: } finally {
722: try {
723: con.close();
724: } catch (Exception e) {
725: log.error("", e);
726: }
727: }
728: }
729:
730: /**
731: * Inserts a new forum thread into the database. A connection object must
732: * be passed in. The connection must be open when passed in, and will
733: * remain open when passed back. This method allows us to make insertions
734: * be transactional.
735: *
736: * @param con an open Connection used to insert the thread to the db.
737: */
738: public void insertIntoDb(Connection con) throws SQLException {
739: PreparedStatement pstmt = con.prepareStatement(INSERT_THREAD);
740: pstmt.setInt(1, id);
741: pstmt.setInt(2, forum.getID());
742: pstmt.setInt(3, rootMessageID);
743: pstmt.setString(4, Long.toString(creationDate.getTime()));
744: pstmt.setString(5, Long.toString(modifiedDate.getTime()));
745: pstmt.setInt(6, approved ? 1 : 0);
746: pstmt.executeUpdate();
747: pstmt.close();
748:
749: //Now, insert the message into the database.
750:
751: ((MessageProxy) rootMessage).insertIntoDb(con, this );
752:
753: //since we're done inserting the object to the database, it is ready
754: //for future insertions.
755: isReadyToSave = true;
756: }
757:
758: /**
759: * Saves the ForumThread to the database.
760: */
761: private synchronized void saveToDb() {
762: Connection con = null;
763: PreparedStatement pstmt = null;
764: try {
765: con = DbConnectionManager.getConnection();
766: pstmt = con.prepareStatement(SAVE_THREAD);
767: pstmt.setInt(1, rootMessageID);
768: pstmt.setString(2, Long.toString(creationDate.getTime()));
769: pstmt.setString(3, Long.toString(modifiedDate.getTime()));
770: pstmt.setInt(4, approved ? 1 : 0);
771: pstmt.setInt(5, id);
772: pstmt.executeUpdate();
773: } catch (SQLException sqle) {
774: log.error("Error in DbForumThread:saveToDb()-", sqle);
775: } finally {
776: try {
777: pstmt.close();
778: } catch (Exception e) {
779: log.error("", e);
780: }
781: try {
782: con.close();
783: } catch (Exception e) {
784: log.error("", e);
785: }
786: }
787: }
788:
789: // gestion des évenements
790: private static Vector listeners = new Vector();
791:
792: public static void addListener(ForumListener listener) {
793: listeners.add(listener);
794: }
795:
796: public static void removeListener(ForumListener listener) {
797: listeners.remove(listener);
798: }
799: }
|