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            @Override
068            public BlogsEntry addEntry(
069                            String title, String description, String content,
070                            int displayDateMonth, int displayDateDay, int displayDateYear,
071                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
072                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
073                            String smallImageURL, String smallImageFileName,
074                            InputStream smallImageInputStream, ServiceContext serviceContext)
075                    throws PortalException, SystemException {
076    
077                    BlogsPermission.check(
078                            getPermissionChecker(), serviceContext.getScopeGroupId(),
079                            ActionKeys.ADD_ENTRY);
080    
081                    return blogsEntryLocalService.addEntry(
082                            getUserId(), title, description, content, displayDateMonth,
083                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
084                            allowPingbacks, allowTrackbacks, trackbacks, smallImage,
085                            smallImageURL, smallImageFileName, smallImageInputStream,
086                            serviceContext);
087            }
088    
089            @Override
090            public void deleteEntry(long entryId)
091                    throws PortalException, SystemException {
092    
093                    BlogsEntryPermission.check(
094                            getPermissionChecker(), entryId, ActionKeys.DELETE);
095    
096                    blogsEntryLocalService.deleteEntry(entryId);
097            }
098    
099            @Override
100            public List<BlogsEntry> getCompanyEntries(
101                            long companyId, Date displayDate, int status, int max)
102                    throws PortalException, SystemException {
103    
104                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
105    
106                    boolean listNotExhausted = true;
107    
108                    QueryDefinition queryDefinition = new QueryDefinition(
109                            status, false, 0, 0, new EntryDisplayDateComparator());
110    
111                    if (status == WorkflowConstants.STATUS_ANY) {
112                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
113                    }
114    
115                    while ((entries.size() < max) && listNotExhausted) {
116                            queryDefinition.setEnd(queryDefinition.getStart() + max);
117    
118                            List<BlogsEntry> entryList =
119                                    blogsEntryLocalService.getCompanyEntries(
120                                            companyId, displayDate, queryDefinition);
121    
122                            queryDefinition.setStart(queryDefinition.getStart() + max);
123    
124                            listNotExhausted = (entryList.size() == max);
125    
126                            for (BlogsEntry entry : entryList) {
127                                    if (entries.size() >= max) {
128                                            break;
129                                    }
130    
131                                    if (BlogsEntryPermission.contains(
132                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
133    
134                                            entries.add(entry);
135                                    }
136                            }
137                    }
138    
139                    return entries;
140            }
141    
142            @Override
143            public String getCompanyEntriesRSS(
144                            long companyId, Date displayDate, int status, int max, String type,
145                            double version, String displayStyle, String feedURL,
146                            String entryURL, ThemeDisplay themeDisplay)
147                    throws PortalException, SystemException {
148    
149                    Company company = companyPersistence.findByPrimaryKey(companyId);
150    
151                    String name = company.getName();
152                    List<BlogsEntry> blogsEntries = getCompanyEntries(
153                            companyId, displayDate, status, max);
154    
155                    return exportToRSS(
156                            name, name, type, version, displayStyle, feedURL, entryURL,
157                            blogsEntries, themeDisplay);
158            }
159    
160            @Override
161            public BlogsEntry getEntry(long entryId)
162                    throws PortalException, SystemException {
163    
164                    BlogsEntryPermission.check(
165                            getPermissionChecker(), entryId, ActionKeys.VIEW);
166    
167                    return blogsEntryLocalService.getEntry(entryId);
168            }
169    
170            @Override
171            public BlogsEntry getEntry(long groupId, String urlTitle)
172                    throws PortalException, SystemException {
173    
174                    BlogsEntry entry = blogsEntryLocalService.getEntry(groupId, urlTitle);
175    
176                    BlogsEntryPermission.check(
177                            getPermissionChecker(), entry.getEntryId(), ActionKeys.VIEW);
178    
179                    return entry;
180            }
181    
182            @Override
183            public List<BlogsEntry> getGroupEntries(
184                            long groupId, Date displayDate, int status, int max)
185                    throws SystemException {
186    
187                    return getGroupEntries(groupId, displayDate, status, 0, max);
188            }
189    
190            @Override
191            public List<BlogsEntry> getGroupEntries(
192                            long groupId, Date displayDate, int status, int start, int end)
193                    throws SystemException {
194    
195                    if (status == WorkflowConstants.STATUS_ANY) {
196                            return blogsEntryPersistence.filterFindByG_LtD_NotS(
197                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH, start,
198                                    end);
199                    }
200                    else {
201                            return blogsEntryPersistence.filterFindByG_LtD_S(
202                                    groupId, displayDate, status, start, end);
203                    }
204            }
205    
206            @Override
207            public List<BlogsEntry> getGroupEntries(long groupId, int status, int max)
208                    throws SystemException {
209    
210                    return getGroupEntries(groupId, status, 0, max);
211            }
212    
213            @Override
214            public List<BlogsEntry> getGroupEntries(
215                            long groupId, int status, int start, int end)
216                    throws SystemException {
217    
218                    if (status == WorkflowConstants.STATUS_ANY) {
219                            return blogsEntryPersistence.filterFindByG_NotS(
220                                    groupId, WorkflowConstants.STATUS_IN_TRASH, start, end);
221                    }
222                    else {
223                            return blogsEntryPersistence.filterFindByG_S(
224                                    groupId, status, start, end);
225                    }
226            }
227    
228            @Override
229            public int getGroupEntriesCount(long groupId, Date displayDate, int status)
230                    throws SystemException {
231    
232                    if (status == WorkflowConstants.STATUS_ANY) {
233                            return blogsEntryPersistence.filterCountByG_LtD_NotS(
234                                    groupId, displayDate, WorkflowConstants.STATUS_IN_TRASH);
235                    }
236                    else {
237                            return blogsEntryPersistence.filterCountByG_LtD_S(
238                                    groupId, displayDate, status);
239                    }
240            }
241    
242            @Override
243            public int getGroupEntriesCount(long groupId, int status)
244                    throws SystemException {
245    
246                    if (status == WorkflowConstants.STATUS_ANY) {
247                            return blogsEntryPersistence.filterCountByG_NotS(
248                                    groupId, WorkflowConstants.STATUS_IN_TRASH);
249                    }
250                    else {
251                            return blogsEntryPersistence.filterCountByG_S(groupId, status);
252                    }
253            }
254    
255            @Override
256            public String getGroupEntriesRSS(
257                            long groupId, Date displayDate, int status, int max, String type,
258                            double version, String displayStyle, String feedURL,
259                            String entryURL, ThemeDisplay themeDisplay)
260                    throws PortalException, SystemException {
261    
262                    Group group = groupPersistence.findByPrimaryKey(groupId);
263    
264                    String name = group.getDescriptiveName();
265                    List<BlogsEntry> blogsEntries = getGroupEntries(
266                            groupId, displayDate, status, max);
267    
268                    return exportToRSS(
269                            name, name, type, version, displayStyle, feedURL, entryURL,
270                            blogsEntries, themeDisplay);
271            }
272    
273            @Override
274            public List<BlogsEntry> getGroupsEntries(
275                            long companyId, long groupId, Date displayDate, int status, int max)
276                    throws PortalException, SystemException {
277    
278                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
279    
280                    boolean listNotExhausted = true;
281    
282                    QueryDefinition queryDefinition = new QueryDefinition(
283                            status, false, 0, 0, new EntryDisplayDateComparator());
284    
285                    if (status == WorkflowConstants.STATUS_ANY) {
286                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
287                    }
288    
289                    while ((entries.size() < max) && listNotExhausted) {
290                            queryDefinition.setEnd(queryDefinition.getStart() + max);
291    
292                            List<BlogsEntry> entryList =
293                                    blogsEntryLocalService.getGroupsEntries(
294                                            companyId, groupId, displayDate, queryDefinition);
295    
296                            queryDefinition.setStart(queryDefinition.getStart() + max);
297    
298                            listNotExhausted = (entryList.size() == max);
299    
300                            for (BlogsEntry entry : entryList) {
301                                    if (entries.size() >= max) {
302                                            break;
303                                    }
304    
305                                    if (BlogsEntryPermission.contains(
306                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
307    
308                                            entries.add(entry);
309                                    }
310                            }
311                    }
312    
313                    return entries;
314            }
315    
316            @Override
317            public List<BlogsEntry> getOrganizationEntries(
318                            long organizationId, Date displayDate, int status, int max)
319                    throws PortalException, SystemException {
320    
321                    List<BlogsEntry> entries = new ArrayList<BlogsEntry>();
322    
323                    boolean listNotExhausted = true;
324    
325                    QueryDefinition queryDefinition = new QueryDefinition(
326                            status, false, 0, 0, new EntryDisplayDateComparator());
327    
328                    if (status == WorkflowConstants.STATUS_ANY) {
329                            queryDefinition.setStatus(WorkflowConstants.STATUS_IN_TRASH, true);
330                    }
331    
332                    while ((entries.size() < max) && listNotExhausted) {
333                            queryDefinition.setEnd(queryDefinition.getStart() + max);
334    
335                            List<BlogsEntry> entryList = blogsEntryFinder.findByOrganizationId(
336                                    organizationId, displayDate, queryDefinition);
337    
338                            queryDefinition.setStart(queryDefinition.getStart() + max);
339    
340                            listNotExhausted = (entryList.size() == max);
341    
342                            for (BlogsEntry entry : entryList) {
343                                    if (entries.size() >= max) {
344                                            break;
345                                    }
346    
347                                    if (BlogsEntryPermission.contains(
348                                                    getPermissionChecker(), entry, ActionKeys.VIEW)) {
349    
350                                            entries.add(entry);
351                                    }
352                            }
353                    }
354    
355                    return entries;
356            }
357    
358            @Override
359            public String getOrganizationEntriesRSS(
360                            long organizationId, Date displayDate, int status, int max,
361                            String type, double version, String displayStyle, String feedURL,
362                            String entryURL, ThemeDisplay themeDisplay)
363                    throws PortalException, SystemException {
364    
365                    Organization organization = organizationPersistence.findByPrimaryKey(
366                            organizationId);
367    
368                    String name = organization.getName();
369                    List<BlogsEntry> blogsEntries = getOrganizationEntries(
370                            organizationId, displayDate, status, max);
371    
372                    return exportToRSS(
373                            name, name, type, version, displayStyle, feedURL, entryURL,
374                            blogsEntries, themeDisplay);
375            }
376    
377            @Override
378            public BlogsEntry moveEntryToTrash(long entryId)
379                    throws PortalException, SystemException {
380    
381                    BlogsEntryPermission.check(
382                            getPermissionChecker(), entryId, ActionKeys.DELETE);
383    
384                    return blogsEntryLocalService.moveEntryToTrash(getUserId(), entryId);
385            }
386    
387            @Override
388            public void restoreEntryFromTrash(long entryId)
389                    throws PortalException, SystemException {
390    
391                    BlogsEntryPermission.check(
392                            getPermissionChecker(), entryId, ActionKeys.DELETE);
393    
394                    blogsEntryLocalService.restoreEntryFromTrash(getUserId(), entryId);
395            }
396    
397            @Override
398            public void subscribe(long groupId)
399                    throws PortalException, SystemException {
400    
401                    BlogsPermission.check(
402                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
403    
404                    blogsEntryLocalService.subscribe(getUserId(), groupId);
405            }
406    
407            @Override
408            public void unsubscribe(long groupId)
409                    throws PortalException, SystemException {
410    
411                    BlogsPermission.check(
412                            getPermissionChecker(), groupId, ActionKeys.SUBSCRIBE);
413    
414                    blogsEntryLocalService.unsubscribe(getUserId(), groupId);
415            }
416    
417            @Override
418            public BlogsEntry updateEntry(
419                            long entryId, String title, String description, String content,
420                            int displayDateMonth, int displayDateDay, int displayDateYear,
421                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
422                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
423                            String smallImageURL, String smallImageFileName,
424                            InputStream smallImageInputStream, ServiceContext serviceContext)
425                    throws PortalException, SystemException {
426    
427                    BlogsEntryPermission.check(
428                            getPermissionChecker(), entryId, ActionKeys.UPDATE);
429    
430                    return blogsEntryLocalService.updateEntry(
431                            getUserId(), entryId, title, description, content, displayDateMonth,
432                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
433                            allowPingbacks, allowTrackbacks, trackbacks, smallImage,
434                            smallImageURL, smallImageFileName, smallImageInputStream,
435                            serviceContext);
436            }
437    
438            protected String exportToRSS(
439                            String name, String description, String type, double version,
440                            String displayStyle, String feedURL, String entryURL,
441                            List<BlogsEntry> blogsEntries, ThemeDisplay themeDisplay)
442                    throws SystemException {
443    
444                    SyndFeed syndFeed = new SyndFeedImpl();
445    
446                    syndFeed.setDescription(description);
447    
448                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
449    
450                    syndFeed.setEntries(syndEntries);
451    
452                    for (BlogsEntry entry : blogsEntries) {
453                            SyndEntry syndEntry = new SyndEntryImpl();
454    
455                            String author = PortalUtil.getUserName(entry);
456    
457                            syndEntry.setAuthor(author);
458    
459                            SyndContent syndContent = new SyndContentImpl();
460    
461                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
462    
463                            String value = null;
464    
465                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
466                                    String summary = entry.getDescription();
467    
468                                    if (Validator.isNull(summary)) {
469                                            summary = entry.getContent();
470                                    }
471    
472                                    value = StringUtil.shorten(
473                                            HtmlUtil.extractText(summary),
474                                            PropsValues.BLOGS_RSS_ABSTRACT_LENGTH, StringPool.BLANK);
475                            }
476                            else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
477                                    value = StringPool.BLANK;
478                            }
479                            else {
480                                    value = StringUtil.replace(
481                                            entry.getContent(),
482                                            new String[] {
483                                                    "href=\"/", "src=\"/"
484                                            },
485                                            new String[] {
486                                                    "href=\"" + themeDisplay.getURLPortal() + "/",
487                                                    "src=\"" + themeDisplay.getURLPortal() + "/"
488                                            });
489                            }
490    
491                            syndContent.setValue(value);
492    
493                            syndEntry.setDescription(syndContent);
494    
495                            StringBundler sb = new StringBundler(4);
496    
497                            if (entryURL.endsWith("/blogs/rss")) {
498                                    sb.append(entryURL.substring(0, entryURL.length() - 3));
499                                    sb.append(entry.getUrlTitle());
500                            }
501                            else {
502                                    sb.append(entryURL);
503    
504                                    if (!entryURL.endsWith(StringPool.QUESTION)) {
505                                            sb.append(StringPool.AMPERSAND);
506                                    }
507    
508                                    sb.append("entryId=");
509                                    sb.append(entry.getEntryId());
510                            }
511    
512                            String link = sb.toString();
513    
514                            syndEntry.setLink(link);
515    
516                            syndEntry.setPublishedDate(entry.getDisplayDate());
517                            syndEntry.setTitle(entry.getTitle());
518                            syndEntry.setUpdatedDate(entry.getModifiedDate());
519                            syndEntry.setUri(link);
520    
521                            syndEntries.add(syndEntry);
522                    }
523    
524                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
525    
526                    List<SyndLink> syndLinks = new ArrayList<SyndLink>();
527    
528                    syndFeed.setLinks(syndLinks);
529    
530                    SyndLink selfSyndLink = new SyndLinkImpl();
531    
532                    syndLinks.add(selfSyndLink);
533    
534                    selfSyndLink.setHref(feedURL);
535                    selfSyndLink.setRel("self");
536    
537                    if (feedURL.endsWith("/-/blogs/rss")) {
538                            SyndLink alternateSyndLink = new SyndLinkImpl();
539    
540                            syndLinks.add(alternateSyndLink);
541    
542                            alternateSyndLink.setHref(
543                                    feedURL.substring(0, feedURL.length() - 12));
544                            alternateSyndLink.setRel("alternate");
545                    }
546    
547                    syndFeed.setPublishedDate(new Date());
548                    syndFeed.setTitle(name);
549                    syndFeed.setUri(feedURL);
550    
551                    try {
552                            return RSSUtil.export(syndFeed);
553                    }
554                    catch (FeedException fe) {
555                            throw new SystemException(fe);
556                    }
557            }
558    
559    }