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