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