KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > portlet > forums > interceptors > NotificationInterceptor


1 /*****************************************
2  * *
3  * JBoss Portal: The OpenSource Portal *
4  * *
5  * Forums JBoss Portlet *
6  * *
7  * Distributable under LGPL license. *
8  * See terms of license at gnu.org. *
9  * *
10  *****************************************/

11 package org.jboss.portlet.forums.interceptors;
12
13 import java.io.StringWriter JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.ResourceBundle JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import javax.naming.InitialContext JavaDoc;
20 import javax.naming.NamingException JavaDoc;
21 import javax.portlet.PortletURL;
22 import javax.transaction.Synchronization JavaDoc;
23 import javax.transaction.Transaction JavaDoc;
24 import javax.transaction.Status JavaDoc;
25 import javax.transaction.TransactionManager JavaDoc;
26
27 import org.jboss.portal.common.command.Command;
28 import org.jboss.portal.common.command.CommandException;
29 import org.jboss.portal.common.command.filter.AbstractCommandFilter;
30 import org.jboss.portal.common.command.result.Result;
31 import org.jboss.portal.common.transaction.Transactions;
32 import org.jboss.portal.core.model.User;
33 import org.jboss.portal.core.modules.MailModule;
34 import org.jboss.portal.core.modules.ModuleConstants;
35 import org.jboss.portal.core.security.AuthorizationRealm;
36 import org.jboss.portal.format.render.bbcodehtml.ToTextRenderer;
37 import org.jboss.portal.format.template.TemplateLoader;
38 import org.jboss.portlet.JBossActionRequest;
39 import org.jboss.portlet.JBossActionResponse;
40 import org.jboss.portlet.JBossPortlet;
41 import org.jboss.portlet.command.ActionCommand;
42 import org.jboss.portlet.forums.ForumsConstants;
43 import org.jboss.portlet.forums.ForumsModule;
44 import org.jboss.portlet.forums.ForumsPortlet;
45 import org.jboss.portlet.forums.commands.CommandConstants;
46 import org.jboss.portlet.forums.commands.post.NewTopicCommand;
47 import org.jboss.portlet.forums.commands.post.ReplyCommand;
48 import org.jboss.portlet.forums.commands.post.RepostCommand;
49 import org.jboss.portlet.forums.model.Category;
50 import org.jboss.portlet.forums.model.Forum;
51 import org.jboss.portlet.forums.model.ForumWatch;
52 import org.jboss.portlet.forums.model.Message;
53 import org.jboss.portlet.forums.model.Post;
54 import org.jboss.portlet.forums.model.Topic;
55 import org.jboss.portlet.forums.model.TopicWatch;
56
57 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
58 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
59
60 /**
61  * @author <a HREF="mailto:julien@jboss.org">Julien Viet</a>
62  * @version $Revision: 1.10 $
63  */

