001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.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.util.HtmlUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
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.Organization;
029    import com.liferay.portal.security.permission.ActionKeys;
030    import com.liferay.portal.service.ServiceContext;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portal.util.PropsValues;
034    import com.liferay.portlet.blogs.model.BlogsEntry;
035    import com.liferay.portlet.blogs.service.base.BlogsEntryServiceBaseImpl;
036    import com.liferay.portlet.blogs.service.permission.BlogsEntryPermission;
037    import com.liferay.portlet.blogs.service.permission.BlogsPermission;
038    import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
039    import com.liferay.util.RSSUtil;
040    
041    import com.sun.syndication.feed.synd.SyndContent;
042    import com.sun.syndication.feed.synd.SyndContentImpl;
043    import com.sun.syndication.feed.synd.SyndEntry;
044    import com.sun.syndication.feed.synd.SyndEntryImpl;
045    import com.sun.syndication.feed.synd.SyndFeed;
046    import com.sun.syndication.feed.synd.SyndFeedImpl;
047    import com.sun.syndication.feed.synd.SyndLink;
048    import com.sun.syndication.feed.synd.SyndLinkImpl;
049    import com.sun.syndication.io.FeedException;
050    
051    import java.io.InputStream;
052    
053    import java.util.ArrayList;
054    import java.util.Date;
055    import java.util.List;
056    
057    /**
058     * Provides the remote service for accessing, adding, deleting, subscription
059     * handling of, trash handling of, and updating blog entries. Its methods
060     * include permission checks.
061     *
062     * @author Brian Wing Shun Chan
063     * @author Mate Thurzo
064     */
065    public class BlogsEntryServiceImpl extends BlogsEntryServiceBaseImpl {
066    
067            public BlogsEntry addEntry(
068                            String title, String description, String content,
069                            int displayDateMonth, int displayDateDay, int displayDateYear,
070                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
071                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
072                            String smallImageURL, String smallImageFileName,
073                            InputStream smallImageInputStream, ServiceContext serviceContext)
074                    throws PortalException, SystemException {
075    
076                    BlogsPermission.check(
077                            getPermissionChecker(), serviceContext.getScopeGroupId(),
078                            ActionKeys.ADD_ENTRY);
079    
080                    return blogsEntryLocalService.addEntry(
081                            getUserId(), title, description, content, displayDateMonth,
082                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
083                            allowPingbacks, allowTrackbacks, trackbacks, smallImage,
084                            smallImageURL, smallImageFileName, smallImageInputStream,
085                            serviceContext);
086            }
087    
088            public void deleteEntry(long entryId)
089                    throws PortalException, SystemException {
090    
091                    BlogsEntryPermission.check(
092                            getPermissionChecker(), entryId, ActionKeys.DELETE);
093    
094                    blogsEntryLocalService.deleteEntry(entryId);
095            }
096    
097            public List<BlogsEntry> getCompanyEntries(
098                            long companyId, Date displayDate, int status, int max)
099                    throws PortalException, SystemException {
100    
101                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
102    
103                    boolean listNotExhausted = true;
104    
105                    QueryDefinition queryDefinition = new QueryDefinition(
106                            status, false, 0, 0, new EntryDisplayDateComparator());
107    
108                    if (status == WorkflowConstants.STATUS_ANY) {
109                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
110                    }
111    
112                    while ((entries.size() < max) && listNotExhausted) {
113                            queryDefinition.setEnd(queryDefinition.getStart() + max);
114    
115                            List<BlogsEntry> entryList =
116                                    blogsEntryLocalService.getCompanyEntries(
117                                            companyId, displayDate, queryDefinition);
118    
119                            queryDefinition.setStart(queryDefinition.getStart() + max);
120    
121                            listNotExhausted = (entryList.size() == max);
122    
123                            for (BlogsEntry entry : entryList) {
124                                    if (entries.size() >= max) {
125                                            break;
126                                    }
127    
128                                    if (BlogsEntryPermission.contains(
129                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
130    
131                                            entries.add(entry);
132                                    }
133                            }
134                    }
135    
136                    return entries;
137            }
138    
139            public String getCompanyEntriesRSS(
140                            long companyId, Date displayDate, int status, int max, String type,
141                            double version, String displayStyle, String feedURL,
142                            String entryURL, ThemeDisplay themeDisplay)
143                    throws PortalException, SystemException {
144    
145                    Company company = companyPersistence.findByPrimaryKey(companyId);
146    
147                    String name = company.getName();
148                    List<BlogsEntry> blogsEntries = getCompanyEntries(
149                            companyId, displayDate, status, max);
150    
151                    return exportToRSS(
152                            name, name, type, version, displayStyle, feedURL, entryURL,
153                            blogsEntries, themeDisplay);
154            }
155    
156            public BlogsEntry getEntry(long entryId)
157                    throws PortalException, SystemException {
158    
159                    BlogsEntryPermission.check(
160                            getPermissionChecker(), entryId, ActionKeys.VIEW);
161    
162                    return blogsEntryLocalService.getEntry(entryId);
163            }
164    
165            public BlogsEntry getEntry(long groupId, String urlTitle)
166                    throws PortalException, SystemException {
167    
168                    BlogsEntry entry = blogsEntryLocalService.getEntry(groupId, urlTitle);
169    
170                    BlogsEntryPermission.check(
171                            getPermissionChecker(), entry.getEntryId(), ActionKeys.VIEW);
172    
173                    return entry;
174            }
175    
176            public List<BlogsEntry> getGroupEntries(
177                            long groupId, Date displayDate, int status, int max)
178                    throws SystemException {
179    
180                    return getGroupEntries(groupId, displayDate, status, 0, max);
181            }
182    
183            public List<BlogsEntry> getGroupEntries(
184                            long groupId, Date displayDate, int status, int start, int end)
185                    throws SystemException {
186    
187                    if (status == WorkflowConstants.STATUS_ANY) {
188                            return blogsEntryPersistence.filterFindByG_LtD_NotS(
189                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH, start,
190                                    end);
191                    }
192                    else {
193                            return blogsEntryPersistence.filterFindByG_LtD_S(
194                                    groupId, displayDate, status, start, end);
195                    }
196            }
197    
198            public List<BlogsEntry> getGroupEntries(long groupId, int status, int max)
199                    throws SystemException {
200    
201                    return getGroupEntries(groupId, status, 0, max);
202            }
203    
204            public List<BlogsEntry> getGroupEntries(
205                            long groupId, int status, int start, int end)
206                    throws SystemException {
207    
208                    if (status == WorkflowConstants.STATUS_ANY) {
209                            return blogsEntryPersistence.filterFindByG_NotS(
210                                    groupId, WorkflowConstants.STATUS_IN_TRASH, start, end);
211                    }
212                    else {
213                            return blogsEntryPersistence.filterFindByG_S(
214                                    groupId, status, start, end);
215                    }
216            }
217    
218            public int getGroupEntriesCount(long groupId, Date displayDate, int status)
219                    throws SystemException {
220    
221                    if (status == WorkflowConstants.STATUS_ANY) {
222                            return blogsEntryPersistence.filterCountByG_LtD_NotS(
223                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH);
224                    }
225                    else {
226                            return blogsEntryPersistence.filterCountByG_LtD_S(
227                                    groupId, displayDate, status);
228                    }
229            }
230    
231            public int getGroupEntriesCount(long groupId, int status)
232                    throws SystemException {
233    
234                    if (status == WorkflowConstants.STATUS_ANY) {
235                            return blogsEntryPersistence.filterCountByG_NotS(
236                                    groupId, WorkflowConstants.STATUS_IN_TRASH);
237                    }
238                    else {
239                            return blogsEntryPersistence.filterCountByG_S(groupId, status);
240                    }
241            }
242    
243            public String getGroupEntriesRSS(
244                            long groupId, Date displayDate, int status, int max, String type,
245                            double version, String displayStyle, String feedURL,
246                            String entryURL, ThemeDisplay themeDisplay)
247                    throws PortalException, SystemException {
248    
249                    Group group = groupPersistence.findByPrimaryKey(groupId);
250    
251                    String name = group.getDescriptiveName();
252                    List<BlogsEntry> blogsEntries = getGroupEntries(
253                            groupId, displayDate, status, max);
254    
255                    return exportToRSS(
256                            name, name, type, version, displayStyle, feedURL, entryURL,
257                            blogsEntries, themeDisplay);
258            }
259    
260            public List<BlogsEntry> getGroupsEntries(
261                            long companyId, long groupId, Date displayDate, int status, int max)
262                    throws PortalException, SystemException {
263    
264                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
265    
266                    boolean listNotExhausted = true;
267    
268                    QueryDefinition queryDefinition = new QueryDefinition(
269                            status, false, 0, 0, new EntryDisplayDateComparator());
270    
271                    if (status == WorkflowConstants.STATUS_ANY) {
272                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
273                    }
274    
275                    while ((entries.size() < max) && listNotExhausted) {
276                            queryDefinition.setEnd(queryDefinition.getStart() + max);
277    
278                            List<BlogsEntry> entryList =
279                                    blogsEntryLocalService.getGroupsEntries(
280                                            companyId, groupId, displayDate, queryDefinition);
281    
282                            queryDefinition.setStart(queryDefinition.getStart() + max);
283    
284                            listNotExhausted = (entryList.size() == max);
285    
286                            for (BlogsEntry entry : entryList) {
287                                    if (entries.size() >= max) {
288                                            break;
289                                    }
290    
291                                    if (BlogsEntryPermission.contains(
292                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
293    
294                                            entries.add(entry);
295                                    }
296                            }
297                    }
298    
299                    return entries;
300            }
301    
302            public List<BlogsEntry> getOrganizationEntries(
303                            long organizationId, Date displayDate, int status, int max)
304                    throws PortalException, SystemException {
305    
306                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
307    
308                    boolean listNotExhausted = true;
309    
310                    QueryDefinition queryDefinition = new QueryDefinition(
311                            status, false, 0, 0, new EntryDisplayDateComparator());
312    
313                    if (status == WorkflowConstants.STATUS_ANY) {
314                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
315                    }
316    
317                    while ((entries.size() < max) && listNotExhausted) {
318                            queryDefinition.setEnd(queryDefinition.getStart() + max);
319    
320                            List<BlogsEntry> entryList = blogsEntryFinder.findByOrganizationId(
321                                    organizationId, displayDate, queryDefinition);
322    
323                            queryDefinition.setStart(queryDefinition.getStart() + max);
324    
325                            listNotExhausted = (entryList.size() == max);
326    
327                            for (BlogsEntry entry : entryList) {
328                                    if (entries.size() >= max) {
329                                            break;
330                                    }
331    
332                                    if (BlogsEntryPermission.contains(
333                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
334    
335                                            entries.add(entry);
336                                    }
337                            }
338                    }
339    
340                    return entries;
341            }
342    
343            public String getOrganizationEntriesRSS(
344                            long organizationId, Date displayDate, int status, int max,
345                            String type, double version, String displayStyle, String feedURL,
346                            String entryURL, ThemeDisplay themeDisplay)
347                    throws PortalException, SystemException {
348    
349                    Organization organization = organizationPersistence.findByPrimaryKey(
350                            organizationId);
351    
352                    String name = organization.getName();
353                    List<BlogsEntry> blogsEntries = getOrganizationEntries(
354                            organizationId, displayDate, status, max);
355    
356                    return exportToRSS(
357                            name, name, type, version, displayStyle, feedURL, entryURL,
358                            blogsEntries, themeDisplay);
359            }
360    
361            public void moveEntryToTrash(long entryId)
362                    throws PortalException, SystemException {
363    
364                    BlogsEntryPermission.check(
365                            getPermissionChecker(), entryId, ActionKeys.DELETE);
366    
367                    blogsEntryLocalService.moveEntryToTrash(getUserId(), entryId);
368            }
369    
370            public void restoreEntryFromTrash(long entryId)
371                    throws PortalException, SystemException {
372    
373                    BlogsEntryPermission.check(
374                            getPermissionChecker(), entryId, ActionKeys.DELETE);
375    
376                    blogsEntryLocalService.restoreEntryFromTrash(getUserId(), entryId);
377            }
378    
379            public void subscribe(long groupId)
380                    throws PortalException, SystemException {
381    
382                    BlogsPermission.check(
383                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
384    
385                    blogsEntryLocalService.subscribe(getUserId(), groupId);
386            }
387    
388            public void unsubscribe(long groupId)
389                    throws PortalException, SystemException {
390    
391                    BlogsPermission.check(
392                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
393    
394                    blogsEntryLocalService.unsubscribe(getUserId(), groupId);
395            }
396    
397            public BlogsEntry updateEntry(
398                            long entryId, String title, String description, String content,
399                            int displayDateMonth, int displayDateDay, int displayDateYear,
400                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
401                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
402                            String smallImageURL, String smallImageFileName,
403                            InputStream smallImageInputStream, ServiceContext serviceContext)
404                    throws PortalException, SystemException {
405    
406                    BlogsEntryPermission.check(
407                            getPermissionChecker(), entryId, ActionKeys.UPDATE);
408    
409                    return blogsEntryLocalService.updateEntry(
410                            getUserId(), entryId, title, description, content, displayDateMonth,
411                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
412                            allowPingbacks, allowTrackbacks, trackbacks, smallImage,
413                            smallImageURL, smallImageFileName, smallImageInputStream,
414                            serviceContext);
415            }
416    
417            protected String exportToRSS(
418                            String name, String description, String type, double version,
419                            String displayStyle, String feedURL, String entryURL,
420                            List<BlogsEntry> blogsEntries, ThemeDisplay themeDisplay)
421                    throws SystemException {
422    
423                    SyndFeed syndFeed = new SyndFeedImpl();
424    
425                    syndFeed.setDescription(description);
426    
427                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
428    
429                    syndFeed.setEntries(syndEntries);
430    
431                    for (BlogsEntry entry : blogsEntries) {
432                            SyndEntry syndEntry = new SyndEntryImpl();
433    
434                            String author = PortalUtil.getUserName(entry);
435    
436                            syndEntry.setAuthor(author);
437    
438                            SyndContent syndContent = new SyndContentImpl();
439    
440                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
441    
442                            String value = null;
443    
444                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
445                                    String summary = entry.getDescription();
446    
447                                    if (Validator.isNull(summary)) {
448                                            summary = entry.getContent();
449                                    }
450    
451                                    value = StringUtil.shorten(
452                                            HtmlUtil.extractText(summary),
453                                            PropsValues.BLOGS_RSS_ABSTRACT_LENGTH, StringPool.BLANK);
454                            }
455                            else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
456                                    value = StringPool.BLANK;
457                            }
458                            else {
459                                    value = StringUtil.replace(
460                                            entry.getContent(),
461                                            new String[] {
462                                                    "href=\"/", "src=\"/"
463                                            },
464                                            new String[] {
465                                                    "href=\"" + themeDisplay.getURLPortal() + "/",
466                                                    "src=\"" + themeDisplay.getURLPortal() + "/"
467                                            });
468                            }
469    
470                            syndContent.setValue(value);
471    
472                            syndEntry.setDescription(syndContent);
473    
474                            StringBundler sb = new StringBundler(4);
475    
476                            if (entryURL.endsWith("/blogs/rss")) {
477                                    sb.append(entryURL.substring(0, entryURL.length() - 3));
478                                    sb.append(entry.getUrlTitle());
479                            }
480                            else {
481                                    sb.append(entryURL);
482    
483                                    if (!entryURL.endsWith(StringPool.QUESTION)) {
484                                            sb.append(StringPool.AMPERSAND);
485                                    }
486    
487                                    sb.append("entryId=");
488                                    sb.append(entry.getEntryId());
489                            }
490    
491                            String link = sb.toString();
492    
493                            syndEntry.setLink(link);
494    
495                            syndEntry.setPublishedDate(entry.getDisplayDate());
496                            syndEntry.setTitle(entry.getTitle());
497                            syndEntry.setUpdatedDate(entry.getModifiedDate());
498                            syndEntry.setUri(link);
499    
500                            syndEntries.add(syndEntry);
501                    }
502    
503                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
504    
505                    List<SyndLink> syndLinks = new ArrayList<SyndLink>();
506    
507                    syndFeed.setLinks(syndLinks);
508    
509                    SyndLink selfSyndLink = new SyndLinkImpl();
510    
511                    syndLinks.add(selfSyndLink);
512    
513                    selfSyndLink.setHref(feedURL);
514                    selfSyndLink.setRel("self");
515    
516                    if (feedURL.endsWith("/-/blogs/rss")) {
517                            SyndLink alternateSyndLink = new SyndLinkImpl();
518    
519                            syndLinks.add(alternateSyndLink);
520    
521                            alternateSyndLink.setHref(
522                                    feedURL.substring(0, feedURL.length() - 12));
523                            alternateSyndLink.setRel("alternate");
524                    }
525    
526                    syndFeed.setPublishedDate(new Date());
527                    syndFeed.setTitle(name);
528                    syndFeed.setUri(feedURL);
529    
530                    try {
531                            return RSSUtil.export(syndFeed);
532                    }
533                    catch (FeedException fe) {
534                            throw new SystemException(fe);
535                    }
536            }
537    
538    }