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.blogs.service.impl;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.servlet.taglib.ui.ImageSelector;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.HtmlUtil;
025    import com.liferay.portal.kernel.util.MimeTypesUtil;
026    import com.liferay.portal.kernel.util.OrderByComparator;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.workflow.WorkflowConstants;
032    import com.liferay.portal.model.Company;
033    import com.liferay.portal.model.Group;
034    import com.liferay.portal.model.Organization;
035    import com.liferay.portal.security.permission.ActionKeys;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.theme.ThemeDisplay;
038    import com.liferay.portal.util.PortalUtil;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portlet.blogs.model.BlogsEntry;
041    import com.liferay.portlet.blogs.service.base.BlogsEntryServiceBaseImpl;
042    import com.liferay.portlet.blogs.service.permission.BlogsEntryPermission;
043    import com.liferay.portlet.blogs.service.permission.BlogsPermission;
044    import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
045    import com.liferay.util.RSSUtil;
046    
047    import com.sun.syndication.feed.synd.SyndContent;
048    import com.sun.syndication.feed.synd.SyndContentImpl;
049    import com.sun.syndication.feed.synd.SyndEntry;
050    import com.sun.syndication.feed.synd.SyndEntryImpl;
051    import com.sun.syndication.feed.synd.SyndFeed;
052    import com.sun.syndication.feed.synd.SyndFeedImpl;
053    import com.sun.syndication.feed.synd.SyndLink;
054    import com.sun.syndication.feed.synd.SyndLinkImpl;
055    import com.sun.syndication.io.FeedException;
056    
057    import java.io.IOException;
058    import java.io.InputStream;
059    
060    import java.util.ArrayList;
061    import java.util.Date;
062    import java.util.List;
063    
064    /**
065     * Provides the remote service for accessing, adding, deleting, subscription
066     * handling of, trash handling of, and updating blog entries. Its methods
067     * include permission checks.
068     *
069     * @author Brian Wing Shun Chan
070     * @author Mate Thurzo
071     */
072    public class BlogsEntryServiceImpl extends BlogsEntryServiceBaseImpl {
073    
074            /**
075             * @deprecated As of 7.0.0, replaced by {@link #addEntry(String, String,
076             *             String, String, int, int, int, int, int, boolean, boolean,
077             *             String[], String, ImageSelector, ImageSelector,
078             *             ServiceContext)}
079             */
080            @Deprecated
081            @Override
082            public BlogsEntry addEntry(
083                            String title, String description, String content,
084                            int displayDateMonth, int displayDateDay, int displayDateYear,
085                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
086                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
087                            String smallImageURL, String smallImageFileName,
088                            InputStream smallImageInputStream, ServiceContext serviceContext)
089                    throws PortalException {
090    
091                    BlogsPermission.check(
092                            getPermissionChecker(), serviceContext.getScopeGroupId(),
093                            ActionKeys.ADD_ENTRY);
094    
095                    ImageSelector coverImageImageSelector = null;
096                    ImageSelector smallImageImageSelector = null;
097    
098                    if (smallImage) {
099                            if (Validator.isNotNull(smallImageFileName) &&
100                                    (smallImageInputStream != null)) {
101    
102                                    try {
103                                            byte[] bytes = FileUtil.getBytes(smallImageInputStream);
104    
105                                            smallImageImageSelector = new ImageSelector(
106                                                    bytes, smallImageFileName,
107                                                    MimeTypesUtil.getContentType(smallImageFileName), null);
108                                    }
109                                    catch (IOException ioe) {
110                                            if (_log.isErrorEnabled()) {
111                                                    _log.error("Unable to create image selector", ioe);
112                                            }
113                                    }
114                            }
115                            else if (Validator.isNotNull(smallImageURL)) {
116                                    smallImageImageSelector = new ImageSelector(smallImageURL);
117                            }
118                    }
119    
120                    return addEntry(
121                            title, StringPool.BLANK, description, content, displayDateMonth,
122                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
123                            allowPingbacks, allowTrackbacks, trackbacks, StringPool.BLANK,
124                            coverImageImageSelector, smallImageImageSelector, serviceContext);
125            }
126    
127            @Override
128            public BlogsEntry addEntry(
129                            String title, String subtitle, String description, String content,
130                            int displayDateMonth, int displayDateDay, int displayDateYear,
131                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
132                            boolean allowTrackbacks, String[] trackbacks,
133                            String coverImageCaption, ImageSelector coverImageImageSelector,
134                            ImageSelector smallImageImageSelector,
135                            ServiceContext serviceContext)
136                    throws PortalException {
137    
138                    BlogsPermission.check(
139                            getPermissionChecker(), serviceContext.getScopeGroupId(),
140                            ActionKeys.ADD_ENTRY);
141    
142                    return blogsEntryLocalService.addEntry(
143                            getUserId(), title, subtitle, description, content,
144                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
145                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
146                            coverImageCaption, coverImageImageSelector, smallImageImageSelector,
147                            serviceContext);
148            }
149    
150            @Override
151            public void deleteEntry(long entryId) throws PortalException {
152                    BlogsEntryPermission.check(
153                            getPermissionChecker(), entryId, ActionKeys.DELETE);
154    
155                    blogsEntryLocalService.deleteEntry(entryId);
156            }
157    
158            @Override
159            public List<BlogsEntry> getCompanyEntries(
160                            long companyId, Date displayDate, int status, int max)
161                    throws PortalException {
162    
163                    List<BlogsEntry> entries = new ArrayList<>();
164    
165                    boolean listNotExhausted = true;
166    
167                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
168                            status, false, 0, 0, new EntryDisplayDateComparator());
169    
170                    if (status == WorkflowConstants.STATUS_ANY) {
171                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
172                    }
173    
174                    while ((entries.size() < max) && listNotExhausted) {
175                            queryDefinition.setEnd(queryDefinition.getStart() + max);
176    
177                            List<BlogsEntry> entryList =
178                                    blogsEntryLocalService.getCompanyEntries(
179                                            companyId, displayDate, queryDefinition);
180    
181                            queryDefinition.setStart(queryDefinition.getStart() + max);
182    
183                            listNotExhausted = (entryList.size() == max);
184    
185                            for (BlogsEntry entry : entryList) {
186                                    if (entries.size() >= max) {
187                                            break;
188                                    }
189    
190                                    if (BlogsEntryPermission.contains(
191                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
192    
193                                            entries.add(entry);
194                                    }
195                            }
196                    }
197    
198                    return entries;
199            }
200    
201            @Override
202            public String getCompanyEntriesRSS(
203                            long companyId, Date displayDate, int status, int max, String type,
204                            double version, String displayStyle, String feedURL,
205                            String entryURL, ThemeDisplay themeDisplay)
206                    throws PortalException {
207    
208                    Company company = companyPersistence.findByPrimaryKey(companyId);
209    
210                    String name = company.getName();
211                    List<BlogsEntry> blogsEntries = getCompanyEntries(
212                            companyId, displayDate, status, max);
213    
214                    return exportToRSS(
215                            name, name, type, version, displayStyle, feedURL, entryURL,
216                            blogsEntries, themeDisplay);
217            }
218    
219            @Override
220            public BlogsEntry getEntry(long entryId) throws PortalException {
221                    BlogsEntryPermission.check(
222                            getPermissionChecker(), entryId, ActionKeys.VIEW);
223    
224                    return blogsEntryLocalService.getEntry(entryId);
225            }
226    
227            @Override
228            public BlogsEntry getEntry(long groupId, String urlTitle)
229                    throws PortalException {
230    
231                    BlogsEntry entry = blogsEntryLocalService.getEntry(groupId, urlTitle);
232    
233                    BlogsEntryPermission.check(
234                            getPermissionChecker(), entry.getEntryId(), ActionKeys.VIEW);
235    
236                    return entry;
237            }
238    
239            @Override
240            public List<BlogsEntry> getGroupEntries(
241                    long groupId, Date displayDate, int status, int max) {
242    
243                    return getGroupEntries(groupId, displayDate, status, 0, max);
244            }
245    
246            @Override
247            public List<BlogsEntry> getGroupEntries(
248                    long groupId, Date displayDate, int status, int start, int end) {
249    
250                    if (status == WorkflowConstants.STATUS_ANY) {
251                            return blogsEntryPersistence.filterFindByG_LtD_NotS(
252                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH, start,
253                                    end);
254                    }
255                    else {
256                            return blogsEntryPersistence.filterFindByG_LtD_S(
257                                    groupId, displayDate, status, start, end);
258                    }
259            }
260    
261            @Override
262            public List<BlogsEntry> getGroupEntries(long groupId, int status, int max) {
263                    return getGroupEntries(groupId, status, 0, max);
264            }
265    
266            @Override
267            public List<BlogsEntry> getGroupEntries(
268                    long groupId, int status, int start, int end) {
269    
270                    if (status == WorkflowConstants.STATUS_ANY) {
271                            return blogsEntryPersistence.filterFindByG_NotS(
272                                    groupId, WorkflowConstants.STATUS_IN_TRASH, start, end);
273                    }
274                    else {
275                            return blogsEntryPersistence.filterFindByG_S(
276                                    groupId, status, start, end);
277                    }
278            }
279    
280            @Override
281            public List<BlogsEntry> getGroupEntries(
282                    long groupId, int status, int start, int end,
283                    OrderByComparator<BlogsEntry> obc) {
284    
285                    if (status == WorkflowConstants.STATUS_ANY) {
286                            return blogsEntryPersistence.filterFindByG_NotS(
287                                    groupId, WorkflowConstants.STATUS_IN_TRASH, start, end, obc);
288                    }
289                    else {
290                            return blogsEntryPersistence.filterFindByG_S(
291                                    groupId, status, start, end, obc);
292                    }
293            }
294    
295            @Override
296            public int getGroupEntriesCount(
297                    long groupId, Date displayDate, int status) {
298    
299                    if (status == WorkflowConstants.STATUS_ANY) {
300                            return blogsEntryPersistence.filterCountByG_LtD_NotS(
301                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH);
302                    }
303                    else {
304                            return blogsEntryPersistence.filterCountByG_LtD_S(
305                                    groupId, displayDate, status);
306                    }
307            }
308    
309            @Override
310            public int getGroupEntriesCount(long groupId, int status) {
311                    if (status == WorkflowConstants.STATUS_ANY) {
312                            return blogsEntryPersistence.filterCountByG_NotS(
313                                    groupId, WorkflowConstants.STATUS_IN_TRASH);
314                    }
315                    else {
316                            return blogsEntryPersistence.filterCountByG_S(groupId, status);
317                    }
318            }
319    
320            @Override
321            public String getGroupEntriesRSS(
322                            long groupId, Date displayDate, int status, int max, String type,
323                            double version, String displayStyle, String feedURL,
324                            String entryURL, ThemeDisplay themeDisplay)
325                    throws PortalException {
326    
327                    Group group = groupPersistence.findByPrimaryKey(groupId);
328    
329                    String name = group.getDescriptiveName();
330                    List<BlogsEntry> blogsEntries = getGroupEntries(
331                            groupId, displayDate, status, max);
332    
333                    return exportToRSS(
334                            name, name, type, version, displayStyle, feedURL, entryURL,
335                            blogsEntries, themeDisplay);
336            }
337    
338            @Override
339            public List<BlogsEntry> getGroupsEntries(
340                            long companyId, long groupId, Date displayDate, int status, int max)
341                    throws PortalException {
342    
343                    List<BlogsEntry> entries = new ArrayList<>();
344    
345                    boolean listNotExhausted = true;
346    
347                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
348                            status, false, 0, 0, new EntryDisplayDateComparator());
349    
350                    if (status == WorkflowConstants.STATUS_ANY) {
351                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
352                    }
353    
354                    while ((entries.size() < max) && listNotExhausted) {
355                            queryDefinition.setEnd(queryDefinition.getStart() + max);
356    
357                            List<BlogsEntry> entryList =
358                                    blogsEntryLocalService.getGroupsEntries(
359                                            companyId, groupId, displayDate, queryDefinition);
360    
361                            queryDefinition.setStart(queryDefinition.getStart() + max);
362    
363                            listNotExhausted = (entryList.size() == max);
364    
365                            for (BlogsEntry entry : entryList) {
366                                    if (entries.size() >= max) {
367                                            break;
368                                    }
369    
370                                    if (BlogsEntryPermission.contains(
371                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
372    
373                                            entries.add(entry);
374                                    }
375                            }
376                    }
377    
378                    return entries;
379            }
380    
381            @Override
382            public List<BlogsEntry> getGroupUserEntries(
383                    long groupId, long userId, int status, int start, int end,
384                    OrderByComparator<BlogsEntry> obc) {
385    
386                    if (status == WorkflowConstants.STATUS_ANY) {
387                            return blogsEntryPersistence.filterFindByG_U_NotS(
388                                    groupId, userId, WorkflowConstants.STATUS_IN_TRASH, start, end,
389                                    obc);
390                    }
391                    else {
392                            return blogsEntryPersistence.filterFindByG_U_S(
393                                    groupId, userId, status, start, end, obc);
394                    }
395            }
396    
397            @Override
398            public int getGroupUserEntriesCount(long groupId, long userId, int status) {
399                    if (status == WorkflowConstants.STATUS_ANY) {
400                            return blogsEntryPersistence.filterCountByG_U_NotS(
401                                    groupId, userId, WorkflowConstants.STATUS_IN_TRASH);
402                    }
403                    else {
404                            return blogsEntryPersistence.filterCountByG_U_S(
405                                    groupId, userId, status);
406                    }
407            }
408    
409            @Override
410            public List<BlogsEntry> getOrganizationEntries(
411                            long organizationId, Date displayDate, int status, int max)
412                    throws PortalException {
413    
414                    List<BlogsEntry> entries = new ArrayList<>();
415    
416                    boolean listNotExhausted = true;
417    
418                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
419                            status, false, 0, 0, new EntryDisplayDateComparator());
420    
421                    if (status == WorkflowConstants.STATUS_ANY) {
422                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
423                    }
424    
425                    while ((entries.size() < max) && listNotExhausted) {
426                            queryDefinition.setEnd(queryDefinition.getStart() + max);
427    
428                            List<BlogsEntry> entryList = blogsEntryFinder.findByOrganizationId(
429                                    organizationId, displayDate, queryDefinition);
430    
431                            queryDefinition.setStart(queryDefinition.getStart() + max);
432    
433                            listNotExhausted = (entryList.size() == max);
434    
435                            for (BlogsEntry entry : entryList) {
436                                    if (entries.size() >= max) {
437                                            break;
438                                    }
439    
440                                    if (BlogsEntryPermission.contains(
441                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
442    
443                                            entries.add(entry);
444                                    }
445                            }
446                    }
447    
448                    return entries;
449            }
450    
451            @Override
452            public String getOrganizationEntriesRSS(
453                            long organizationId, Date displayDate, int status, int max,
454                            String type, double version, String displayStyle, String feedURL,
455                            String entryURL, ThemeDisplay themeDisplay)
456                    throws PortalException {
457    
458                    Organization organization = organizationPersistence.findByPrimaryKey(
459                            organizationId);
460    
461                    String name = organization.getName();
462                    List<BlogsEntry> blogsEntries = getOrganizationEntries(
463                            organizationId, displayDate, status, max);
464    
465                    return exportToRSS(
466                            name, name, type, version, displayStyle, feedURL, entryURL,
467                            blogsEntries, themeDisplay);
468            }
469    
470            @Override
471            public BlogsEntry moveEntryToTrash(long entryId) throws PortalException {
472                    BlogsEntryPermission.check(
473                            getPermissionChecker(), entryId, ActionKeys.DELETE);
474    
475                    return blogsEntryLocalService.moveEntryToTrash(getUserId(), entryId);
476            }
477    
478            @Override
479            public void restoreEntryFromTrash(long entryId) throws PortalException {
480                    BlogsEntryPermission.check(
481                            getPermissionChecker(), entryId, ActionKeys.DELETE);
482    
483                    blogsEntryLocalService.restoreEntryFromTrash(getUserId(), entryId);
484            }
485    
486            @Override
487            public void subscribe(long groupId) throws PortalException {
488                    BlogsPermission.check(
489                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
490    
491                    blogsEntryLocalService.subscribe(getUserId(), groupId);
492            }
493    
494            @Override
495            public void unsubscribe(long groupId) throws PortalException {
496                    BlogsPermission.check(
497                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
498    
499                    blogsEntryLocalService.unsubscribe(getUserId(), groupId);
500            }
501    
502            /**
503             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, String,
504             *             String, String, String, int, int, int, int, int, boolean,
505             *             boolean, String[], String, ImageSelector, ImageSelector,
506             *             ServiceContext)}
507             */
508            @Deprecated
509            @Override
510            public BlogsEntry updateEntry(
511                            long entryId, String title, String description, String content,
512                            int displayDateMonth, int displayDateDay, int displayDateYear,
513                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
514                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
515                            String smallImageURL, String smallImageFileName,
516                            InputStream smallImageInputStream, ServiceContext serviceContext)
517                    throws PortalException {
518    
519                    BlogsPermission.check(
520                            getPermissionChecker(), serviceContext.getScopeGroupId(),
521                            ActionKeys.UPDATE);
522    
523                    ImageSelector coverImageImageSelector = null;
524                    ImageSelector smallImageImageSelector = null;
525    
526                    if (smallImage) {
527                            if (Validator.isNotNull(smallImageFileName) &&
528                                    (smallImageInputStream != null)) {
529    
530                                    try {
531                                            byte[] bytes = FileUtil.getBytes(smallImageInputStream);
532    
533                                            smallImageImageSelector = new ImageSelector(
534                                                    bytes, smallImageFileName,
535                                                    MimeTypesUtil.getContentType(smallImageFileName), null);
536                                    }
537                                    catch (IOException ioe) {
538                                            if (_log.isErrorEnabled()) {
539                                                    _log.error("Unable to create image selector", ioe);
540                                            }
541                                    }
542                            }
543                            else if (Validator.isNotNull(smallImageURL)) {
544                                    smallImageImageSelector = new ImageSelector(smallImageURL);
545                            }
546                    }
547                    else {
548                            smallImageImageSelector = new ImageSelector();
549                    }
550    
551                    return updateEntry(
552                            entryId, title, StringPool.BLANK, description, content,
553                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
554                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
555                            StringPool.BLANK, coverImageImageSelector, smallImageImageSelector,
556                            serviceContext);
557            }
558    
559            @Override
560            public BlogsEntry updateEntry(
561                            long entryId, String title, String subtitle, String description,
562                            String content, int displayDateMonth, int displayDateDay,
563                            int displayDateYear, int displayDateHour, int displayDateMinute,
564                            boolean allowPingbacks, boolean allowTrackbacks,
565                            String[] trackbacks, String coverImageCaption,
566                            ImageSelector coverImageImageSelector,
567                            ImageSelector smallImageImageSelector,
568                            ServiceContext serviceContext)
569                    throws PortalException {
570    
571                    BlogsEntryPermission.check(
572                            getPermissionChecker(), entryId, ActionKeys.UPDATE);
573    
574                    return blogsEntryLocalService.updateEntry(
575                            getUserId(), entryId, title, subtitle, description, content,
576                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
577                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
578                            coverImageCaption, coverImageImageSelector, smallImageImageSelector,
579                            serviceContext);
580            }
581    
582            protected String exportToRSS(
583                    String name, String description, String type, double version,
584                    String displayStyle, String feedURL, String entryURL,
585                    List<BlogsEntry> blogsEntries, ThemeDisplay themeDisplay) {
586    
587                    SyndFeed syndFeed = new SyndFeedImpl();
588    
589                    syndFeed.setDescription(description);
590    
591                    List<SyndEntry> syndEntries = new ArrayList<>();
592    
593                    syndFeed.setEntries(syndEntries);
594    
595                    for (BlogsEntry entry : blogsEntries) {
596                            SyndEntry syndEntry = new SyndEntryImpl();
597    
598                            String author = PortalUtil.getUserName(entry);
599    
600                            syndEntry.setAuthor(author);
601    
602                            SyndContent syndContent = new SyndContentImpl();
603    
604                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
605    
606                            String value = null;
607    
608                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
609                                    String summary = entry.getDescription();
610    
611                                    if (Validator.isNull(summary)) {
612                                            summary = entry.getContent();
613                                    }
614    
615                                    value = StringUtil.shorten(
616                                            HtmlUtil.extractText(summary),
617                                            PropsValues.BLOGS_RSS_ABSTRACT_LENGTH, StringPool.BLANK);
618                            }
619                            else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
620                                    value = StringPool.BLANK;
621                            }
622                            else {
623                                    value = StringUtil.replace(
624                                            entry.getContent(), new String[] {"href=\"/", "src=\"/"},
625                                            new String[] {
626                                                    "href=\"" + themeDisplay.getURLPortal() + "/",
627                                                    "src=\"" + themeDisplay.getURLPortal() + "/"
628                                            });
629                            }
630    
631                            syndContent.setValue(value);
632    
633                            syndEntry.setDescription(syndContent);
634    
635                            StringBundler sb = new StringBundler(4);
636    
637                            sb.append(entryURL);
638    
639                            if (!entryURL.endsWith(StringPool.QUESTION)) {
640                                    sb.append(StringPool.AMPERSAND);
641                            }
642    
643                            sb.append("entryId=");
644                            sb.append(entry.getEntryId());
645    
646                            String link = sb.toString();
647    
648                            syndEntry.setLink(link);
649    
650                            syndEntry.setPublishedDate(entry.getDisplayDate());
651                            syndEntry.setTitle(entry.getTitle());
652                            syndEntry.setUpdatedDate(entry.getModifiedDate());
653                            syndEntry.setUri(link);
654    
655                            syndEntries.add(syndEntry);
656                    }
657    
658                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
659    
660                    List<SyndLink> syndLinks = new ArrayList<>();
661    
662                    syndFeed.setLinks(syndLinks);
663    
664                    SyndLink selfSyndLink = new SyndLinkImpl();
665    
666                    syndLinks.add(selfSyndLink);
667    
668                    selfSyndLink.setHref(feedURL);
669                    selfSyndLink.setRel("self");
670    
671                    syndFeed.setPublishedDate(new Date());
672                    syndFeed.setTitle(name);
673                    syndFeed.setUri(feedURL);
674    
675                    try {
676                            return RSSUtil.export(syndFeed);
677                    }
678                    catch (FeedException fe) {
679                            throw new SystemException(fe);
680                    }
681            }
682    
683            private static final Log _log = LogFactoryUtil.getLog(
684                    BlogsEntryServiceImpl.class);
685    
686    }