001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.parsers.bbcode.BBCodeTranslatorUtil;
020    import com.liferay.portal.kernel.util.HtmlUtil;
021    import com.liferay.portal.kernel.util.ObjectValuePair;
022    import com.liferay.portal.kernel.util.ParamUtil;
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.PropsValues;
035    import com.liferay.portlet.messageboards.LockedThreadException;
036    import com.liferay.portlet.messageboards.model.MBCategory;
037    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
038    import com.liferay.portlet.messageboards.model.MBMessage;
039    import com.liferay.portlet.messageboards.model.MBMessageConstants;
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.MBUtil;
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.feed.synd.SyndLink;
058    import com.sun.syndication.feed.synd.SyndLinkImpl;
059    import com.sun.syndication.io.FeedException;
060    
061    import java.io.File;
062    import java.io.FileInputStream;
063    import java.io.FileNotFoundException;
064    import java.io.InputStream;
065    
066    import java.util.ArrayList;
067    import java.util.Collections;
068    import java.util.Date;
069    import java.util.List;
070    
071    /**
072     * @author Brian Wing Shun Chan
073     * @author Mika Koivisto
074     * @author Shuyang Zhou
075     */
076    public class MBMessageServiceImpl extends MBMessageServiceBaseImpl {
077    
078            @Override
079            public MBMessage addDiscussionMessage(
080                            long groupId, String className, long classPK,
081                            String permissionClassName, long permissionClassPK,
082                            long permissionOwnerId, long threadId, long parentMessageId,
083                            String subject, String body, ServiceContext serviceContext)
084                    throws PortalException, SystemException {
085    
086                    User user = getGuestOrUser();
087    
088                    MBDiscussionPermission.check(
089                            getPermissionChecker(), user.getCompanyId(),
090                            serviceContext.getScopeGroupId(), permissionClassName,
091                            permissionClassPK, permissionOwnerId, ActionKeys.ADD_DISCUSSION);
092    
093                    return mbMessageLocalService.addDiscussionMessage(
094                            user.getUserId(), null, groupId, className, classPK, threadId,
095                            parentMessageId, subject, body, serviceContext);
096            }
097    
098            /**
099             * @deprecated As of 6.2.0, replaced by {@link #addMessage(long, String,
100             *             String, String, java.util.List, boolean, double, boolean,
101             *             com.liferay.portal.service.ServiceContext)}
102             */
103            @Override
104            public MBMessage addMessage(
105                            long groupId, long categoryId, long threadId, long parentMessageId,
106                            String subject, String body, String format,
107                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
108                            boolean anonymous, double priority, boolean allowPingbacks,
109                            ServiceContext serviceContext)
110                    throws PortalException, SystemException {
111    
112                    return addMessage(
113                            parentMessageId, subject, body, format, inputStreamOVPs, anonymous,
114                            priority, allowPingbacks, serviceContext);
115            }
116    
117            @Override
118            public MBMessage addMessage(
119                            long groupId, long categoryId, String subject, String body,
120                            String fileName, File file, ServiceContext serviceContext)
121                    throws FileNotFoundException, PortalException, SystemException {
122    
123                    return addMessage(
124                            groupId, categoryId, subject, body,
125                            MBMessageConstants.DEFAULT_FORMAT, fileName, file, false,
126                            MBThreadConstants.PRIORITY_NOT_GIVEN, false, serviceContext);
127            }
128    
129            @Override
130            public MBMessage addMessage(
131                            long groupId, long categoryId, String subject, String body,
132                            String format,
133                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
134                            boolean anonymous, double priority, boolean allowPingbacks,
135                            ServiceContext serviceContext)
136                    throws PortalException, SystemException {
137    
138                    MBCategoryPermission.check(
139                            getPermissionChecker(), groupId, categoryId,
140                            ActionKeys.ADD_MESSAGE);
141    
142                    if (!MBCategoryPermission.contains(
143                                    getPermissionChecker(), groupId, categoryId,
144                                    ActionKeys.ADD_FILE)) {
145    
146                            inputStreamOVPs = Collections.emptyList();
147                    }
148    
149                    if (!MBCategoryPermission.contains(
150                                    getPermissionChecker(), groupId, categoryId,
151                                    ActionKeys.UPDATE_THREAD_PRIORITY)) {
152    
153                            priority = MBThreadConstants.PRIORITY_NOT_GIVEN;
154                    }
155    
156                    return mbMessageLocalService.addMessage(
157                            getGuestOrUserId(), null, groupId, categoryId, subject, body,
158                            format, inputStreamOVPs, anonymous, priority, allowPingbacks,
159                            serviceContext);
160            }
161    
162            @Override
163            public MBMessage addMessage(
164                            long groupId, long categoryId, String subject, String body,
165                            String format, String fileName, File file, boolean anonymous,
166                            double priority, boolean allowPingbacks,
167                            ServiceContext serviceContext)
168                    throws FileNotFoundException, PortalException, SystemException {
169    
170                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
171                            new ArrayList<ObjectValuePair<String, InputStream>>();
172    
173                    InputStream inputStream = new FileInputStream(file);
174    
175                    ObjectValuePair<String, InputStream> inputStreamOVP =
176                            new ObjectValuePair<String, InputStream>(fileName, inputStream);
177    
178                    inputStreamOVPs.add(inputStreamOVP);
179    
180                    return addMessage(
181                            groupId, categoryId, subject, body, format, inputStreamOVPs,
182                            anonymous, priority, allowPingbacks, serviceContext);
183            }
184    
185            @Override
186            public MBMessage addMessage(
187                            long categoryId, String subject, String body,
188                            ServiceContext serviceContext)
189                    throws PortalException, SystemException {
190    
191                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
192                            categoryId);
193    
194                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
195                            Collections.emptyList();
196    
197                    return addMessage(
198                            category.getGroupId(), categoryId, subject, body,
199                            MBMessageConstants.DEFAULT_FORMAT, inputStreamOVPs, false, 0.0,
200                            false, serviceContext);
201            }
202    
203            @Override
204            public MBMessage addMessage(
205                            long parentMessageId, String subject, String body, String format,
206                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
207                            boolean anonymous, double priority, boolean allowPingbacks,
208                            ServiceContext serviceContext)
209                    throws PortalException, SystemException {
210    
211                    MBMessage parentMessage = mbMessagePersistence.findByPrimaryKey(
212                            parentMessageId);
213    
214                    checkReplyToPermission(
215                            parentMessage.getGroupId(), parentMessage.getCategoryId(),
216                            parentMessageId);
217    
218                    boolean preview = ParamUtil.getBoolean(serviceContext, "preview");
219    
220                    int workFlowAction = serviceContext.getWorkflowAction();
221    
222                    if ((workFlowAction == WorkflowConstants.STATUS_DRAFT) && !preview &&
223                            !serviceContext.isSignedIn()) {
224    
225                            MBMessagePermission.check(
226                                    getPermissionChecker(), parentMessageId, ActionKeys.UPDATE);
227                    }
228    
229                    if (lockLocalService.isLocked(
230                                    MBThread.class.getName(), parentMessage.getThreadId())) {
231    
232                            throw new LockedThreadException();
233                    }
234    
235                    if (!MBCategoryPermission.contains(
236                                    getPermissionChecker(), parentMessage.getGroupId(),
237                                    parentMessage.getCategoryId(), ActionKeys.ADD_FILE)) {
238    
239                            inputStreamOVPs = Collections.emptyList();
240                    }
241    
242                    if (!MBCategoryPermission.contains(
243                                    getPermissionChecker(), parentMessage.getGroupId(),
244                                    parentMessage.getCategoryId(),
245                                    ActionKeys.UPDATE_THREAD_PRIORITY)) {
246    
247                            priority = MBThreadConstants.PRIORITY_NOT_GIVEN;
248                    }
249    
250                    return mbMessageLocalService.addMessage(
251                            getGuestOrUserId(), null, parentMessage.getGroupId(),
252                            parentMessage.getCategoryId(), parentMessage.getThreadId(),
253                            parentMessageId, subject, body, format, inputStreamOVPs, anonymous,
254                            priority, allowPingbacks, serviceContext);
255            }
256    
257            @Override
258            public void deleteDiscussionMessage(
259                            long groupId, String className, long classPK,
260                            String permissionClassName, long permissionClassPK,
261                            long permissionOwnerId, long messageId)
262                    throws PortalException, SystemException {
263    
264                    User user = getUser();
265    
266                    MBDiscussionPermission.check(
267                            getPermissionChecker(), user.getCompanyId(), groupId,
268                            permissionClassName, permissionClassPK, messageId,
269                            permissionOwnerId, ActionKeys.DELETE_DISCUSSION);
270    
271                    mbMessageLocalService.deleteDiscussionMessage(messageId);
272            }
273    
274            @Override
275            public void deleteMessage(long messageId)
276                    throws PortalException, SystemException {
277    
278                    MBMessagePermission.check(
279                            getPermissionChecker(), messageId, ActionKeys.DELETE);
280    
281                    mbMessageLocalService.deleteMessage(messageId);
282            }
283    
284            @Override
285            public void deleteMessageAttachments(long messageId)
286                    throws PortalException, SystemException {
287    
288                    MBMessagePermission.check(
289                            getPermissionChecker(), messageId, ActionKeys.DELETE);
290    
291                    mbMessageLocalService.deleteMessageAttachments(messageId);
292            }
293    
294            @Override
295            public List<MBMessage> getCategoryMessages(
296                            long groupId, long categoryId, int status, int start, int end)
297                    throws PortalException, SystemException {
298    
299                    List<MBMessage> messages = new ArrayList<MBMessage>();
300    
301                    List<MBMessage> categoryMessages =
302                            mbMessageLocalService.getCategoryMessages(
303                                    groupId, categoryId, status, start, end);
304    
305                    for (MBMessage message : categoryMessages) {
306                            if (MBMessagePermission.contains(
307                                            getPermissionChecker(), message, ActionKeys.VIEW)) {
308    
309                                    messages.add(message);
310                            }
311                    }
312    
313                    return messages;
314            }
315    
316            @Override
317            public int getCategoryMessagesCount(
318                            long groupId, long categoryId, int status)
319                    throws SystemException {
320    
321                    return mbMessageLocalService.getCategoryMessagesCount(
322                            groupId, categoryId, status);
323            }
324    
325            @Override
326            public String getCategoryMessagesRSS(
327                            long groupId, long categoryId, int status, int max, String type,
328                            double version, String displayStyle, String feedURL,
329                            String entryURL, ThemeDisplay themeDisplay)
330                    throws PortalException, SystemException {
331    
332                    String name = StringPool.BLANK;
333                    String description = StringPool.BLANK;
334    
335                    MBCategory category = mbCategoryLocalService.fetchMBCategory(
336                            categoryId);
337    
338                    if (category == null) {
339                            Group group = groupLocalService.getGroup(categoryId);
340    
341                            groupId = group.getGroupId();
342                            categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
343                            name = group.getDescriptiveName();
344                            description = group.getDescription();
345                    }
346                    else {
347                            groupId = category.getGroupId();
348                            name = category.getName();
349                            description = category.getDescription();
350                    }
351    
352                    List<MBMessage> messages = new ArrayList<MBMessage>();
353    
354                    int lastIntervalStart = 0;
355                    boolean listNotExhausted = true;
356                    MessageCreateDateComparator comparator =
357                            new MessageCreateDateComparator(false);
358    
359                    while ((messages.size() < max) && listNotExhausted) {
360                            List<MBMessage> messageList =
361                                    mbMessageLocalService.getCategoryMessages(
362                                            groupId, categoryId, status, lastIntervalStart,
363                                            lastIntervalStart + max, comparator);
364    
365                            lastIntervalStart += max;
366                            listNotExhausted = (messageList.size() == max);
367    
368                            for (MBMessage message : messageList) {
369                                    if (messages.size() >= max) {
370                                            break;
371                                    }
372    
373                                    if (MBMessagePermission.contains(
374                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
375    
376                                            messages.add(message);
377                                    }
378                            }
379                    }
380    
381                    return exportToRSS(
382                            name, description, type, version, displayStyle, feedURL, entryURL,
383                            messages, themeDisplay);
384            }
385    
386            @Override
387            public String getCompanyMessagesRSS(
388                            long companyId, int status, int max, String type, double version,
389                            String displayStyle, String feedURL, String entryURL,
390                            ThemeDisplay themeDisplay)
391                    throws PortalException, SystemException {
392    
393                    Company company = companyPersistence.findByPrimaryKey(companyId);
394    
395                    String name = company.getName();
396                    String description = company.getName();
397    
398                    List<MBMessage> messages = new ArrayList<MBMessage>();
399    
400                    int lastIntervalStart = 0;
401                    boolean listNotExhausted = true;
402                    MessageCreateDateComparator comparator =
403                            new MessageCreateDateComparator(false);
404    
405                    while ((messages.size() < max) && listNotExhausted) {
406                            List<MBMessage> messageList =
407                                    mbMessageLocalService.getCompanyMessages(
408                                            companyId, status, lastIntervalStart,
409                                            lastIntervalStart + max, comparator);
410    
411                            lastIntervalStart += max;
412                            listNotExhausted = (messageList.size() == max);
413    
414                            for (MBMessage message : messageList) {
415                                    if (messages.size() >= max) {
416                                            break;
417                                    }
418    
419                                    if (MBMessagePermission.contains(
420                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
421    
422                                            messages.add(message);
423                                    }
424                            }
425                    }
426    
427                    return exportToRSS(
428                            name, description, type, version, displayStyle, feedURL, entryURL,
429                            messages, themeDisplay);
430            }
431    
432            @Override
433            public int getGroupMessagesCount(long groupId, int status)
434                    throws SystemException {
435    
436                    if (status == WorkflowConstants.STATUS_ANY) {
437                            return mbMessagePersistence.filterCountByGroupId(groupId);
438                    }
439                    else {
440                            return mbMessagePersistence.filterCountByG_S(groupId, status);
441                    }
442            }
443    
444            @Override
445            public String getGroupMessagesRSS(
446                            long groupId, int status, int max, String type, double version,
447                            String displayStyle, String feedURL, String entryURL,
448                            ThemeDisplay themeDisplay)
449                    throws PortalException, SystemException {
450    
451                    String name = StringPool.BLANK;
452                    String description = StringPool.BLANK;
453    
454                    List<MBMessage> messages = new ArrayList<MBMessage>();
455    
456                    int lastIntervalStart = 0;
457                    boolean listNotExhausted = true;
458                    MessageCreateDateComparator comparator =
459                            new MessageCreateDateComparator(false);
460    
461                    while ((messages.size() < max) && listNotExhausted) {
462                            List<MBMessage> messageList =
463                                    mbMessageLocalService.getGroupMessages(
464                                            groupId, status, lastIntervalStart, lastIntervalStart + max,
465                                            comparator);
466    
467                            lastIntervalStart += max;
468                            listNotExhausted = (messageList.size() == max);
469    
470                            for (MBMessage message : messageList) {
471                                    if (messages.size() >= max) {
472                                            break;
473                                    }
474    
475                                    if (MBMessagePermission.contains(
476                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
477    
478                                            messages.add(message);
479                                    }
480                            }
481                    }
482    
483                    if (messages.size() > 0) {
484                            MBMessage message = messages.get(messages.size() - 1);
485    
486                            name = message.getSubject();
487                            description = message.getSubject();
488                    }
489    
490                    return exportToRSS(
491                            name, description, type, version, displayStyle, feedURL, entryURL,
492                            messages, themeDisplay);
493            }
494    
495            @Override
496            public String getGroupMessagesRSS(
497                            long groupId, long userId, int status, int max, String type,
498                            double version, String displayStyle, String feedURL,
499                            String entryURL, ThemeDisplay themeDisplay)
500                    throws PortalException, SystemException {
501    
502                    String name = StringPool.BLANK;
503                    String description = StringPool.BLANK;
504    
505                    List<MBMessage> messages = new ArrayList<MBMessage>();
506    
507                    int lastIntervalStart = 0;
508                    boolean listNotExhausted = true;
509                    MessageCreateDateComparator comparator =
510                            new MessageCreateDateComparator(false);
511    
512                    while ((messages.size() < max) && listNotExhausted) {
513                            List<MBMessage> messageList =
514                                    mbMessageLocalService.getGroupMessages(
515                                            groupId, userId, status, lastIntervalStart,
516                                            lastIntervalStart + max, comparator);
517    
518                            lastIntervalStart += max;
519                            listNotExhausted = (messageList.size() == max);
520    
521                            for (MBMessage message : messageList) {
522                                    if (messages.size() >= max) {
523                                            break;
524                                    }
525    
526                                    if (MBMessagePermission.contains(
527                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
528    
529                                            messages.add(message);
530                                    }
531                            }
532                    }
533    
534                    if (messages.size() > 0) {
535                            MBMessage message = messages.get(messages.size() - 1);
536    
537                            name = message.getSubject();
538                            description = message.getSubject();
539                    }
540    
541                    return exportToRSS(
542                            name, description, type, version, displayStyle, feedURL, entryURL,
543                            messages, themeDisplay);
544            }
545    
546            @Override
547            public MBMessage getMessage(long messageId)
548                    throws PortalException, SystemException {
549    
550                    MBMessagePermission.check(
551                            getPermissionChecker(), messageId, ActionKeys.VIEW);
552    
553                    return mbMessageLocalService.getMessage(messageId);
554            }
555    
556            @Override
557            public MBMessageDisplay getMessageDisplay(
558                            long messageId, int status, String threadView,
559                            boolean includePrevAndNext)
560                    throws PortalException, SystemException {
561    
562                    MBMessagePermission.check(
563                            getPermissionChecker(), messageId, ActionKeys.VIEW);
564    
565                    return mbMessageLocalService.getMessageDisplay(
566                            getGuestOrUserId(), messageId, status, threadView,
567                            includePrevAndNext);
568            }
569    
570            @Override
571            public int getThreadAnswersCount(
572                            long groupId, long categoryId, long threadId)
573                    throws SystemException {
574    
575                    return mbMessagePersistence.filterCountByG_C_T_A(
576                            groupId, categoryId, threadId, true);
577            }
578    
579            @Override
580            public List<MBMessage> getThreadMessages(
581                            long groupId, long categoryId, long threadId, int status, int start,
582                            int end)
583                    throws SystemException {
584    
585                    if (status == WorkflowConstants.STATUS_ANY) {
586                            return mbMessagePersistence.filterFindByG_C_T(
587                                    groupId, categoryId, threadId, start, end);
588                    }
589                    else {
590                            return mbMessagePersistence.filterFindByG_C_T_S(
591                                    groupId, categoryId, threadId, status, start, end);
592                    }
593            }
594    
595            @Override
596            public int getThreadMessagesCount(
597                            long groupId, long categoryId, long threadId, int status)
598                    throws SystemException {
599    
600                    if (status == WorkflowConstants.STATUS_ANY) {
601                            return mbMessagePersistence.filterCountByG_C_T(
602                                    groupId, categoryId, threadId);
603                    }
604                    else {
605                            return mbMessagePersistence.filterCountByG_C_T_S(
606                                    groupId, categoryId, threadId, status);
607                    }
608            }
609    
610            @Override
611            public String getThreadMessagesRSS(
612                            long threadId, int status, int max, String type, double version,
613                            String displayStyle, String feedURL, String entryURL,
614                            ThemeDisplay themeDisplay)
615                    throws PortalException, SystemException {
616    
617                    String name = StringPool.BLANK;
618                    String description = StringPool.BLANK;
619    
620                    List<MBMessage> messages = new ArrayList<MBMessage>();
621    
622                    MBThread thread = mbThreadLocalService.getThread(threadId);
623    
624                    if (MBMessagePermission.contains(
625                                    getPermissionChecker(), thread.getRootMessageId(),
626                                    ActionKeys.VIEW)) {
627    
628                            MessageCreateDateComparator comparator =
629                                    new MessageCreateDateComparator(false);
630    
631                            List<MBMessage> threadMessages =
632                                    mbMessageLocalService.getThreadMessages(
633                                            threadId, status, comparator);
634    
635                            for (MBMessage message : threadMessages) {
636                                    if (messages.size() >= max) {
637                                            break;
638                                    }
639    
640                                    if (MBMessagePermission.contains(
641                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
642    
643                                            messages.add(message);
644                                    }
645                            }
646    
647                            if (messages.size() > 0) {
648                                    MBMessage message = messages.get(messages.size() - 1);
649    
650                                    name = message.getSubject();
651                                    description = message.getSubject();
652                            }
653                    }
654    
655                    return exportToRSS(
656                            name, description, type, version, displayStyle, feedURL, entryURL,
657                            messages, themeDisplay);
658            }
659    
660            @Override
661            public void restoreMessageAttachmentFromTrash(
662                            long messageId, String fileName)
663                    throws PortalException, SystemException {
664    
665                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
666    
667                    MBCategoryPermission.check(
668                            getPermissionChecker(), message.getGroupId(),
669                            message.getCategoryId(), ActionKeys.ADD_FILE);
670    
671                    mbMessageLocalService.restoreMessageAttachmentFromTrash(
672                            getUserId(), messageId, fileName);
673            }
674    
675            @Override
676            public void subscribeMessage(long messageId)
677                    throws PortalException, SystemException {
678    
679                    MBMessagePermission.check(
680                            getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
681    
682                    mbMessageLocalService.subscribeMessage(getUserId(), messageId);
683            }
684    
685            @Override
686            public void unsubscribeMessage(long messageId)
687                    throws PortalException, SystemException {
688    
689                    MBMessagePermission.check(
690                            getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
691    
692                    mbMessageLocalService.unsubscribeMessage(getUserId(), messageId);
693            }
694    
695            @Override
696            public void updateAnswer(long messageId, boolean answer, boolean cascade)
697                    throws PortalException, SystemException {
698    
699                    mbMessageLocalService.updateAnswer(messageId, answer, cascade);
700            }
701    
702            @Override
703            public MBMessage updateDiscussionMessage(
704                            String className, long classPK, String permissionClassName,
705                            long permissionClassPK, long permissionOwnerId, long messageId,
706                            String subject, String body, ServiceContext serviceContext)
707                    throws PortalException, SystemException {
708    
709                    User user = getUser();
710    
711                    MBDiscussionPermission.check(
712                            getPermissionChecker(), user.getCompanyId(),
713                            serviceContext.getScopeGroupId(), permissionClassName,
714                            permissionClassPK, messageId, permissionOwnerId,
715                            ActionKeys.UPDATE_DISCUSSION);
716    
717                    return mbMessageLocalService.updateDiscussionMessage(
718                            getUserId(), messageId, className, classPK, subject, body,
719                            serviceContext);
720            }
721    
722            @Override
723            public MBMessage updateMessage(
724                            long messageId, String subject, String body,
725                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
726                            List<String> existingFiles, double priority, boolean allowPingbacks,
727                            ServiceContext serviceContext)
728                    throws PortalException, SystemException {
729    
730                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
731    
732                    boolean preview = ParamUtil.getBoolean(serviceContext, "preview");
733    
734                    if (preview &&
735                            MBMessagePermission.contains(
736                                    getPermissionChecker(), message, ActionKeys.UPDATE)) {
737    
738                            checkReplyToPermission(
739                                    message.getGroupId(), message.getCategoryId(),
740                                    message.getParentMessageId());
741                    }
742                    else {
743                            MBMessagePermission.check(
744                                    getPermissionChecker(), messageId, ActionKeys.UPDATE);
745                    }
746    
747                    if (lockLocalService.isLocked(
748                                    MBThread.class.getName(), message.getThreadId())) {
749    
750                            throw new LockedThreadException();
751                    }
752    
753                    if (!MBCategoryPermission.contains(
754                                    getPermissionChecker(), message.getGroupId(),
755                                    message.getCategoryId(), ActionKeys.ADD_FILE)) {
756    
757                            inputStreamOVPs = Collections.emptyList();
758                    }
759    
760                    if (!MBCategoryPermission.contains(
761                                    getPermissionChecker(), message.getGroupId(),
762                                    message.getCategoryId(), ActionKeys.UPDATE_THREAD_PRIORITY)) {
763    
764                            MBThread thread = mbThreadLocalService.getThread(
765                                    message.getThreadId());
766    
767                            priority = thread.getPriority();
768                    }
769    
770                    return mbMessageLocalService.updateMessage(
771                            getGuestOrUserId(), messageId, subject, body, inputStreamOVPs,
772                            existingFiles, priority, allowPingbacks, serviceContext);
773            }
774    
775            protected void checkReplyToPermission(
776                            long groupId, long categoryId, long parentMessageId)
777                    throws PortalException, SystemException {
778    
779                    if (parentMessageId > 0) {
780                            if (MBCategoryPermission.contains(
781                                            getPermissionChecker(), groupId, categoryId,
782                                            ActionKeys.ADD_MESSAGE)) {
783    
784                                    return;
785                            }
786    
787                            if (!MBCategoryPermission.contains(
788                                            getPermissionChecker(), groupId, categoryId,
789                                            ActionKeys.REPLY_TO_MESSAGE)) {
790    
791                                    throw new PrincipalException();
792                            }
793                    }
794                    else {
795                            MBCategoryPermission.check(
796                                    getPermissionChecker(), groupId, categoryId,
797                                    ActionKeys.ADD_MESSAGE);
798                    }
799            }
800    
801            protected String exportToRSS(
802                            String name, String description, String type, double version,
803                            String displayStyle, String feedURL, String entryURL,
804                            List<MBMessage> messages, ThemeDisplay themeDisplay)
805                    throws SystemException {
806    
807                    SyndFeed syndFeed = new SyndFeedImpl();
808    
809                    syndFeed.setDescription(description);
810    
811                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
812    
813                    syndFeed.setEntries(syndEntries);
814    
815                    for (MBMessage message : messages) {
816                            SyndEntry syndEntry = new SyndEntryImpl();
817    
818                            if (!message.isAnonymous()) {
819                                    String author = PortalUtil.getUserName(message);
820    
821                                    syndEntry.setAuthor(author);
822                            }
823    
824                            SyndContent syndContent = new SyndContentImpl();
825    
826                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
827    
828                            String value = null;
829    
830                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
831                                    value = StringUtil.shorten(
832                                            HtmlUtil.extractText(message.getBody()),
833                                            PropsValues.MESSAGE_BOARDS_RSS_ABSTRACT_LENGTH,
834                                            StringPool.BLANK);
835                            }
836                            else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
837                                    value = StringPool.BLANK;
838                            }
839                            else if (message.isFormatBBCode()) {
840                                    value = BBCodeTranslatorUtil.getHTML(message.getBody());
841    
842                                    value = MBUtil.replaceMessageBodyPaths(themeDisplay, value);
843                            }
844                            else {
845                                    value = message.getBody();
846                            }
847    
848                            syndContent.setValue(value);
849    
850                            syndEntry.setDescription(syndContent);
851    
852                            syndEntry.setLink(
853                                    entryURL + "&messageId=" + message.getMessageId());
854                            syndEntry.setPublishedDate(message.getCreateDate());
855                            syndEntry.setTitle(message.getSubject());
856                            syndEntry.setUpdatedDate(message.getModifiedDate());
857                            syndEntry.setUri(syndEntry.getLink());
858    
859                            syndEntries.add(syndEntry);
860                    }
861    
862                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
863    
864                    List<SyndLink> syndLinks = new ArrayList<SyndLink>();
865    
866                    syndFeed.setLinks(syndLinks);
867    
868                    SyndLink selfSyndLink = new SyndLinkImpl();
869    
870                    syndLinks.add(selfSyndLink);
871    
872                    selfSyndLink.setHref(feedURL);
873                    selfSyndLink.setRel("self");
874    
875                    syndFeed.setPublishedDate(new Date());
876                    syndFeed.setTitle(name);
877                    syndFeed.setUri(feedURL);
878    
879                    try {
880                            return RSSUtil.export(syndFeed);
881                    }
882                    catch (FeedException fe) {
883                            throw new SystemException(fe);
884                    }
885            }
886    
887    }