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