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.assetpublisher.action;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
019    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
020    import com.liferay.portal.kernel.util.ContentTypes;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.Http;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.model.Layout;
027    import com.liferay.portal.struts.PortletAction;
028    import com.liferay.portal.theme.PortletDisplay;
029    import com.liferay.portal.theme.ThemeDisplay;
030    import com.liferay.portal.util.Portal;
031    import com.liferay.portal.util.PortalUtil;
032    import com.liferay.portal.util.WebKeys;
033    import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
034    import com.liferay.portlet.asset.model.AssetEntry;
035    import com.liferay.portlet.asset.model.AssetRenderer;
036    import com.liferay.portlet.asset.model.AssetRendererFactory;
037    import com.liferay.portlet.asset.service.AssetEntryServiceUtil;
038    import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
039    import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
040    import com.liferay.util.RSSUtil;
041    
042    import com.sun.syndication.feed.synd.SyndContent;
043    import com.sun.syndication.feed.synd.SyndContentImpl;
044    import com.sun.syndication.feed.synd.SyndEntry;
045    import com.sun.syndication.feed.synd.SyndEntryImpl;
046    import com.sun.syndication.feed.synd.SyndFeed;
047    import com.sun.syndication.feed.synd.SyndFeedImpl;
048    import com.sun.syndication.feed.synd.SyndLink;
049    import com.sun.syndication.feed.synd.SyndLinkImpl;
050    
051    import java.io.OutputStream;
052    
053    import java.util.ArrayList;
054    import java.util.Date;
055    import java.util.List;
056    
057    import javax.portlet.PortletConfig;
058    import javax.portlet.PortletPreferences;
059    import javax.portlet.PortletRequest;
060    import javax.portlet.PortletResponse;
061    import javax.portlet.ResourceRequest;
062    import javax.portlet.ResourceResponse;
063    
064    import org.apache.struts.action.ActionForm;
065    import org.apache.struts.action.ActionMapping;
066    
067    /**
068     * @author Brian Wing Shun Chan
069     * @author Julio Camarero
070     */
071    public class RSSAction extends PortletAction {
072    
073            @Override
074            public void serveResource(
075                            ActionMapping actionMapping, ActionForm actionForm,
076                            PortletConfig portletConfig, ResourceRequest resourceRequest,
077                            ResourceResponse resourceResponse)
078                    throws Exception {
079    
080                    resourceResponse.setContentType(ContentTypes.TEXT_XML_UTF8);
081    
082                    OutputStream outputStream = resourceResponse.getPortletOutputStream();
083    
084                    try {
085                            byte[] bytes = getRSS(resourceRequest, resourceResponse);
086    
087                            outputStream.write(bytes);
088                    }
089                    finally {
090                            outputStream.close();
091                    }
092            }
093    
094            protected String exportToRSS(
095                            PortletRequest portletRequest, PortletResponse portletResponse,
096                            String name, String description, String type, double version,
097                            String displayStyle, String linkBehavior,
098                            List<AssetEntry> assetEntries)
099                    throws Exception {
100    
101                    SyndFeed syndFeed = new SyndFeedImpl();
102    
103                    syndFeed.setDescription(GetterUtil.getString(description, name));
104    
105                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
106    
107                    syndFeed.setEntries(syndEntries);
108    
109                    for (AssetEntry assetEntry : assetEntries) {
110                            SyndEntry syndEntry = new SyndEntryImpl();
111    
112                            String author = PortalUtil.getUserName(assetEntry);
113    
114                            syndEntry.setAuthor(author);
115    
116                            SyndContent syndContent = new SyndContentImpl();
117    
118                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
119    
120                            String value = null;
121    
122                            String languageId = LanguageUtil.getLanguageId(portletRequest);
123    
124                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
125                                    value = StringPool.BLANK;
126                            }
127                            else {
128                                    value = assetEntry.getSummary(languageId, true);
129                            }
130    
131                            syndContent.setValue(value);
132    
133                            syndEntry.setDescription(syndContent);
134    
135                            String link = getEntryURL(
136                                    portletRequest, portletResponse, linkBehavior, assetEntry);
137    
138                            syndEntry.setLink(link);
139    
140                            syndEntry.setPublishedDate(assetEntry.getPublishDate());
141                            syndEntry.setTitle(assetEntry.getTitle(languageId, true));
142                            syndEntry.setUpdatedDate(assetEntry.getModifiedDate());
143                            syndEntry.setUri(syndEntry.getLink());
144    
145                            syndEntries.add(syndEntry);
146                    }
147    
148                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
149    
150                    List<SyndLink> syndLinks = new ArrayList<SyndLink>();
151    
152                    syndFeed.setLinks(syndLinks);
153    
154                    SyndLink selfSyndLink = new SyndLinkImpl();
155    
156                    syndLinks.add(selfSyndLink);
157    
158                    String feedURL = getFeedURL(portletRequest);
159    
160                    selfSyndLink.setHref(feedURL);
161    
162                    selfSyndLink.setRel("self");
163    
164                    syndFeed.setPublishedDate(new Date());
165                    syndFeed.setTitle(name);
166                    syndFeed.setUri(feedURL);
167    
168                    return RSSUtil.export(syndFeed);
169            }
170    
171            protected List<AssetEntry> getAssetEntries(
172                            PortletRequest portletRequest, PortletPreferences preferences)
173                    throws Exception {
174    
175                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
176                            WebKeys.THEME_DISPLAY);
177    
178                    AssetEntryQuery assetEntryQuery = AssetPublisherUtil.getAssetEntryQuery(
179                            preferences, new long[] {themeDisplay.getScopeGroupId()});
180    
181                    boolean anyAssetType = GetterUtil.getBoolean(
182                            preferences.getValue("anyAssetType", null), true);
183    
184                    if (!anyAssetType) {
185                            long[] availableClassNameIds =
186                                    AssetRendererFactoryRegistryUtil.getClassNameIds();
187    
188                            long[] classNameIds = AssetPublisherUtil.getClassNameIds(
189                                    preferences, availableClassNameIds);
190    
191                            assetEntryQuery.setClassNameIds(classNameIds);
192                    }
193    
194                    long[] classTypeIds = GetterUtil.getLongValues(
195                            preferences.getValues("classTypeIds", null));
196    
197                    assetEntryQuery.setClassTypeIds(classTypeIds);
198    
199                    boolean enablePermissions = GetterUtil.getBoolean(
200                            preferences.getValue("enablePermissions", null));
201    
202                    assetEntryQuery.setEnablePermissions(enablePermissions);
203    
204                    int rssDelta = GetterUtil.getInteger(
205                            preferences.getValue("rssDelta", "20"));
206    
207                    assetEntryQuery.setEnd(rssDelta);
208    
209                    boolean excludeZeroViewCount = GetterUtil.getBoolean(
210                            preferences.getValue("excludeZeroViewCount", null));
211    
212                    assetEntryQuery.setExcludeZeroViewCount(excludeZeroViewCount);
213    
214                    long[] groupIds = AssetPublisherUtil.getGroupIds(
215                            preferences, themeDisplay.getScopeGroupId(),
216                            themeDisplay.getLayout());
217    
218                    assetEntryQuery.setGroupIds(groupIds);
219    
220                    boolean showOnlyLayoutAssets = GetterUtil.getBoolean(
221                            preferences.getValue("showOnlyLayoutAssets", null));
222    
223                    if (showOnlyLayoutAssets) {
224                            assetEntryQuery.setLayout(themeDisplay.getLayout());
225                    }
226    
227                    String orderByColumn1 = GetterUtil.getString(
228                            preferences.getValue("orderByColumn1", "modifiedDate"));
229    
230                    assetEntryQuery.setOrderByCol1(orderByColumn1);
231    
232                    String orderByColumn2 = GetterUtil.getString(
233                            preferences.getValue("orderByColumn2", "title"));
234    
235                    assetEntryQuery.setOrderByCol2(orderByColumn2);
236    
237                    String orderByType1 = GetterUtil.getString(
238                            preferences.getValue("orderByType1", "DESC"));
239    
240                    assetEntryQuery.setOrderByType1(orderByType1);
241    
242                    String orderByType2 = GetterUtil.getString(
243                            preferences.getValue("orderByType2", "ASC"));
244    
245                    assetEntryQuery.setOrderByType2(orderByType2);
246    
247                    assetEntryQuery.setStart(0);
248    
249                    return AssetEntryServiceUtil.getEntries(assetEntryQuery);
250            }
251    
252            protected String getAssetPublisherURL(PortletRequest portletRequest)
253                    throws Exception {
254    
255                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
256                            WebKeys.THEME_DISPLAY);
257    
258                    Layout layout = themeDisplay.getLayout();
259    
260                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
261    
262                    StringBundler sb = new StringBundler(7);
263    
264                    String layoutFriendlyURL = GetterUtil.getString(
265                            PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
266    
267                    if (!layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
268                            !layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
269    
270                            sb.append(themeDisplay.getPortalURL());
271                    }
272    
273                    sb.append(layoutFriendlyURL);
274                    sb.append(Portal.FRIENDLY_URL_SEPARATOR);
275                    sb.append("asset_publisher/");
276                    sb.append(portletDisplay.getInstanceId());
277                    sb.append(StringPool.SLASH);
278    
279                    return sb.toString();
280            }
281    
282            protected String getEntryURL(
283                            PortletRequest portletRequest, PortletResponse portletResponse,
284                            String linkBehavior, AssetEntry assetEntry)
285                    throws Exception {
286    
287                    if (linkBehavior.equals("viewInPortlet")) {
288                            return getEntryURLViewInContext(
289                                    portletRequest, portletResponse, assetEntry);
290                    }
291                    else {
292                            return getEntryURLAssetPublisher(
293                                    portletRequest, portletResponse, assetEntry);
294                    }
295            }
296    
297            protected String getEntryURLAssetPublisher(
298                            PortletRequest portletRequest, PortletResponse portletResponse,
299                            AssetEntry assetEntry)
300                    throws Exception {
301    
302                    AssetRendererFactory assetRendererFactory =
303                            AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
304                                    assetEntry.getClassName());
305    
306                    StringBundler sb = new StringBundler(4);
307    
308                    sb.append(getAssetPublisherURL(portletRequest));
309                    sb.append(assetRendererFactory.getType());
310                    sb.append("/id/");
311                    sb.append(assetEntry.getEntryId());
312    
313                    return sb.toString();
314            }
315    
316            protected String getEntryURLViewInContext(
317                            PortletRequest portletRequest, PortletResponse portletResponse,
318                            AssetEntry assetEntry)
319                    throws Exception {
320    
321                    AssetRendererFactory assetRendererFactory =
322                            AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
323                                    assetEntry.getClassName());
324    
325                    AssetRenderer assetRenderer = assetRendererFactory.getAssetRenderer(
326                            assetEntry.getClassPK());
327    
328                    String viewInContextURL = assetRenderer.getURLViewInContext(
329                            (LiferayPortletRequest)portletRequest,
330                            (LiferayPortletResponse)portletResponse, null);
331    
332                    if (Validator.isNotNull(viewInContextURL) &&
333                            !viewInContextURL.startsWith(Http.HTTP_WITH_SLASH) &&
334                            !viewInContextURL.startsWith(Http.HTTPS_WITH_SLASH)) {
335    
336                            ThemeDisplay themeDisplay =
337                                    (ThemeDisplay)portletRequest.getAttribute(
338                                            WebKeys.THEME_DISPLAY);
339    
340                            viewInContextURL = themeDisplay.getPortalURL() + viewInContextURL;
341                    }
342    
343                    return viewInContextURL;
344            }
345    
346            protected String getFeedURL(PortletRequest portletRequest)
347                    throws Exception {
348    
349                    String feedURL = getAssetPublisherURL(portletRequest);
350    
351                    return feedURL.concat("rss");
352            }
353    
354            protected byte[] getRSS(
355                            PortletRequest portletRequest, PortletResponse portletResponse)
356                    throws Exception {
357    
358                    PortletPreferences preferences = portletRequest.getPreferences();
359    
360                    String selectionStyle = preferences.getValue(
361                            "selectionStyle", "dynamic");
362    
363                    if (!selectionStyle.equals("dynamic")) {
364                            return new byte[0];
365                    }
366    
367                    String rssName = preferences.getValue("rssName", null);
368                    String rssFormat = preferences.getValue("rssFormat", "atom10");
369                    String rssDisplayStyle = preferences.getValue(
370                            "rssDisplayStyle", RSSUtil.DISPLAY_STYLE_ABSTRACT);
371                    String assetLinkBehavior = preferences.getValue(
372                            "assetLinkBehavior", "showFullContent");
373    
374                    String rss = exportToRSS(
375                            portletRequest, portletResponse, rssName, null,
376                            RSSUtil.getFormatType(rssFormat),
377                            RSSUtil.getFormatVersion(rssFormat), rssDisplayStyle,
378                            assetLinkBehavior, getAssetEntries(portletRequest, preferences));
379    
380                    return rss.getBytes(StringPool.UTF8);
381            }
382    
383    }