1
14
15 package com.liferay.portlet.messageboards.service.impl;
16
17 import com.liferay.portal.kernel.exception.PortalException;
18 import com.liferay.portal.kernel.exception.SystemException;
19 import com.liferay.portal.kernel.util.GetterUtil;
20 import com.liferay.portal.kernel.util.HtmlUtil;
21 import com.liferay.portal.kernel.util.ObjectValuePair;
22 import com.liferay.portal.kernel.util.PropsKeys;
23 import com.liferay.portal.kernel.util.StringPool;
24 import com.liferay.portal.kernel.util.StringUtil;
25 import com.liferay.portal.kernel.workflow.WorkflowConstants;
26 import com.liferay.portal.model.Company;
27 import com.liferay.portal.model.Group;
28 import com.liferay.portal.model.User;
29 import com.liferay.portal.security.auth.PrincipalException;
30 import com.liferay.portal.security.permission.ActionKeys;
31 import com.liferay.portal.service.ServiceContext;
32 import com.liferay.portal.theme.ThemeDisplay;
33 import com.liferay.portal.util.PortalUtil;
34 import com.liferay.portal.util.PropsUtil;
35 import com.liferay.portlet.messageboards.LockedThreadException;
36 import com.liferay.portlet.messageboards.NoSuchCategoryException;
37 import com.liferay.portlet.messageboards.model.MBCategory;
38 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
39 import com.liferay.portlet.messageboards.model.MBMessage;
40 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
41 import com.liferay.portlet.messageboards.model.MBThread;
42 import com.liferay.portlet.messageboards.model.MBThreadConstants;
43 import com.liferay.portlet.messageboards.service.base.MBMessageServiceBaseImpl;
44 import com.liferay.portlet.messageboards.service.permission.MBCategoryPermission;
45 import com.liferay.portlet.messageboards.service.permission.MBDiscussionPermission;
46 import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
47 import com.liferay.portlet.messageboards.util.BBCodeUtil;
48 import com.liferay.portlet.messageboards.util.comparator.MessageCreateDateComparator;
49 import com.liferay.util.RSSUtil;
50
51 import com.sun.syndication.feed.synd.SyndContent;
52 import com.sun.syndication.feed.synd.SyndContentImpl;
53 import com.sun.syndication.feed.synd.SyndEntry;
54 import com.sun.syndication.feed.synd.SyndEntryImpl;
55 import com.sun.syndication.feed.synd.SyndFeed;
56 import com.sun.syndication.feed.synd.SyndFeedImpl;
57 import com.sun.syndication.io.FeedException;
58
59 import java.util.ArrayList;
60 import java.util.Iterator;
61 import java.util.List;
62
63
69 public class MBMessageServiceImpl extends MBMessageServiceBaseImpl {
70
71 public MBMessage addDiscussionMessage(
72 long groupId, String className, long classPK,
73 String permissionClassName, long permissionClassPK, long threadId,
74 long parentMessageId, String subject, String body,
75 ServiceContext serviceContext)
76 throws PortalException, SystemException {
77
78 User user = getGuestOrUser();
79
80 MBDiscussionPermission.check(
81 getPermissionChecker(), user.getCompanyId(),
82 serviceContext.getScopeGroupId(), permissionClassName,
83 permissionClassPK, user.getUserId(), ActionKeys.ADD_DISCUSSION);
84
85 return mbMessageLocalService.addDiscussionMessage(
86 null, user.getUserId(), null, groupId, className, classPK, threadId,
87 parentMessageId, subject, body, serviceContext);
88 }
89
90 public MBMessage addMessage(
91 long groupId, long categoryId, String subject, String body,
92 List<ObjectValuePair<String, byte[]>> files,
93 boolean anonymous, double priority, boolean allowPingbacks,
94 ServiceContext serviceContext)
95 throws PortalException, SystemException {
96
97 MBCategoryPermission.check(
98 getPermissionChecker(), groupId, categoryId,
99 ActionKeys.ADD_MESSAGE);
100
101 if (!MBCategoryPermission.contains(
102 getPermissionChecker(), groupId, categoryId,
103 ActionKeys.ADD_FILE)) {
104
105 files.clear();
106 }
107
108 if (!MBCategoryPermission.contains(
109 getPermissionChecker(), groupId, categoryId,
110 ActionKeys.UPDATE_THREAD_PRIORITY)) {
111
112 priority = MBThreadConstants.PRIORITY_NOT_GIVEN;
113 }
114
115 return mbMessageLocalService.addMessage(
116 getGuestOrUserId(), null, groupId, categoryId, subject, body, files,
117 anonymous, priority, allowPingbacks, serviceContext);
118 }
119
120 public MBMessage addMessage(
121 long groupId, long categoryId, long threadId, long parentMessageId,
122 String subject, String body,
123 List<ObjectValuePair<String, byte[]>> files, boolean anonymous,
124 double priority, boolean allowPingbacks,
125 ServiceContext serviceContext)
126 throws PortalException, SystemException {
127
128 checkReplyToPermission(groupId, categoryId, parentMessageId);
129
130 if (lockLocalService.isLocked(
131 MBThread.class.getName(), threadId)) {
132
133 throw new LockedThreadException();
134 }
135
136 if (!MBCategoryPermission.contains(
137 getPermissionChecker(), groupId, categoryId,
138 ActionKeys.ADD_FILE)) {
139
140 files.clear();
141 }
142
143 if (!MBCategoryPermission.contains(
144 getPermissionChecker(), groupId, categoryId,
145 ActionKeys.UPDATE_THREAD_PRIORITY)) {
146
147 priority = MBThreadConstants.PRIORITY_NOT_GIVEN;
148 }
149
150 return mbMessageLocalService.addMessage(
151 getGuestOrUserId(), null, groupId, categoryId, threadId,
152 parentMessageId, subject, body, files, anonymous, priority,
153 allowPingbacks, serviceContext);
154 }
155
156 public void deleteDiscussionMessage(
157 long groupId, String className, long classPK,
158 String permissionClassName, long permissionClassPK, long messageId)
159 throws PortalException, SystemException {
160
161 User user = getUser();
162
163 MBDiscussionPermission.check(
164 getPermissionChecker(), user.getCompanyId(), groupId,
165 permissionClassName, permissionClassPK, messageId, user.getUserId(),
166 ActionKeys.DELETE_DISCUSSION);
167
168 mbMessageLocalService.deleteDiscussionMessage(messageId);
169 }
170
171 public void deleteMessage(long messageId)
172 throws PortalException, SystemException {
173
174 MBMessagePermission.check(
175 getPermissionChecker(), messageId, ActionKeys.DELETE);
176
177 mbMessageLocalService.deleteMessage(messageId);
178 }
179
180 public List<MBMessage> getCategoryMessages(
181 long groupId, long categoryId, int status, int start, int end)
182 throws PortalException, SystemException {
183
184 List<MBMessage> messages = new ArrayList<MBMessage>();
185
186 Iterator<MBMessage> itr = mbMessageLocalService.getCategoryMessages(
187 groupId, categoryId, status, start, end).iterator();
188
189 while (itr.hasNext()) {
190 MBMessage message = itr.next();
191
192 if (MBMessagePermission.contains(
193 getPermissionChecker(), message, ActionKeys.VIEW)) {
194
195 messages.add(message);
196 }
197 }
198
199 return messages;
200 }
201
202 public int getCategoryMessagesCount(
203 long groupId, long categoryId, int status)
204 throws SystemException {
205
206 return mbMessageLocalService.getCategoryMessagesCount(
207 groupId, categoryId, status);
208 }
209
210 public String getCategoryMessagesRSS(
211 long groupId, long categoryId, int status, int max, String type,
212 double version, String displayStyle, String feedURL,
213 String entryURL, ThemeDisplay themeDisplay)
214 throws PortalException, SystemException {
215
216 String name = StringPool.BLANK;
217 String description = StringPool.BLANK;
218
219 try {
220 MBCategory category = mbCategoryLocalService.getCategory(
221 categoryId);
222
223 groupId = category.getGroupId();
224 name = category.getName();
225 description = category.getDescription();
226 }
227 catch (NoSuchCategoryException nsce) {
228 Group group = groupLocalService.getGroup(categoryId);
229
230 groupId = group.getGroupId();
231 categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
232 name = group.getName();
233 description = group.getDescription();
234 }
235
236 List<MBMessage> messages = new ArrayList<MBMessage>();
237
238 int lastIntervalStart = 0;
239 boolean listNotExhausted = true;
240 MessageCreateDateComparator comparator =
241 new MessageCreateDateComparator(false);
242
243 while ((messages.size() < max) && listNotExhausted) {
244 List<MBMessage> messageList =
245 mbMessageLocalService.getCategoryMessages(
246 groupId, categoryId, status, lastIntervalStart,
247 lastIntervalStart + max, comparator);
248
249 Iterator<MBMessage> itr = messageList.iterator();
250
251 lastIntervalStart += max;
252 listNotExhausted = (messageList.size() == max);
253
254 while (itr.hasNext() && (messages.size() < max)) {
255 MBMessage message = itr.next();
256
257 if (MBMessagePermission.contains(
258 getPermissionChecker(), message, ActionKeys.VIEW)) {
259
260 messages.add(message);
261 }
262 }
263 }
264
265 return exportToRSS(
266 name, description, type, version, displayStyle, feedURL, entryURL,
267 messages, themeDisplay);
268 }
269
270 public String getCompanyMessagesRSS(
271 long companyId, int status, int max, String type, double version,
272 String displayStyle, String feedURL, String entryURL,
273 ThemeDisplay themeDisplay)
274 throws PortalException, SystemException {
275
276 Company company = companyPersistence.findByPrimaryKey(companyId);
277
278 String name = company.getName();
279 String description = company.getName();
280
281 List<MBMessage> messages = new ArrayList<MBMessage>();
282
283 int lastIntervalStart = 0;
284 boolean listNotExhausted = true;
285 MessageCreateDateComparator comparator =
286 new MessageCreateDateComparator(false);
287
288 while ((messages.size() < max) && listNotExhausted) {
289 List<MBMessage> messageList =
290 mbMessageLocalService.getCompanyMessages(
291 companyId, status, lastIntervalStart,
292 lastIntervalStart + max, comparator);
293
294 Iterator<MBMessage> itr = messageList.iterator();
295
296 lastIntervalStart += max;
297 listNotExhausted = (messageList.size() == max);
298
299 while (itr.hasNext() && (messages.size() < max)) {
300 MBMessage message = itr.next();
301
302 if (MBMessagePermission.contains(
303 getPermissionChecker(), message, ActionKeys.VIEW)) {
304
305 messages.add(message);
306 }
307 }
308 }
309
310 return exportToRSS(
311 name, description, type, version, displayStyle, feedURL, entryURL,
312 messages, themeDisplay);
313 }
314
315 public String getGroupMessagesRSS(
316 long groupId, int status, int max, String type, double version,
317 String displayStyle, String feedURL, String entryURL,
318 ThemeDisplay themeDisplay)
319 throws PortalException, SystemException {
320
321 String name = StringPool.BLANK;
322 String description = StringPool.BLANK;
323
324 List<MBMessage> messages = new ArrayList<MBMessage>();
325
326 int lastIntervalStart = 0;
327 boolean listNotExhausted = true;
328 MessageCreateDateComparator comparator =
329 new MessageCreateDateComparator(false);
330
331 while ((messages.size() < max) && listNotExhausted) {
332 List<MBMessage> messageList =
333 mbMessageLocalService.getGroupMessages(
334 groupId, status, lastIntervalStart, lastIntervalStart + max,
335 comparator);
336
337 Iterator<MBMessage> itr = messageList.iterator();
338
339 lastIntervalStart += max;
340 listNotExhausted = (messageList.size() == max);
341
342 while (itr.hasNext() && (messages.size() < max)) {
343 MBMessage message = itr.next();
344
345 if (MBMessagePermission.contains(
346 getPermissionChecker(), message, ActionKeys.VIEW)) {
347
348 messages.add(message);
349 }
350 }
351 }
352
353 if (messages.size() > 0) {
354 MBMessage message = messages.get(messages.size() - 1);
355
356 name = message.getSubject();
357 description = message.getSubject();
358 }
359
360 return exportToRSS(
361 name, description, type, version, displayStyle, feedURL, entryURL,
362 messages, themeDisplay);
363 }
364
365 public String getGroupMessagesRSS(
366 long groupId, long userId, int status, int max, String type,
367 double version, String displayStyle, String feedURL,
368 String entryURL, ThemeDisplay themeDisplay)
369 throws PortalException, SystemException {
370
371 String name = StringPool.BLANK;
372 String description = StringPool.BLANK;
373
374 List<MBMessage> messages = new ArrayList<MBMessage>();
375
376 int lastIntervalStart = 0;
377 boolean listNotExhausted = true;
378 MessageCreateDateComparator comparator =
379 new MessageCreateDateComparator(false);
380
381 while ((messages.size() < max) && listNotExhausted) {
382 List<MBMessage> messageList =
383 mbMessageLocalService.getGroupMessages(
384 groupId, userId, status, lastIntervalStart,
385 lastIntervalStart + max, comparator);
386
387 Iterator<MBMessage> itr = messageList.iterator();
388
389 lastIntervalStart += max;
390 listNotExhausted = (messageList.size() == max);
391
392 while (itr.hasNext() && (messages.size() < max)) {
393 MBMessage message = itr.next();
394
395 if (MBMessagePermission.contains(
396 getPermissionChecker(), message, ActionKeys.VIEW)) {
397
398 messages.add(message);
399 }
400 }
401 }
402
403 if (messages.size() > 0) {
404 MBMessage message = messages.get(messages.size() - 1);
405
406 name = message.getSubject();
407 description = message.getSubject();
408 }
409
410 return exportToRSS(
411 name, description, type, version, displayStyle, feedURL, entryURL,
412 messages, themeDisplay);
413 }
414
415 public MBMessage getMessage(long messageId)
416 throws PortalException, SystemException {
417
418 MBMessagePermission.check(
419 getPermissionChecker(), messageId, ActionKeys.VIEW);
420
421 return mbMessageLocalService.getMessage(messageId);
422 }
423
424 public MBMessageDisplay getMessageDisplay(
425 long messageId, int status, String threadView,
426 boolean includePrevAndNext)
427 throws PortalException, SystemException {
428
429 MBMessagePermission.check(
430 getPermissionChecker(), messageId, ActionKeys.VIEW);
431
432 return mbMessageLocalService.getMessageDisplay(
433 messageId, status, threadView, includePrevAndNext);
434 }
435
436 public List<MBMessage> getThreadMessages(
437 long groupId, long categoryId, long threadId, int status, int start,
438 int end)
439 throws SystemException {
440
441 if (status == WorkflowConstants.STATUS_ANY) {
442 return mbMessagePersistence.filterFindByG_C_T(
443 groupId, categoryId, threadId, start, end);
444 }
445 else {
446 return mbMessagePersistence.filterFindByG_C_T_S(
447 groupId, categoryId, threadId, status, start, end);
448 }
449 }
450
451 public int getThreadMessagesCount(
452 long groupId, long categoryId, long threadId, int status)
453 throws SystemException {
454
455 if (status == WorkflowConstants.STATUS_ANY) {
456 return mbMessagePersistence.filterCountByG_C_T(
457 groupId, categoryId, threadId);
458 }
459 else {
460 return mbMessagePersistence.filterCountByG_C_T_S(
461 groupId, categoryId, threadId, status);
462 }
463 }
464
465 public String getThreadMessagesRSS(
466 long threadId, int status, int max, String type, double version,
467 String displayStyle, String feedURL, String entryURL,
468 ThemeDisplay themeDisplay)
469 throws PortalException, SystemException {
470
471 String name = StringPool.BLANK;
472 String description = StringPool.BLANK;
473
474 List<MBMessage> messages = new ArrayList<MBMessage>();
475
476 MBThread thread = mbThreadLocalService.getThread(threadId);
477
478 if (MBMessagePermission.contains(
479 getPermissionChecker(), thread.getRootMessageId(),
480 ActionKeys.VIEW)) {
481
482 MessageCreateDateComparator comparator =
483 new MessageCreateDateComparator(false);
484
485 Iterator<MBMessage> itr = mbMessageLocalService.getThreadMessages(
486 threadId, status, comparator).iterator();
487
488 while (itr.hasNext() && (messages.size() < max)) {
489 MBMessage message = itr.next();
490
491 if (MBMessagePermission.contains(
492 getPermissionChecker(), message, ActionKeys.VIEW)) {
493
494 messages.add(message);
495 }
496 }
497
498 if (messages.size() > 0) {
499 MBMessage message = messages.get(messages.size() - 1);
500
501 name = message.getSubject();
502 description = message.getSubject();
503 }
504 }
505
506 return exportToRSS(
507 name, description, type, version, displayStyle, feedURL, entryURL,
508 messages, themeDisplay);
509 }
510
511 public void subscribeMessage(long messageId)
512 throws PortalException, SystemException {
513
514 MBMessagePermission.check(
515 getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
516
517 mbMessageLocalService.subscribeMessage(getUserId(), messageId);
518 }
519
520 public void unsubscribeMessage(long messageId)
521 throws PortalException, SystemException {
522
523 MBMessagePermission.check(
524 getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
525
526 mbMessageLocalService.unsubscribeMessage(getUserId(), messageId);
527 }
528
529 public MBMessage updateDiscussionMessage(
530 String className, long classPK, String permissionClassName,
531 long permissionClassPK, long messageId, String subject, String body,
532 ServiceContext serviceContext)
533 throws PortalException, SystemException {
534
535 User user = getUser();
536
537 MBDiscussionPermission.check(
538 getPermissionChecker(), user.getCompanyId(),
539 serviceContext.getScopeGroupId(), permissionClassName,
540 permissionClassPK, messageId, user.getUserId(),
541 ActionKeys.UPDATE_DISCUSSION);
542
543 return mbMessageLocalService.updateDiscussionMessage(
544 getUserId(), messageId, subject, body,
545 serviceContext.getWorkflowAction());
546 }
547
548 public MBMessage updateMessage(
549 long messageId, String subject, String body,
550 List<ObjectValuePair<String, byte[]>> files,
551 List<String> existingFiles, double priority, boolean allowPingbacks,
552 ServiceContext serviceContext)
553 throws PortalException, SystemException {
554
555 MBMessage message = mbMessageLocalService.getMessage(messageId);
556
557 MBMessagePermission.check(
558 getPermissionChecker(), messageId, ActionKeys.UPDATE);
559
560 if (lockLocalService.isLocked(
561 MBThread.class.getName(), message.getThreadId())) {
562
563 throw new LockedThreadException();
564 }
565
566 if (!MBCategoryPermission.contains(
567 getPermissionChecker(), message.getGroupId(),
568 message.getCategoryId(), ActionKeys.ADD_FILE)) {
569
570 files.clear();
571 }
572
573 if (!MBCategoryPermission.contains(
574 getPermissionChecker(), message.getGroupId(),
575 message.getCategoryId(), ActionKeys.UPDATE_THREAD_PRIORITY)) {
576
577 MBThread thread = mbThreadLocalService.getThread(
578 message.getThreadId());
579
580 priority = thread.getPriority();
581 }
582
583 return mbMessageLocalService.updateMessage(
584 getUserId(), messageId, subject, body, files, existingFiles,
585 priority, allowPingbacks, serviceContext);
586 }
587
588 protected void checkReplyToPermission(
589 long groupId, long categoryId, long parentMessageId)
590 throws PortalException, SystemException {
591
592 if (parentMessageId > 0) {
593 if (MBCategoryPermission.contains(
594 getPermissionChecker(), groupId, categoryId,
595 ActionKeys.ADD_MESSAGE)) {
596
597 return;
598 }
599
600 MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey(
601 parentMessageId);
602
603 if ((parentMessage == null) ||
604 !MBCategoryPermission.contains(
605 getPermissionChecker(), groupId, categoryId,
606 ActionKeys.REPLY_TO_MESSAGE)) {
607
608 throw new PrincipalException();
609 }
610 }
611 else {
612 MBCategoryPermission.check(
613 getPermissionChecker(), groupId, categoryId,
614 ActionKeys.ADD_MESSAGE);
615 }
616 }
617
618 protected String exportToRSS(
619 String name, String description, String type, double version,
620 String displayStyle, String feedURL, String entryURL,
621 List<MBMessage> messages, ThemeDisplay themeDisplay)
622 throws SystemException {
623
624 SyndFeed syndFeed = new SyndFeedImpl();
625
626 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
627 syndFeed.setTitle(name);
628 syndFeed.setLink(feedURL);
629 syndFeed.setDescription(description);
630
631 List<SyndEntry> entries = new ArrayList<SyndEntry>();
632
633 syndFeed.setEntries(entries);
634
635 Iterator<MBMessage> itr = messages.iterator();
636
637 while (itr.hasNext()) {
638 MBMessage message = itr.next();
639
640 String author = HtmlUtil.escape(
641 PortalUtil.getUserName(
642 message.getUserId(), message.getUserName()));
643
644 String value = null;
645
646 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
647 value = StringUtil.shorten(
648 HtmlUtil.extractText(message.getBody()),
649 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
650 }
651 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
652 value = StringPool.BLANK;
653 }
654 else {
655 value = BBCodeUtil.getHTML(message);
656
657 value = StringUtil.replace(
658 value,
659 new String[] {
660 "@theme_images_path@",
661 "href=\"/",
662 "src=\"/"
663 },
664 new String[] {
665 themeDisplay.getURLPortal() +
666 themeDisplay.getPathThemeImages(),
667 "href=\"" + themeDisplay.getURLPortal() + "/",
668 "src=\"" + themeDisplay.getURLPortal() + "/"
669 });
670 }
671
672 SyndEntry syndEntry = new SyndEntryImpl();
673
674 if (!message.isAnonymous()) {
675 syndEntry.setAuthor(author);
676 }
677
678 syndEntry.setTitle(message.getSubject());
679 syndEntry.setLink(
680 entryURL + "&messageId=" + message.getMessageId());
681 syndEntry.setUri(syndEntry.getLink());
682 syndEntry.setPublishedDate(message.getCreateDate());
683 syndEntry.setUpdatedDate(message.getModifiedDate());
684
685 SyndContent syndContent = new SyndContentImpl();
686
687 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
688 syndContent.setValue(value);
689
690 syndEntry.setDescription(syndContent);
691
692 entries.add(syndEntry);
693 }
694
695 try {
696 return RSSUtil.export(syndFeed);
697 }
698 catch (FeedException fe) {
699 throw new SystemException(fe);
700 }
701 }
702
703 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
704 PropsUtil.get(PropsKeys.MESSAGE_BOARDS_RSS_ABSTRACT_LENGTH));
705
706 }