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                            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, ActionKeys.DELETE_DISCUSSION);
273    
274                    checkDiscussion(className, classPK, 0, messageId);
275    
276                    mbMessageLocalService.deleteDiscussionMessage(messageId);
277            }
278    
279            @Override
280            public void deleteMessage(long messageId)
281                    throws PortalException, SystemException {
282    
283                    MBMessagePermission.check(
284                            getPermissionChecker(), messageId, ActionKeys.DELETE);
285    
286                    mbMessageLocalService.deleteMessage(messageId);
287            }
288    
289            @Override
290            public void deleteMessageAttachments(long messageId)
291                    throws PortalException, SystemException {
292    
293                    MBMessagePermission.check(
294                            getPermissionChecker(), messageId, ActionKeys.DELETE);
295    
296                    mbMessageLocalService.deleteMessageAttachments(messageId);
297            }
298    
299            @Override
300            public List<MBMessage> getCategoryMessages(
301                            long groupId, long categoryId, int status, int start, int end)
302                    throws PortalException, SystemException {
303    
304                    List<MBMessage> messages = new ArrayList<MBMessage>();
305    
306                    List<MBMessage> categoryMessages =
307                            mbMessageLocalService.getCategoryMessages(
308                                    groupId, categoryId, status, start, end);
309    
310                    for (MBMessage message : categoryMessages) {
311                            if (MBMessagePermission.contains(
312                                            getPermissionChecker(), message, ActionKeys.VIEW)) {
313    
314                                    messages.add(message);
315                            }
316                    }
317    
318                    return messages;
319            }
320    
321            @Override
322            public int getCategoryMessagesCount(
323                            long groupId, long categoryId, int status)
324                    throws SystemException {
325    
326                    return mbMessageLocalService.getCategoryMessagesCount(
327                            groupId, categoryId, status);
328            }
329    
330            @Override
331            public String getCategoryMessagesRSS(
332                            long groupId, long categoryId, int status, int max, String type,
333                            double version, String displayStyle, String feedURL,
334                            String entryURL, ThemeDisplay themeDisplay)
335                    throws PortalException, SystemException {
336    
337                    String name = StringPool.BLANK;
338                    String description = StringPool.BLANK;
339    
340                    MBCategory category = mbCategoryLocalService.fetchMBCategory(
341                            categoryId);
342    
343                    if (category == null) {
344                            Group group = groupLocalService.getGroup(categoryId);
345    
346                            groupId = group.getGroupId();
347                            categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
348                            name = group.getDescriptiveName();
349                            description = group.getDescription();
350                    }
351                    else {
352                            groupId = category.getGroupId();
353                            name = category.getName();
354                            description = category.getDescription();
355                    }
356    
357                    List<MBMessage> messages = new ArrayList<MBMessage>();
358    
359                    int lastIntervalStart = 0;
360                    boolean listNotExhausted = true;
361                    MessageCreateDateComparator comparator =
362                            new MessageCreateDateComparator(false);
363    
364                    while ((messages.size() < max) && listNotExhausted) {
365                            List<MBMessage> messageList =
366                                    mbMessageLocalService.getCategoryMessages(
367                                            groupId, categoryId, status, lastIntervalStart,
368                                            lastIntervalStart + max, comparator);
369    
370                            lastIntervalStart += max;
371                            listNotExhausted = (messageList.size() == max);
372    
373                            for (MBMessage message : messageList) {
374                                    if (messages.size() >= max) {
375                                            break;
376                                    }
377    
378                                    if (MBMessagePermission.contains(
379                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
380    
381                                            messages.add(message);
382                                    }
383                            }
384                    }
385    
386                    return exportToRSS(
387                            name, description, type, version, displayStyle, feedURL, entryURL,
388                            messages, themeDisplay);
389            }
390    
391            @Override
392            public String getCompanyMessagesRSS(
393                            long companyId, int status, int max, String type, double version,
394                            String displayStyle, String feedURL, String entryURL,
395                            ThemeDisplay themeDisplay)
396                    throws PortalException, SystemException {
397    
398                    Company company = companyPersistence.findByPrimaryKey(companyId);
399    
400                    String name = company.getName();
401                    String description = company.getName();
402    
403                    List<MBMessage> messages = new ArrayList<MBMessage>();
404    
405                    int lastIntervalStart = 0;
406                    boolean listNotExhausted = true;
407                    MessageCreateDateComparator comparator =
408                            new MessageCreateDateComparator(false);
409    
410                    while ((messages.size() < max) && listNotExhausted) {
411                            List<MBMessage> messageList =
412                                    mbMessageLocalService.getCompanyMessages(
413                                            companyId, status, lastIntervalStart,
414                                            lastIntervalStart + max, comparator);
415    
416                            lastIntervalStart += max;
417                            listNotExhausted = (messageList.size() == max);
418    
419                            for (MBMessage message : messageList) {
420                                    if (messages.size() >= max) {
421                                            break;
422                                    }
423    
424                                    if (MBMessagePermission.contains(
425                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
426    
427                                            messages.add(message);
428                                    }
429                            }
430                    }
431    
432                    return exportToRSS(
433                            name, description, type, version, displayStyle, feedURL, entryURL,
434                            messages, themeDisplay);
435            }
436    
437            @Override
438            public int getGroupMessagesCount(long groupId, int status)
439                    throws SystemException {
440    
441                    if (status == WorkflowConstants.STATUS_ANY) {
442                            return mbMessagePersistence.filterCountByGroupId(groupId);
443                    }
444                    else {
445                            return mbMessagePersistence.filterCountByG_S(groupId, status);
446                    }
447            }
448    
449            @Override
450            public String getGroupMessagesRSS(
451                            long groupId, int status, int max, String type, double version,
452                            String displayStyle, String feedURL, String entryURL,
453                            ThemeDisplay themeDisplay)
454                    throws PortalException, SystemException {
455    
456                    String name = StringPool.BLANK;
457                    String description = StringPool.BLANK;
458    
459                    List<MBMessage> messages = new ArrayList<MBMessage>();
460    
461                    int lastIntervalStart = 0;
462                    boolean listNotExhausted = true;
463                    MessageCreateDateComparator comparator =
464                            new MessageCreateDateComparator(false);
465    
466                    while ((messages.size() < max) && listNotExhausted) {
467                            List<MBMessage> messageList =
468                                    mbMessageLocalService.getGroupMessages(
469                                            groupId, status, lastIntervalStart, lastIntervalStart + max,
470                                            comparator);
471    
472                            lastIntervalStart += max;
473                            listNotExhausted = (messageList.size() == max);
474    
475                            for (MBMessage message : messageList) {
476                                    if (messages.size() >= max) {
477                                            break;
478                                    }
479    
480                                    if (MBMessagePermission.contains(
481                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
482    
483                                            messages.add(message);
484                                    }
485                            }
486                    }
487    
488                    if (messages.size() > 0) {
489                            MBMessage message = messages.get(messages.size() - 1);
490    
491                            name = message.getSubject();
492                            description = message.getSubject();
493                    }
494    
495                    return exportToRSS(
496                            name, description, type, version, displayStyle, feedURL, entryURL,
497                            messages, themeDisplay);
498            }
499    
500            @Override
501            public String getGroupMessagesRSS(
502                            long groupId, long userId, int status, int max, String type,
503                            double version, String displayStyle, String feedURL,
504                            String entryURL, ThemeDisplay themeDisplay)
505                    throws PortalException, SystemException {
506    
507                    String name = StringPool.BLANK;
508                    String description = StringPool.BLANK;
509    
510                    List<MBMessage> messages = new ArrayList<MBMessage>();
511    
512                    int lastIntervalStart = 0;
513                    boolean listNotExhausted = true;
514                    MessageCreateDateComparator comparator =
515                            new MessageCreateDateComparator(false);
516    
517                    while ((messages.size() < max) && listNotExhausted) {
518                            List<MBMessage> messageList =
519                                    mbMessageLocalService.getGroupMessages(
520                                            groupId, userId, status, lastIntervalStart,
521                                            lastIntervalStart + max, comparator);
522    
523                            lastIntervalStart += max;
524                            listNotExhausted = (messageList.size() == max);
525    
526                            for (MBMessage message : messageList) {
527                                    if (messages.size() >= max) {
528                                            break;
529                                    }
530    
531                                    if (MBMessagePermission.contains(
532                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
533    
534                                            messages.add(message);
535                                    }
536                            }
537                    }
538    
539                    if (messages.size() > 0) {
540                            MBMessage message = messages.get(messages.size() - 1);
541    
542                            name = message.getSubject();
543                            description = message.getSubject();
544                    }
545    
546                    return exportToRSS(
547                            name, description, type, version, displayStyle, feedURL, entryURL,
548                            messages, themeDisplay);
549            }
550    
551            @Override
552            public MBMessage getMessage(long messageId)
553                    throws PortalException, SystemException {
554    
555                    MBMessagePermission.check(
556                            getPermissionChecker(), messageId, ActionKeys.VIEW);
557    
558                    return mbMessageLocalService.getMessage(messageId);
559            }
560    
561            @Override
562            public MBMessageDisplay getMessageDisplay(
563                            long messageId, int status, String threadView,
564                            boolean includePrevAndNext)
565                    throws PortalException, SystemException {
566    
567                    MBMessagePermission.check(
568                            getPermissionChecker(), messageId, ActionKeys.VIEW);
569    
570                    return mbMessageLocalService.getMessageDisplay(
571                            getGuestOrUserId(), messageId, status, threadView,
572                            includePrevAndNext);
573            }
574    
575            @Override
576            public int getThreadAnswersCount(
577                            long groupId, long categoryId, long threadId)
578                    throws SystemException {
579    
580                    return mbMessagePersistence.filterCountByG_C_T_A(
581                            groupId, categoryId, threadId, true);
582            }
583    
584            @Override
585            public List<MBMessage> getThreadMessages(
586                            long groupId, long categoryId, long threadId, int status, int start,
587                            int end)
588                    throws SystemException {
589    
590                    if (status == WorkflowConstants.STATUS_ANY) {
591                            return mbMessagePersistence.filterFindByG_C_T(
592                                    groupId, categoryId, threadId, start, end);
593                    }
594                    else {
595                            return mbMessagePersistence.filterFindByG_C_T_S(
596                                    groupId, categoryId, threadId, status, start, end);
597                    }
598            }
599    
600            @Override
601            public int getThreadMessagesCount(
602                            long groupId, long categoryId, long threadId, int status)
603                    throws SystemException {
604    
605                    if (status == WorkflowConstants.STATUS_ANY) {
606                            return mbMessagePersistence.filterCountByG_C_T(
607                                    groupId, categoryId, threadId);
608                    }
609                    else {
610                            return mbMessagePersistence.filterCountByG_C_T_S(
611                                    groupId, categoryId, threadId, status);
612                    }
613            }
614    
615            @Override
616            public String getThreadMessagesRSS(
617                            long threadId, int status, int max, String type, double version,
618                            String displayStyle, String feedURL, String entryURL,
619                            ThemeDisplay themeDisplay)
620                    throws PortalException, SystemException {
621    
622                    String name = StringPool.BLANK;
623                    String description = StringPool.BLANK;
624    
625                    List<MBMessage> messages = new ArrayList<MBMessage>();
626    
627                    MBThread thread = mbThreadLocalService.getThread(threadId);
628    
629                    if (MBMessagePermission.contains(
630                                    getPermissionChecker(), thread.getRootMessageId(),
631                                    ActionKeys.VIEW)) {
632    
633                            MessageCreateDateComparator comparator =
634                                    new MessageCreateDateComparator(false);
635    
636                            List<MBMessage> threadMessages =
637                                    mbMessageLocalService.getThreadMessages(
638                                            threadId, status, comparator);
639    
640                            for (MBMessage message : threadMessages) {
641                                    if (messages.size() >= max) {
642                                            break;
643                                    }
644    
645                                    if (MBMessagePermission.contains(
646                                                    getPermissionChecker(), message, ActionKeys.VIEW)) {
647    
648                                            messages.add(message);
649                                    }
650                            }
651    
652                            if (messages.size() > 0) {
653                                    MBMessage message = messages.get(messages.size() - 1);
654    
655                                    name = message.getSubject();
656                                    description = message.getSubject();
657                            }
658                    }
659    
660                    return exportToRSS(
661                            name, description, type, version, displayStyle, feedURL, entryURL,
662                            messages, themeDisplay);
663            }
664    
665            @Override
666            public void restoreMessageAttachmentFromTrash(
667                            long messageId, String fileName)
668                    throws PortalException, SystemException {
669    
670                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
671    
672                    MBCategoryPermission.check(
673                            getPermissionChecker(), message.getGroupId(),
674                            message.getCategoryId(), ActionKeys.ADD_FILE);
675    
676                    mbMessageLocalService.restoreMessageAttachmentFromTrash(
677                            getUserId(), messageId, fileName);
678            }
679    
680            @Override
681            public void subscribeMessage(long messageId)
682                    throws PortalException, SystemException {
683    
684                    MBMessagePermission.check(
685                            getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
686    
687                    mbMessageLocalService.subscribeMessage(getUserId(), messageId);
688            }
689    
690            @Override
691            public void unsubscribeMessage(long messageId)
692                    throws PortalException, SystemException {
693    
694                    MBMessagePermission.check(
695                            getPermissionChecker(), messageId, ActionKeys.SUBSCRIBE);
696    
697                    mbMessageLocalService.unsubscribeMessage(getUserId(), messageId);
698            }
699    
700            @Override
701            public void updateAnswer(long messageId, boolean answer, boolean cascade)
702                    throws PortalException, SystemException {
703    
704                    mbMessageLocalService.updateAnswer(messageId, answer, cascade);
705            }
706    
707            @Override
708            public MBMessage updateDiscussionMessage(
709                            String className, long classPK, String permissionClassName,
710                            long permissionClassPK, long permissionOwnerId, long messageId,
711                            String subject, String body, ServiceContext serviceContext)
712                    throws PortalException, SystemException {
713    
714                    User user = getUser();
715    
716                    MBDiscussionPermission.check(
717                            getPermissionChecker(), user.getCompanyId(),
718                            serviceContext.getScopeGroupId(), className, classPK, messageId,
719                            ActionKeys.UPDATE_DISCUSSION);
720    
721                    checkDiscussion(className, classPK, 0, messageId);
722    
723                    return mbMessageLocalService.updateDiscussionMessage(
724                            getUserId(), messageId, className, classPK, subject, body,
725                            serviceContext);
726            }
727    
728            @Override
729            public MBMessage updateMessage(
730                            long messageId, String subject, String body,
731                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
732                            List<String> existingFiles, double priority, boolean allowPingbacks,
733                            ServiceContext serviceContext)
734                    throws PortalException, SystemException {
735    
736                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
737    
738                    boolean preview = ParamUtil.getBoolean(serviceContext, "preview");
739    
740                    if (preview &&
741                            MBMessagePermission.contains(
742                                    getPermissionChecker(), message, ActionKeys.UPDATE)) {
743    
744                            checkReplyToPermission(
745                                    message.getGroupId(), message.getCategoryId(),
746                                    message.getParentMessageId());
747                    }
748                    else {
749                            MBMessagePermission.check(
750                                    getPermissionChecker(), messageId, ActionKeys.UPDATE);
751                    }
752    
753                    if (lockLocalService.isLocked(
754                                    MBThread.class.getName(), message.getThreadId())) {
755    
756                            throw new LockedThreadException();
757                    }
758    
759                    if (!MBCategoryPermission.contains(
760                                    getPermissionChecker(), message.getGroupId(),
761                                    message.getCategoryId(), ActionKeys.ADD_FILE)) {
762    
763                            inputStreamOVPs = Collections.emptyList();
764                    }
765    
766                    if (!MBCategoryPermission.contains(
767                                    getPermissionChecker(), message.getGroupId(),
768                                    message.getCategoryId(), ActionKeys.UPDATE_THREAD_PRIORITY)) {
769    
770                            MBThread thread = mbThreadLocalService.getThread(
771                                    message.getThreadId());
772    
773                            priority = thread.getPriority();
774                    }
775    
776                    return mbMessageLocalService.updateMessage(
777                            getGuestOrUserId(), messageId, subject, body, inputStreamOVPs,
778                            existingFiles, priority, allowPingbacks, serviceContext);
779            }
780    
781            protected void checkDiscussion(
782                            String className, long classPK, long threadId, long messageId)
783                    throws PortalException, SystemException {
784    
785                    long classNameId = ClassNameLocalServiceUtil.getClassNameId(className);
786    
787                    MBDiscussion discussion = mbDiscussionPersistence.findByC_C(
788                            classNameId, classPK);
789    
790                    MBThread thread;
791    
792                    if (threadId > 0) {
793                            thread = mbThreadPersistence.findByPrimaryKey(threadId);
794    
795                            if (discussion.getThreadId() != threadId) {
796                                    throw new PrincipalException();
797                            }
798                    }
799                    else {
800                            thread = mbThreadPersistence.findByPrimaryKey(
801                                    discussion.getThreadId());
802                    }
803    
804                    if (messageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
805                            MBMessage message = mbMessagePersistence.findByPrimaryKey(
806                                    messageId);
807    
808                            if (thread.getRootMessageId() != message.getRootMessageId()) {
809                                    throw new PrincipalException();
810                            }
811                    }
812            }
813    
814            protected void checkReplyToPermission(
815                            long groupId, long categoryId, long parentMessageId)
816                    throws PortalException, SystemException {
817    
818                    if (parentMessageId > 0) {
819                            if (MBCategoryPermission.contains(
820                                            getPermissionChecker(), groupId, categoryId,
821                                            ActionKeys.ADD_MESSAGE)) {
822    
823                                    return;
824                            }
825    
826                            if (!MBCategoryPermission.contains(
827                                            getPermissionChecker(), groupId, categoryId,
828                                            ActionKeys.REPLY_TO_MESSAGE)) {
829    
830                                    throw new PrincipalException();
831                            }
832                    }
833                    else {
834                            MBCategoryPermission.check(
835                                    getPermissionChecker(), groupId, categoryId,
836                                    ActionKeys.ADD_MESSAGE);
837                    }
838            }
839    
840            protected String exportToRSS(
841                            String name, String description, String type, double version,
842                            String displayStyle, String feedURL, String entryURL,
843                            List<MBMessage> messages, ThemeDisplay themeDisplay)
844                    throws SystemException {
845    
846                    SyndFeed syndFeed = new SyndFeedImpl();
847    
848                    syndFeed.setDescription(description);
849    
850                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
851    
852                    syndFeed.setEntries(syndEntries);
853    
854                    for (MBMessage message : messages) {
855                            SyndEntry syndEntry = new SyndEntryImpl();
856    
857                            if (!message.isAnonymous()) {
858                                    String author = PortalUtil.getUserName(message);
859    
860                                    syndEntry.setAuthor(author);
861                            }
862    
863                            SyndContent syndContent = new SyndContentImpl();
864    
865                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
866    
867                            String value = null;
868    
869                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
870                                    value = StringUtil.shorten(
871                                            HtmlUtil.extractText(message.getBody()),
872                                            PropsValues.MESSAGE_BOARDS_RSS_ABSTRACT_LENGTH,
873                                            StringPool.BLANK);
874                            }
875                            else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
876                                    value = StringPool.BLANK;
877                            }
878                            else if (message.isFormatBBCode()) {
879                                    value = BBCodeTranslatorUtil.getHTML(message.getBody());
880    
881                                    value = MBUtil.replaceMessageBodyPaths(themeDisplay, value);
882                            }
883                            else {
884                                    value = message.getBody();
885                            }
886    
887                            syndContent.setValue(value);
888    
889                            syndEntry.setDescription(syndContent);
890    
891                            syndEntry.setLink(
892                                    entryURL + "&messageId=" + message.getMessageId());
893                            syndEntry.setPublishedDate(message.getCreateDate());
894                            syndEntry.setTitle(message.getSubject());
895                            syndEntry.setUpdatedDate(message.getModifiedDate());
896                            syndEntry.setUri(syndEntry.getLink());
897    
898                            syndEntries.add(syndEntry);
899                    }
900    
901                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
902    
903                    List<SyndLink> syndLinks = new ArrayList<SyndLink>();
904    
905                    syndFeed.setLinks(syndLinks);
906    
907                    SyndLink selfSyndLink = new SyndLinkImpl();
908    
909                    syndLinks.add(selfSyndLink);
910    
911                    selfSyndLink.setHref(feedURL);
912                    selfSyndLink.setRel("self");
913    
914                    syndFeed.setPublishedDate(new Date());
915                    syndFeed.setTitle(name);
916                    syndFeed.setUri(feedURL);
917    
918                    try {
919                            return RSSUtil.export(syndFeed);
920                    }
921                    catch (FeedException fe) {
922                            throw new SystemException(fe);
923                    }
924            }
925    
926    }