001    /**
002     * Copyright (c) 2000-2012 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.HtmlUtil;
023    import com.liferay.portal.kernel.util.Http;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
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    
049    import java.io.OutputStream;
050    
051    import java.util.ArrayList;
052    import java.util.List;
053    
054    import javax.portlet.PortletConfig;
055    import javax.portlet.PortletPreferences;
056    import javax.portlet.PortletRequest;
057    import javax.portlet.PortletResponse;
058    import javax.portlet.ResourceRequest;
059    import javax.portlet.ResourceResponse;
060    
061    import org.apache.struts.action.ActionForm;
062    import org.apache.struts.action.ActionMapping;
063    
064    /**
065     * @author Brian Wing Shun Chan
066     * @author Julio Camarero
067     */
068    public class RSSAction extends PortletAction {
069    
070            @Override
071            public void serveResource(
072                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
073                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
074                    throws Exception {
075    
076                    resourceResponse.setContentType(ContentTypes.TEXT_XML_UTF8);
077    
078                    OutputStream outputStream = resourceResponse.getPortletOutputStream();
079    
080                    try {
081                            byte[] bytes = getRSS(resourceRequest, resourceResponse);
082    
083                            outputStream.write(bytes);
084                    }
085                    finally {
086                            outputStream.close();
087                    }
088            }
089    
090            protected String exportToRSS(
091                            PortletRequest portletRequest, PortletResponse portletResponse,
092                            String name, String description, String type, double version,
093                            String displayStyle, String linkBehavior,
094                            List<AssetEntry> assetEntries)
095                    throws Exception {
096    
097                    SyndFeed syndFeed = new SyndFeedImpl();
098    
099                    syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
100                    syndFeed.setTitle(name);
101                    syndFeed.setLink(getFeedURL(portletRequest));
102                    syndFeed.setDescription(GetterUtil.getString(description, name));
103    
104                    List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
105    
106                    syndFeed.setEntries(syndEntries);
107    
108                    for (AssetEntry assetEntry : assetEntries) {
109                            String link = getEntryURL(
110                                    portletRequest, portletResponse, linkBehavior, assetEntry);
111    
112                            String author = HtmlUtil.escape(
113                                    PortalUtil.getUserName(
114                                            assetEntry.getUserId(), assetEntry.getUserName()));
115    
116                            String value = null;
117    
118                            if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
119                                    value = StringPool.BLANK;
120                            }
121                            else {
122                                    value = assetEntry.getSummary();
123                            }
124    
125                            SyndEntry syndEntry = new SyndEntryImpl();
126    
127                            syndEntry.setAuthor(author);
128    
129                            String languageId = LanguageUtil.getLanguageId(portletRequest);
130    
131                            syndEntry.setTitle(assetEntry.getTitle(languageId, true));
132    
133                            syndEntry.setLink(link);
134                            syndEntry.setUri(syndEntry.getLink());
135                            syndEntry.setPublishedDate(assetEntry.getCreateDate());
136                            syndEntry.setUpdatedDate(assetEntry.getModifiedDate());
137    
138                            SyndContent syndContent = new SyndContentImpl();
139    
140                            syndContent.setType(RSSUtil.ENTRY_TYPE_DEFAULT);
141                            syndContent.setValue(value);
142    
143                            syndEntry.setDescription(syndContent);
144    
145                            syndEntries.add(syndEntry);
146                    }
147    
148                    return RSSUtil.export(syndFeed);
149            }
150    
151            protected String getAssetPublisherURL(PortletRequest portletRequest)
152                    throws Exception {
153    
154                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
155                            WebKeys.THEME_DISPLAY);
156    
157                    Layout layout = themeDisplay.getLayout();
158    
159                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
160    
161                    StringBundler sb = new StringBundler(7);
162    
163                    String layoutFriendlyURL = GetterUtil.getString(
164                            PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
165    
166                    if (!layoutFriendlyURL.startsWith(Http.HTTP_WITH_SLASH) &&
167                            !layoutFriendlyURL.startsWith(Http.HTTPS_WITH_SLASH)) {
168    
169                            sb.append(themeDisplay.getPortalURL());
170                    }
171    
172                    sb.append(layoutFriendlyURL);
173                    sb.append(Portal.FRIENDLY_URL_SEPARATOR);
174                    sb.append("asset_publisher/");
175                    sb.append(portletDisplay.getInstanceId());
176                    sb.append(StringPool.SLASH);
177    
178                    return sb.toString();
179            }
180    
181            protected String getEntryURL(
182                            PortletRequest portletRequest, PortletResponse portletResponse,
183                            String linkBehavior, AssetEntry assetEntry)
184                    throws Exception {
185    
186                    if (linkBehavior.equals("viewInPortlet")) {
187                            return getEntryURLViewInContext(
188                                    portletRequest, portletResponse, assetEntry);
189                    }
190                    else {
191                            return getEntryURLAssetPublisher(
192                                    portletRequest, portletResponse, assetEntry);
193                    }
194            }
195    
196            protected String getEntryURLAssetPublisher(
197                            PortletRequest portletRequest, PortletResponse portletResponse,
198                            AssetEntry assetEntry)
199                    throws Exception {
200    
201                    AssetRendererFactory assetRendererFactory =
202                            AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
203                                    assetEntry.getClassName());
204    
205                    StringBundler sb = new StringBundler(4);
206    
207                    sb.append(getAssetPublisherURL(portletRequest));
208                    sb.append(assetRendererFactory.getType());
209                    sb.append("/id/");
210                    sb.append(assetEntry.getEntryId());
211    
212                    return sb.toString();
213            }
214    
215            protected String getEntryURLViewInContext(
216                            PortletRequest portletRequest, PortletResponse portletResponse,
217                            AssetEntry assetEntry)
218                    throws Exception {
219    
220                    AssetRendererFactory assetRendererFactory =
221                            AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName(
222                                    assetEntry.getClassName());
223    
224                    AssetRenderer assetRenderer = assetRendererFactory.getAssetRenderer(
225                            assetEntry.getClassPK());
226    
227                    String viewInContextURL = assetRenderer.getURLViewInContext(
228                            (LiferayPortletRequest)portletRequest,
229                            (LiferayPortletResponse)portletResponse, null);
230    
231                    if (!viewInContextURL.startsWith(Http.HTTP_WITH_SLASH) &&
232                            !viewInContextURL.startsWith(Http.HTTPS_WITH_SLASH)) {
233    
234                            ThemeDisplay themeDisplay =
235                                    (ThemeDisplay)portletRequest.getAttribute(
236                                            WebKeys.THEME_DISPLAY);
237    
238                            viewInContextURL = themeDisplay.getPortalURL() + viewInContextURL;
239                    }
240    
241                    return viewInContextURL;
242            }
243    
244            protected String getFeedURL(PortletRequest portletRequest)
245                    throws Exception {
246    
247                    String feedURL = getAssetPublisherURL(portletRequest);
248    
249                    return feedURL.concat("rss");
250            }
251    
252            protected byte[] getRSS(
253                            PortletRequest portletRequest, PortletResponse portletResponse)
254                    throws Exception {
255    
256                    PortletPreferences preferences = portletRequest.getPreferences();
257    
258                    String selectionStyle = preferences.getValue(
259                            "selectionStyle", "dynamic");
260    
261                    if (!selectionStyle.equals("dynamic")) {
262                            return new byte[0];
263                    }
264    
265                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
266                            WebKeys.THEME_DISPLAY);
267    
268                    long[] groupIds = AssetPublisherUtil.getGroupIds(
269                            preferences, themeDisplay.getScopeGroupId(),
270                            themeDisplay.getLayout());
271    
272                    boolean anyAssetType = GetterUtil.getBoolean(
273                            preferences.getValue("anyAssetType", Boolean.TRUE.toString()));
274                    String assetLinkBehavior = preferences.getValue(
275                            "assetLinkBehavior", "showFullContent");
276                    boolean excludeZeroViewCount = GetterUtil.getBoolean(
277                            preferences.getValue("excludeZeroViewCount", "0"));
278    
279                    int rssDelta = GetterUtil.getInteger(
280                            preferences.getValue("rssDelta", "20"));
281                    String rssDisplayStyle = preferences.getValue(
282                            "rssDisplayStyle", RSSUtil.DISPLAY_STYLE_ABSTRACT);
283                    String rssFormat = preferences.getValue("rssFormat", "atom10");
284                    String rssName = preferences.getValue("rssName", null);
285    
286                    String rssFormatType = RSSUtil.getFormatType(rssFormat);
287                    double rssFormatVersion = RSSUtil.getFormatVersion(rssFormat);
288    
289                    AssetEntryQuery assetEntryQuery = AssetPublisherUtil.getAssetEntryQuery(
290                            preferences, new long[] {themeDisplay.getScopeGroupId()});
291    
292                    if (!anyAssetType) {
293                            long[] availableClassNameIds =
294                                    AssetRendererFactoryRegistryUtil.getClassNameIds();
295    
296                            long[] classNameIds = AssetPublisherUtil.getClassNameIds(
297                                    preferences, availableClassNameIds);
298    
299                            assetEntryQuery.setClassNameIds(classNameIds);
300                    }
301    
302                    assetEntryQuery.setEnd(rssDelta);
303                    assetEntryQuery.setExcludeZeroViewCount(excludeZeroViewCount);
304                    assetEntryQuery.setGroupIds(groupIds);
305                    assetEntryQuery.setStart(0);
306    
307                    List<AssetEntry> assetEntries = AssetEntryServiceUtil.getEntries(
308                            assetEntryQuery);
309    
310                    String rss = exportToRSS(
311                            portletRequest, portletResponse, rssName, null, rssFormatType,
312                            rssFormatVersion, rssDisplayStyle, assetLinkBehavior, assetEntries);
313    
314                    return rss.getBytes(StringPool.UTF8);
315            }
316    
317    }