KickJava   Java API By Example, From Geeks To Geeks.

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


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.sql.Connection JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.ResultSet JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.Vector JavaDoc;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.nemesis.forum.Forum;
41 import org.nemesis.forum.ForumFactory;
42 import org.nemesis.forum.ForumThread;
43 import org.nemesis.forum.Message;
44 import org.nemesis.forum.User;
45 import org.nemesis.forum.event.ForumEvent;
46 import org.nemesis.forum.event.ForumListener;
47 import org.nemesis.forum.exception.ForumMessageNotFoundException;
48 import org.nemesis.forum.exception.UnauthorizedException;
49 import org.nemesis.forum.exception.UserNotFoundException;
50 import org.nemesis.forum.util.StringUtils;
51 import org.nemesis.forum.util.cache.CacheSizes;
52 import org.nemesis.forum.util.cache.Cacheable;
53 import org.nemesis.forum.util.jdbc.DbConnectionManager;
54 /**
55  * Database implementation of the ForumMessage interface. It stores messages
56  * in the Message database table, and message properties in JiveMessageProp
57  * table.
58  */

59 public final class DbForumMessage implements Message, Cacheable {
60 static protected Log log = LogFactory.getLog(DbForumMessage.class);
61     /** DATABASE QUERIES **/
62     private static final String JavaDoc LOAD_PROPERTIES = "SELECT name, propValue FROM yazdMessageProp WHERE messageID=?";
63     private static final String JavaDoc DELETE_PROPERTIES = "DELETE FROM yazdMessageProp WHERE messageID=?";
64     private static final String JavaDoc INSERT_PROPERTY = "INSERT INTO yazdMessageProp(messageID,name,propValue) VALUES(?,?,?)";
65     
66     private static final String JavaDoc LOAD_MESSAGE = "SELECT userID, creationDate, modifiedDate, subject, body, threadID,approved FROM " + "yazdMessage WHERE messageID=?";
67     private static final String JavaDoc INSERT_MESSAGE ="INSERT INTO yazdMessage(messageID, threadID,creationDate,modifiedDate,userID," + "subject,body,approved) VALUES(?,?,?,?,?,?,?,?)";
68     private static final String JavaDoc SAVE_MESSAGE = "UPDATE yazdMessage SET userID=?, subject=?, body=?, creationDate=?, modifiedDate=?,approved=? " + "WHERE messageID=?";
69     
70     private static final String JavaDoc GET_FORUM_BY_THREAD = "SELECT forumID FROM yazdThread where threadID=?";
71
72     private int id = -1;
73     private java.util.Date JavaDoc creationDate;
74     private java.util.Date JavaDoc modifiedDate;
75     private String JavaDoc subject = "";
76     private String JavaDoc body = "";
77     private int userID;
78     private int threadID;
79     private Map JavaDoc properties;
80     private Object JavaDoc propertyLock = new Object JavaDoc();
81     private ForumFactory factory;
82     private ForumThread thread = null;
83     protected boolean approved;//ICI
84

85     /**
86      * Indicates if the object is ready to be saved or not. An object is not
87      * ready to be saved if it has just been created and has not yet been added
88      * to its container. For example, a message added to a thread, etc.
89      */

90     private boolean isReadyToSave = false;
91
92     /**
93      * Creates a new DbForumMessage object.
94      */

95     protected DbForumMessage(User user,boolean approved,ForumFactory factory) {
96         this.id = DbSequenceManager.nextID("ForumMessage");
97         long now = System.currentTimeMillis();
98         creationDate = new java.util.Date JavaDoc(now);
99         modifiedDate = new java.util.Date JavaDoc(now);
100         this.userID = user.getID();
101         this.factory = factory;
102         this.approved=approved;
103         properties = Collections.synchronizedMap(new HashMap JavaDoc());
104     }
105
106     /**
107      * Loads the specified DbForumMessage by its message id.
108      */

109     protected DbForumMessage(int id ,DbForumFactory factory) throws ForumMessageNotFoundException {
110         this.id = id;
111         this.factory = factory;
112         loadFromDb();
113         loadProperties();
114         isReadyToSave = true;
115     }
116
117     //FROM THE FORUMMESSAGE INTERFACE//
118
public boolean isApproved(){
119         return approved;
120     }
121     
122     public void setApproved(boolean approved) throws UnauthorizedException{
123         this.approved = approved;
124         //Only save to the db if the object is read
125
if (!isReadyToSave) {
126             return;
127         }
128         saveToDb();
129     }
130     
131     public int getID() {
132         return id;
133     }
134
135     public java.util.Date JavaDoc getCreationDate() {
136         return creationDate;
137     }
138
139     public void setCreationDate(java.util.Date JavaDoc creationDate) throws UnauthorizedException {
140         this.creationDate = creationDate;
141         //Only save to the db if the object is read
142
if (!isReadyToSave) {
143             return;
144         }
145         saveToDb();
146     }
147
148     public java.util.Date JavaDoc getModifiedDate() {
149         return modifiedDate;
150     }
151
152     public void setModifiedDate(java.util.Date JavaDoc modifiedDate) throws UnauthorizedException {
153         this.modifiedDate = modifiedDate;
154         //Only save to the db if the object is read
155
if (!isReadyToSave) {
156             return;
157         }
158         saveToDb();
159     }
160
161     public String JavaDoc getSubject() {
162         return subject;
163     }
164
165     public String JavaDoc getUnfilteredSubject() {
166         return subject;
167     }
168
169     public void setSubject(String JavaDoc subject) throws UnauthorizedException {
170         this.subject = subject;
171         //Only save to the db if the object is read
172
if (!isReadyToSave) {
173             return;
174         }
175         //Update modifiedDate to the current time.
176
modifiedDate.setTime(System.currentTimeMillis());
177         saveToDb();
178     }
179
180     public String JavaDoc getBody() {
181         return body;
182     }
183
184     public String JavaDoc getUnfilteredBody() {
185         return body;
186     }
187
188     public void setBody(String JavaDoc body) throws UnauthorizedException {
189         this.body = body;
190         //Only save to the db if the object is read
191
if (!isReadyToSave) {
192             return;
193         }
194         //Update modifiedDate to the current time.
195
modifiedDate.setTime(System.currentTimeMillis());
196         saveToDb();
197     }
198
199     public User getUser() {
200         User user = null;
201         try {
202             if (userID == -1) {
203                 user = factory.getProfileManager().getAnonymousUser();
204             } else {
205                 user = factory.getProfileManager().getUser(userID);
206             }
207         } catch (UserNotFoundException unfe) {
208             log.error("",unfe);
209         }
210         return user;
211     }
212
213     public String JavaDoc getProperty(String JavaDoc name) {
214         //For security reasons, pass through the HTML filter.
215
return StringUtils.escapeHTMLTags((String JavaDoc) properties.get(name));
216     }
217
218     public String JavaDoc getUnfilteredProperty(String JavaDoc name) {
219         return (String JavaDoc) properties.get(name);
220     }
221
222     public void setProperty(String JavaDoc name, String JavaDoc value) {
223         properties.put(name, value);
224         //Only save to the db if the object is read
225
if (!isReadyToSave) {
226             return;
227         }
228         saveProperties();
229     }
230
231     public Iterator JavaDoc propertyNames() {
232         return Collections.unmodifiableSet(properties.keySet()).iterator();
233     }
234
235     public boolean isAnonymous() {
236         return (userID == -1);
237     }
238
239     public ForumThread getForumThread() {
240         if (thread != null) {
241             return thread;
242         }
243         //Load the thread since this is the first time the method has been
244
//called.
245
else {
246             //First, we need a handle on the parent Forum object based
247
//on the threadID.
248
int forumID = -1;
249             Connection JavaDoc con = null;
250             PreparedStatement JavaDoc pstmt = null;
251             try {
252                 con = DbConnectionManager.getConnection();
253                 pstmt = con.prepareStatement(GET_FORUM_BY_THREAD);
254                 pstmt.setInt(1, threadID);
255                 ResultSet JavaDoc rs = pstmt.executeQuery();
256                 if (rs.next()) {
257                     forumID = rs.getInt("forumID");
258                 }
259             } catch (SQLException JavaDoc sqle) {
260                 log.error("",sqle);
261             } finally {
262                 try {
263                     pstmt.close();
264                 } catch (Exception JavaDoc e) {
265                     log.error("",e);
266                 }
267                 try {
268                     con.close();
269                 } catch (Exception JavaDoc e) {
270                     log.error("",e);
271                 }
272             }
273             //If the forumID for the message is less than 1, we have problems.
274
//Print a warning and return null
275
if (forumID < 1) {
276                 log.error(
277                     "WARNING: forumID of "
278                         + forumID
279                         + " found for message "
280                         + id
281                         + " in DbForumMessage.getForumThread()."
282                         + " You may wish to delete the message from your database.");
283                 return null;
284             }
285
286             Forum forum = null;
287             ForumThread thread = null;
288             try {
289                 forum = factory.getForum(forumID);
290                 //Now, get the thread
291
thread = forum.getThread(threadID);
292             } catch (Exception JavaDoc e) {
293                 log.error("",e);
294                 return null;
295             }
296             this.thread = thread;
297             return thread;
298         }
299     }
300
301     public boolean hasPermission(int type) {
302         return true;
303     }
304
305     //FROM CACHEABLE INTERFACE//
306

307     public int getSize() {
308         //Approximate the size of the object in bytes by calculating the size
309
//of each field.
310
int size = 0;
311         size += CacheSizes.sizeOfObject(); //overhead of object
312
size += CacheSizes.sizeOfInt(); //id
313
size += CacheSizes.sizeOfString(subject); //subject
314
size += CacheSizes.sizeOfString(body); //body
315
size += CacheSizes.sizeOfDate(); //creation date
316
size += CacheSizes.sizeOfDate(); //modified date
317
size += CacheSizes.sizeOfInt(); //userID
318
size += CacheSizes.sizeOfInt(); //threadID
319
size += CacheSizes.sizeOfMap(properties); //map object
320
size += CacheSizes.sizeOfObject(); //property lock
321
size += CacheSizes.sizeOfObject(); //ref to factory
322

323         return size;
324     }
325
326     //OTHER METHODS//
327

328     /**
329      * Returns a String representation of the message object using the subject.
330      *
331      * @return a String representation of the ForumMessage object.
332      */

333     public String JavaDoc toString() {
334         return subject;
335     }
336     
337
338
339
340     public int hashCode() {
341         return id;
342     }
343
344     public boolean equals(Object JavaDoc object) {
345         if (this == object) {
346             return true;
347         }
348         if (object != null && object instanceof DbForumMessage) {
349             return id == ((DbForumMessage) object).getID();
350         } else {
351             return false;
352         }
353     }
354
355     /**
356      * Loads message properties from the database.
357      */

358     private void loadProperties() {
359         synchronized (propertyLock) {
360             Properties JavaDoc newProps = new Properties JavaDoc();
361             Connection JavaDoc con = null;
362             PreparedStatement JavaDoc pstmt = null;
363             try {
364                 con = DbConnectionManager.getConnection();
365                 pstmt = con.prepareStatement(LOAD_PROPERTIES);
366                 pstmt.setInt(1, id);
367                 ResultSet JavaDoc rs = pstmt.executeQuery();
368                 while (rs.next()) {
369                     String JavaDoc name = rs.getString("name");
370                     String JavaDoc value = rs.getString("propValue");
371                     newProps.put(name, value);
372                 }
373             } catch (SQLException JavaDoc sqle) {
374                 log.error("Error in DbForumMessage:loadProperties():" , sqle);
375                 
376             } finally {
377                 try {
378                     pstmt.close();
379                 } catch (Exception JavaDoc e) {
380                     log.error("",e);
381                 }
382                 try {
383                     con.close();
384                 } catch (Exception JavaDoc e) {
385                     log.error("",e);
386                 }
387             }
388             this.properties = newProps;
389         }
390     }
391
392     /**
393      * Saves message properties to the database.
394      */

395     private void saveProperties() {
396         synchronized (propertyLock) {
397             Connection JavaDoc con = null;
398             PreparedStatement JavaDoc pstmt = null;
399             try {
400                 con = DbConnectionManager.getConnection();
401                 //Delete all old values.
402
pstmt = con.prepareStatement(DELETE_PROPERTIES);
403                 pstmt.setInt(1, id);
404                 pstmt.execute();
405                 pstmt.close();
406                 //Now insert new values.
407
pstmt = con.prepareStatement(INSERT_PROPERTY);
408                 Iterator JavaDoc iter = properties.keySet().iterator();
409                 while (iter.hasNext()) {
410                     String JavaDoc name = (String JavaDoc) iter.next();
411                     String JavaDoc value = (String JavaDoc) properties.get(name);
412                     pstmt.setInt(1, id);
413                     pstmt.setString(2, name);
414                     pstmt.setString(3, value);
415                     pstmt.executeUpdate();
416                 }
417             } catch (SQLException JavaDoc sqle) {
418                 log.error("",sqle);
419             } finally {
420                 try {
421                     pstmt.close();
422                 } catch (Exception JavaDoc e) {
423                     log.error("",e);
424                 }
425                 try {
426                     con.close();
427                 } catch (Exception JavaDoc e) {
428                     log.error("",e);
429                 }
430             }
431         }
432     }
433
434     /**
435      * Loads message and user data from the database.
436      */

437     private void loadFromDb() throws ForumMessageNotFoundException {
438         // Based on the id in the object, get the message data from the database.
439
Connection JavaDoc con = null;
440         PreparedStatement JavaDoc pstmt = null;
441         try {
442             con = DbConnectionManager.getConnection();
443             pstmt = con.prepareStatement(LOAD_MESSAGE);
444             pstmt.setInt(1, id);
445             ResultSet JavaDoc rs = pstmt.executeQuery();
446             if (!rs.next()) {
447                 throw new ForumMessageNotFoundException("Message " + id + " could not be loaded from the database.");
448             }
449             //Get the query results. We use int indexes into the ResultSet
450
//because it is slightly faster. Care should be taken so that the
451
//SQL query is not modified without modifying these indexes.
452
this.userID = rs.getInt(1);
453             //We trim() the dates before trying to parse them because some
454
//databases pad with extra characters when returning the data.
455
this.creationDate = new java.util.Date JavaDoc(Long.parseLong(rs.getString(2).trim()));
456             this.modifiedDate = new java.util.Date JavaDoc(Long.parseLong(rs.getString(3).trim()));
457             this.subject = rs.getString(4);
458             this.body = rs.getString(5);
459             this.threadID = rs.getInt(6);
460             this.approved= rs.getInt(7)==1;
461         } catch (SQLException JavaDoc sqle) {
462             throw new ForumMessageNotFoundException("Message of id " + id + " was not found in the database.");
463         } catch (NumberFormatException JavaDoc nfe) {
464             log.error(
465                 "WARNING: In DbForumMessage.loadFromDb() -- there "
466                     + "was an error parsing the dates returned from the database. Ensure "
467                     + "that they're being stored correctly.");
468         } finally {
469             try {
470                 pstmt.close();
471             } catch (Exception JavaDoc e) {
472                 log.error("",e);
473             }
474             try {
475                 con.close();
476             } catch (Exception JavaDoc e) {
477                 log.error("",e);
478             }
479         }
480     }
481
482     /**
483      * Inserts a new message into the database. A connection object must
484      * be passed in. The connection must be open when passed in, and will
485      * remain open when passed back. This method allows us to make insertions
486      * be transactional.
487      *
488      * @param con an open Connection used to insert the thread to the db.
489      * @param thread the ForumThread the message is being added to.
490      */

491     public void insertIntoDb(Connection JavaDoc con, ForumThread thread) throws SQLException JavaDoc {
492         //Set the message threadID to the thread that the message is being
493
//added to.
494
this.threadID = thread.getID();
495         PreparedStatement JavaDoc pstmt = con.prepareStatement(INSERT_MESSAGE);
496         pstmt.setInt(1, id);
497         pstmt.setInt(2, threadID);
498         pstmt.setString(3, Long.toString(creationDate.getTime()));
499         pstmt.setString(4, Long.toString(modifiedDate.getTime()));
500         pstmt.setInt(5, userID);
501         pstmt.setString(6, subject);
502         pstmt.setString(7, body);
503         pstmt.setInt(8, approved?1:0 );
504         pstmt.executeUpdate();
505         pstmt.close();
506
507         //We're done inserting the message, so now save any extended
508
//properties to the database.
509
saveProperties();
510         
511         ForumEvent event = new ForumEvent(this);
512         for (int i = 0; i < listeners.size(); i++) {
513             ((ForumListener) listeners.get(i)).objectCreated(event);
514         }
515         
516         
517         //since we're done inserting the object to the database, it is ready
518
//for future insertions.
519
isReadyToSave = true;
520     }
521
522     /**
523      * Saves message data to the database.
524      */

525     private synchronized void saveToDb() {
526         Connection JavaDoc con = null;
527         PreparedStatement JavaDoc pstmt = null;
528         try {
529             con = DbConnectionManager.getConnection();
530             pstmt = con.prepareStatement(SAVE_MESSAGE);
531             pstmt.setInt(1, userID);
532             pstmt.setString(2, subject);
533             pstmt.setString(3, body);
534             pstmt.setString(4, Long.toString(creationDate.getTime()));
535             pstmt.setString(5, Long.toString(modifiedDate.getTime()));
536             pstmt.setInt(6, approved?1:0);
537             pstmt.setInt(7, id);
538             pstmt.executeUpdate();
539             
540             
541             ForumEvent event = new ForumEvent(this);
542             for (int i = 0; i < listeners.size(); i++) {
543                 ((ForumListener) listeners.get(i)).objectModified(event);
544             }
545             
546             
547         } catch (SQLException JavaDoc sqle) {
548             log.error("SQLException in DbForumMessage:saveToDb()- " + sqle);
549             
550         } finally {
551             try {
552                 pstmt.close();
553             } catch (Exception JavaDoc e) {
554                 log.error("",e);
555             }
556             try {
557                 con.close();
558             } catch (Exception JavaDoc e) {
559                 log.error("",e);
560             }
561         }
562     }
563     
564     
565
566     // gestion des évenements
567
private static Vector JavaDoc listeners = new Vector JavaDoc();
568
569     public static void addListener(ForumListener listener) {
570         listeners.add(listener);
571     }
572
573     public static void removeListener(ForumListener listener) {
574         listeners.remove(listener);
575     }
576 }
577
Popular Tags