64 public class NotificationInterceptor
65    extends AbstractCommandFilter
66 {
67    private static final int MODE_POST = 0;
68    private static final int MODE_REPLY = 1;
69    private static final int MODE_REPOST = 2;
70
71    private ForumsModule forumsModule;
72    private TemplateLoader mailTemplates;
73    private String JavaDoc from;
74    private QueuedExecutor executor;
75    private MailModule mailModule;
76    private JBossPortlet portlet;
77    private TransactionManager JavaDoc tm;
78
79    public NotificationInterceptor(JBossPortlet portlet, ForumsModule module)
80    {
81       try
82       {
83          this.portlet = portlet;
84          this.forumsModule = module;
85          InitialContext JavaDoc ctx = new InitialContext JavaDoc();
86          mailModule = (MailModule)ctx.lookup(ModuleConstants.MAILMODULE_JNDINAME);
87          tm = (TransactionManager JavaDoc)ctx.lookup("java:TransactionManager");
88          executor = new QueuedExecutor(new LinkedQueue());
89       }
90       catch (NamingException JavaDoc e)
91       {
92          log.error("Cannot create notification interceptor", e);
93       }
94    }
95
96    public void stop()
97    {
98       executor.shutdownAfterProcessingCurrentTask();
99       executor = null;
100       portlet = null;
101       forumsModule = null;
102       mailModule = null;
103       tm = null;
104    }
105
106    public void setFrom(String JavaDoc from)
107    {
108       this.from = from;
109    }
110
111    public TemplateLoader getMailTemplates()
112    {
113       return mailTemplates;
114    }
115
116    public Result filter(Command cmd) throws CommandException
117    {
118       ActionCommand actionCmd = (ActionCommand)cmd;
119       JBossActionRequest request = actionCmd.getRequest();
120       JBossActionResponse response = actionCmd.getResponse();
121       Result result = null;
122       result = getNext().filter(cmd);
123       if (result.getType() == CommandConstants.TYPE_REPLY_POSTED)
124       {
125          Post post = ((ReplyCommand)cmd).newPost;
126          schedule(request, response, post, MODE_REPLY);
127       }
128       else if (result.getType() == CommandConstants.TYPE_NEW_TOPIC_POSTED)
129       {
130          Post post = ((NewTopicCommand)cmd).post;
131          schedule(request, response, post, MODE_POST);
132       }
133       else if (result.getType() == CommandConstants.TYPE_REPOSTED)
134       {
135          Post post = ((RepostCommand)cmd).post;
136          schedule(request, response, post, MODE_REPOST);
137       }
138       return result;
139    }
140
141    private void schedule(JBossActionRequest request, JBossActionResponse response, Post post, int mode)
142    {
143       try
144       {
145          // Compute info needed before sending the mail
146
Integer JavaDoc postID = post.getID();
147          PortletURL viewURL = response.createRenderURL();
148          viewURL.setParameter("p", postID.toString());
149          viewURL.setParameter("op", ForumsPortlet.OP_SHOWTOPIC);
150          String JavaDoc absViewURL = response.createAbsoluteURL(viewURL);
151          PortletURL replyURL = response.createActionURL();
152          replyURL.setParameter("op", "posting");
153          replyURL.setParameter("mode", "reply");
154          replyURL.setParameter("p", postID.toString());
155          String JavaDoc absReplyURL = response.createAbsoluteURL(replyURL);
156          AuthorizationRealm realm = request.getAuthorizationRealm();
157          ResourceBundle JavaDoc bundle = portlet.getResourceBundle(request.getLocale()); // Too bad for now we support notifications sent in the locale of the poster :-(
158

159          // Create task
160
NotificationTask task = new NotificationTask( tm, absViewURL, absReplyURL, postID, mode, realm, bundle);
161
162          // Register at the end of the current tx to broadcast notifications
163
Transaction JavaDoc tx = tm.getTransaction();
164          tx.registerSynchronization(task);
165       }
166       catch (Exception JavaDoc e)
167       {
168          e.printStackTrace();
169       }
170    }
171
172    private String JavaDoc getFrom(Post post)
173    {
174       StringBuffer JavaDoc fromBuf = null;
175       if ((post.getPoster().getUser().getGivenName() != null)
176          && (post.getPoster().getUser().getFamilyName() != null))
177       {
178          fromBuf = new StringBuffer JavaDoc(post.getPoster().getUser().getGivenName()
179             + " " + post.getPoster().getUser().getFamilyName() + " <");
180       }
181       else
182       {
183          fromBuf = new StringBuffer JavaDoc(post.getPoster().getUser().getUserName() + " <");
184       }
185       fromBuf.append(from + ">");
186       return fromBuf.toString();
187    }
188
189    /**
190     * The notification task.
191     */

192    class NotificationTask implements Transactions.Runnable, Synchronization JavaDoc
193    {
194
195       private final TransactionManager JavaDoc tm;
196       private final int mode;
197       private final Integer JavaDoc postID;
198       private final ResourceBundle JavaDoc bundle;
199       private final String JavaDoc viewURL;
200       private final String JavaDoc replyURL;
201       private final AuthorizationRealm realm;
202
203       NotificationTask(TransactionManager JavaDoc tm, String JavaDoc viewURL, String JavaDoc replyURL, final Integer JavaDoc postId, int mode, AuthorizationRealm realm, ResourceBundle JavaDoc bundle)
204       {
205          this.tm = tm;
206          this.mode = mode;
207          this.postID = postId;
208          this.viewURL = viewURL;
209          this.replyURL = replyURL;
210          this.bundle = bundle;
211          this.realm = realm;
212       }
213
214       public Object JavaDoc run() throws Exception JavaDoc
215       {
216          try
217          {
218             Post post = forumsModule.findPostByID(postID);
219             Forum forum = post.getTopic().getForum();
220             Category category = forum.getCategory();
221             Topic topic = post.getTopic();
222             Message message = post.getMessage();
223             String JavaDoc[] test = new String JavaDoc[]{category.getTitle(), forum.getName()};
224
225             // Hold the notified users to avoid duplicated
226
Set JavaDoc notifieds = new HashSet JavaDoc();
227
228             // If this is not an anonymous post, put the user in the notified list
229
// he won't be notified of his own action
230
User poster = post.getPoster().getUser();
231             if (poster != null)
232             {
233                notifieds.add(poster.getID());
234             }
235
236             char[] chars = message.getText().toCharArray();
237             StringWriter JavaDoc out = new StringWriter JavaDoc();
238             ToTextRenderer renderer = new ToTextRenderer();
239             renderer.setWriter(out);
240             renderer.render(chars, 0, chars.length);
241
242             String JavaDoc forumEmbededArgsSubject = "[" + forum.getName() + "] - "
243                + message.getSubject()
244                + (mode == MODE_REPOST ? " (Repost)" : "");
245
246             String JavaDoc forumEmbededArgsText = out.toString() + "\n\n"
247                + bundle.getString("EMAIL_VIEWORIGINAL") + " : "
248                + viewURL.toString() + "#" + post.getID() + "\n\n"
249                + bundle.getString("EMAIL_REPLY") + " : "
250                + replyURL.toString();
251
252             // Notify the forum watchers
253
for (Iterator JavaDoc i = forum.getWatches().iterator(); i.hasNext();)
254             {
255                try
256                {
257                   ForumWatch watch = (ForumWatch)i.next();
258                   User watcher = watch.getPoster().getUser();
259                   Integer JavaDoc watcherId = watcher.getID();
260                   if (!notifieds.contains(watcherId))
261                   {
262                      if (realm.hasPermission(watcher.getRoleNames(), test, "ReadForum"))
263                      {
264                         notifieds.add(watcherId);
265                         String JavaDoc subject = null;
266                         String JavaDoc text = null;
267                         if (watch.getMode() == ForumsConstants.WATCH_MODE_LINKED)
268                         {
269                         }
270                         else
271                         {
272                            subject = forumEmbededArgsSubject;
273                            text = forumEmbededArgsText;
274                         }
275                         mailModule.send(getFrom(post), watcher.getRealEmail(), subject, text);
276                      }
277                      else
278                      {
279                         // Not authorized anymore, we remove the watch
280
forumsModule.removeWatch(watch);
281                      }
282                   }
283                }
284                catch (Exception JavaDoc e)
285                {
286                   log.error("Cannot send an email notification", e);
287                }
288             }
289
290             if (mode == MODE_REPLY)
291             {
292                // Notify the reply watchers
293
for (Iterator JavaDoc i = topic.getWatches().iterator(); i.hasNext();)
294                {
295                   try
296                   {
297                      TopicWatch watch = (TopicWatch)i.next();
298                      User watcher = watch.getPoster().getUser();
299                      Integer JavaDoc watcherId = watcher.getID();
300                      if (!notifieds.contains(watcherId))
301                      {
302                         if (realm.hasPermission(watcher.getRoleNames(), test, "ReadForum"))
303                         {
304                            // Authorized
305
notifieds.add(watcherId);
306
307                            String JavaDoc mailBody = bundle.getString("TOPICWATCH_MAIL_1") + "\n\n" + post.getTopic().getSubject() + "\n\n"
308                               + bundle.getString("EMAIL_VIEWORIGINAL") + " : " + viewURL.toString() + "#" + post.getID() + "\n\n";
309
310                            mailModule.send((String JavaDoc)getFrom(post),
311                               watcher.getRealEmail(),
312                               "[" + forum.getName() + "] " + bundle.getString("Topic_reply_notification"),
313                               mailBody);
314                         }
315                         else
316                         {
317                            // Not authorized anymore, we remove the watch
318
forumsModule.removeWatch(watch);
319                         }
320                      }
321                   }
322                   catch (Exception JavaDoc e)
323                   {
324                      log.error("Cannot send email notification", e);
325                   }
326                }
327             }
328          }
329          catch (IllegalArgumentException JavaDoc e)
330          {
331             log.error("", e);
332          }
333
334          return null;
335       }
336
337       public void beforeCompletion()
338       {
339       }
340
341       public void afterCompletion(int status)
342       {
343          // When transaction succesfully commits broadcast the notification
344
if (status == Status.STATUS_COMMITTED)
345          {
346             try
347             {
348                // Do it asynch
349
executor.execute(new Runnable JavaDoc()
350                {
351                   public void run()
352                   {
353                      try
354                      {
355                         // Wrap with a tx
356
Transactions.required(tm, NotificationTask.this);
357                      }
358                      catch (Exception JavaDoc e)
359                      {
360                         log.error("Cannot broadcast nofication for post id", e);
361                      }
362                   }
363                });
364             }
365             catch (InterruptedException JavaDoc ignored)
366             {
367             }
368          }
369       }
370    }
371 }
Popular Tags