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, user.getUserId(), 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, user.getUserId(),
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, user.getUserId(),
539 ActionKeys.UPDATE_DISCUSSION);
540
541 return mbMessageLocalService.updateDiscussionMessage(
542 getUserId(), messageId, subject, body,
543 serviceContext.getWorkflowAction());
544 }
545
546 public MBMessage updateMessage(
547 long messageId, String subject, String body,
548 List<ObjectValuePair<String, byte[]>> files,
549 List<String> existingFiles, double priority, boolean allowPingbacks,
550 ServiceContext serviceContext)
551 throws PortalException, SystemException {
552
553 MBMessage message = mbMessageLocalService.getMessage(messageId);
554
555 MBMessagePermission.check(
556 getPermissionChecker(), messageId, ActionKeys.UPDATE);
557
558 if (lockLocalService.isLocked(
559 MBThread.class.getName(), message.getThreadId())) {
560
561 throw new LockedThreadException();
562 }
563
564 if (!MBCategoryPermission.contains(
565 getPermissionChecker(), message.getGroupId(),
566 message.getCategoryId(), ActionKeys.ADD_FILE)) {
567
568 files.clear();
569 }
570
571 if (!MBCategoryPermission.contains(
572 getPermissionChecker(), message.getGroupId(),
573 message.getCategoryId(), ActionKeys.UPDATE_THREAD_PRIORITY)) {
574
575 MBThread thread = mbThreadLocalService.getThread(
576 message.getThreadId());
577
578 priority = thread.getPriority();
579 }
580
581 return mbMessageLocalService.updateMessage(
582 getUserId(), messageId, subject, body, files, existingFiles,
583 priority, allowPingbacks, serviceContext);
584 }
585
586 protected void checkReplyToPermission(
587 long groupId, long categoryId, long parentMessageId)
588 throws PortalException, SystemException {
589
590 if (parentMessageId > 0) {
591 if (MBCategoryPermission.contains(
592 getPermissionChecker(), groupId, categoryId,
593 ActionKeys.ADD_MESSAGE)) {
594
595 return;
596 }
597
598 MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey(
599 parentMessageId);
600
601 if ((parentMessage == null) ||
602 !MBCategoryPermission.contains(
603 getPermissionChecker(), groupId, categoryId,
604 ActionKeys.REPLY_TO_MESSAGE)) {
605
606 throw new PrincipalException();
607 }
608 }
609 else {
610 MBCategoryPermission.check(
611 getPermissionChecker(), groupId, categoryId,
612 ActionKeys.ADD_MESSAGE);
613 }
614 }
615
616 protected String exportToRSS(
617 String name, String description, String type, double version,
618 String displayStyle, String feedURL, String entryURL,
619 List<MBMessage> messages, ThemeDisplay themeDisplay)
620 throws SystemException {
621
622 SyndFeed syndFeed = new SyndFeedImpl();
623
624 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
625 syndFeed.setTitle(name);
626 syndFeed.setLink(feedURL);
627 syndFeed.setDescription(description);
628
629 List<SyndEntry> entries = new ArrayList<SyndEntry>();
630
631 syndFeed.setEntries(entries);
632
633 Iterator<MBMessage> itr = messages.iterator();
634
635 while (itr.hasNext()) {
636 MBMessage message = itr.next();
637
638 String author = HtmlUtil.escape(
639 PortalUtil.getUserName(
640 message.getUserId(), message.getUserName()));
641
642 String value = null;
643
644 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
645 value = StringUtil.shorten(
646 HtmlUtil.extractText(message.getBody()),
647 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
648 }
649 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
650 value = StringPool.BLANK;
651 }
652 else {
653 value = BBCodeUtil.getHTML(message);
654
655 value = StringUtil.replace(
656 value,
657 new String[] {
658 "@theme_images_path@",
659 "href=\"/",
660 "src=\"/"
661 },
662 new String[] {
663 themeDisplay.getURLPortal() +
664 themeDisplay.getPathThemeImages(),
665 "href=\"" + themeDisplay.getURLPortal() + "/",
666 "src=\"" + themeDisplay.getURLPortal() + "/"
667 });
668 }
669
670 SyndEntry syndEntry = new SyndEntryImpl();
671
672 if (!message.isAnonymous()) {
673 syndEntry.setAuthor(author);
674 }
675
676 syndEntry.setTitle(message.getSubject());
677 syndEntry.setLink(
678 entryURL + "&messageId=" + message.getMessageId());
679 syndEntry.setUri(syndEntry.getLink());
680 syndEntry.setPublishedDate(message.getCreateDate());
681 syndEntry.setUpdatedDate(message.getModifiedDate());
682
683 SyndContent syndContent = new SyndContentImpl();
684
685 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
686 syndContent.setValue(value);
687
688 syndEntry.setDescription(syndContent);
689
690 entries.add(syndEntry);
691 }
692
693 try {
694 return RSSUtil.export(syndFeed);
695 }
696 catch (FeedException fe) {
697 throw new SystemException(fe);
698 }
699 }
700
701 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
702 PropsUtil.get(PropsKeys.MESSAGE_BOARDS_RSS_ABSTRACT_LENGTH));
703
704 }