001
014
015 package com.liferay.portlet.journal.action;
016
017 import com.liferay.portal.NoSuchLayoutException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.language.LanguageUtil;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.ContentTypes;
023 import com.liferay.portal.kernel.util.HtmlUtil;
024 import com.liferay.portal.kernel.util.ParamUtil;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.xml.Document;
029 import com.liferay.portal.kernel.xml.Element;
030 import com.liferay.portal.kernel.xml.Node;
031 import com.liferay.portal.kernel.xml.SAXReaderUtil;
032 import com.liferay.portal.kernel.xml.XPath;
033 import com.liferay.portal.model.Layout;
034 import com.liferay.portal.service.LayoutLocalServiceUtil;
035 import com.liferay.portal.struts.PortletAction;
036 import com.liferay.portal.theme.ThemeDisplay;
037 import com.liferay.portal.util.PortalUtil;
038 import com.liferay.portal.util.PortletKeys;
039 import com.liferay.portal.util.WebKeys;
040 import com.liferay.portlet.PortletRequestImpl;
041 import com.liferay.portlet.PortletURLImpl;
042 import com.liferay.portlet.journal.model.JournalArticle;
043 import com.liferay.portlet.journal.model.JournalArticleDisplay;
044 import com.liferay.portlet.journal.model.JournalFeed;
045 import com.liferay.portlet.journal.model.JournalFeedConstants;
046 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
047 import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
048 import com.liferay.portlet.journal.util.JournalRSSUtil;
049 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
050 import com.liferay.util.RSSUtil;
051
052 import com.sun.syndication.feed.synd.SyndContent;
053 import com.sun.syndication.feed.synd.SyndContentImpl;
054 import com.sun.syndication.feed.synd.SyndEnclosure;
055 import com.sun.syndication.feed.synd.SyndEntry;
056 import com.sun.syndication.feed.synd.SyndEntryImpl;
057 import com.sun.syndication.feed.synd.SyndFeed;
058 import com.sun.syndication.feed.synd.SyndFeedImpl;
059 import com.sun.syndication.feed.synd.SyndLink;
060 import com.sun.syndication.io.FeedException;
061
062 import java.io.OutputStream;
063
064 import java.util.ArrayList;
065 import java.util.Iterator;
066 import java.util.List;
067
068 import javax.portlet.PortletConfig;
069 import javax.portlet.PortletRequest;
070 import javax.portlet.PortletURL;
071 import javax.portlet.ResourceRequest;
072 import javax.portlet.ResourceResponse;
073 import javax.portlet.ResourceURL;
074
075 import org.apache.struts.action.ActionForm;
076 import org.apache.struts.action.ActionMapping;
077
078
081 public class RSSAction extends PortletAction {
082
083 public void serveResource(
084 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
085 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
086 throws Exception {
087
088 resourceResponse.setContentType(ContentTypes.TEXT_XML_UTF8);
089
090 OutputStream os = resourceResponse.getPortletOutputStream();
091
092 try {
093 os.write(getRSS(resourceRequest, resourceResponse));
094 }
095 finally {
096 os.close();
097 }
098 }
099
100 protected String exportToRSS(
101 ResourceRequest resourceRequest, ResourceResponse resourceResponse,
102 JournalFeed feed, String languageId, Layout layout,
103 ThemeDisplay themeDisplay)
104 throws Exception {
105
106 ResourceURL feedURL = resourceResponse.createResourceURL();
107
108 feedURL.setCacheability(ResourceURL.FULL);
109
110 feedURL.setParameter("struts_action", "/journal/rss");
111 feedURL.setParameter("groupId", String.valueOf(feed.getGroupId()));
112 feedURL.setParameter("feedId", String.valueOf(feed.getFeedId()));
113
114 SyndFeed syndFeed = new SyndFeedImpl();
115
116 syndFeed.setFeedType(feed.getFeedType() + "_" + feed.getFeedVersion());
117 syndFeed.setTitle(feed.getName());
118 syndFeed.setLink(feedURL.toString());
119 syndFeed.setDescription(feed.getDescription());
120
121 List<SyndEntry> entries = new ArrayList<SyndEntry>();
122
123 syndFeed.setEntries(entries);
124
125 List<JournalArticle> articles = JournalRSSUtil.getArticles(feed);
126
127 if (_log.isDebugEnabled()) {
128 _log.debug("Syndicating " + articles.size() + " articles");
129 }
130
131 Iterator<JournalArticle> itr = articles.iterator();
132
133 while (itr.hasNext()) {
134 JournalArticle article = itr.next();
135
136 String author = HtmlUtil.escape(
137 PortalUtil.getUserName(
138 article.getUserId(), article.getUserName()));
139 String link = getEntryURL(
140 resourceRequest, feed, article, layout, themeDisplay);
141
142 SyndEntry syndEntry = new SyndEntryImpl();
143
144 syndEntry.setAuthor(author);
145 syndEntry.setTitle(article.getTitle());
146 syndEntry.setLink(link);
147 syndEntry.setUri(syndEntry.getLink());
148 syndEntry.setPublishedDate(article.getDisplayDate());
149 syndEntry.setUpdatedDate(article.getModifiedDate());
150
151 SyndContent syndContent = new SyndContentImpl();
152
153 String value = article.getDescription();
154
155 try {
156 value = processContent(
157 feed, article, languageId, themeDisplay, syndEntry,
158 syndContent);
159 }
160 catch (Exception e) {
161 if (_log.isWarnEnabled()) {
162 _log.warn(e, e);
163 }
164 }
165
166 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
167 syndContent.setValue(value);
168
169 syndEntry.setDescription(syndContent);
170
171 entries.add(syndEntry);
172 }
173
174 try {
175 return RSSUtil.export(syndFeed);
176 }
177 catch (FeedException fe) {
178 throw new SystemException(fe);
179 }
180 }
181
182 protected String getEntryURL(
183 ResourceRequest resourceRequest, JournalFeed feed,
184 JournalArticle article, Layout layout, ThemeDisplay themeDisplay)
185 throws Exception {
186
187 List<Long> hitLayoutIds =
188 JournalContentSearchLocalServiceUtil.getLayoutIds(
189 layout.getGroupId(), layout.isPrivateLayout(),
190 article.getArticleId());
191
192 if (hitLayoutIds.size() > 0) {
193 Long hitLayoutId = hitLayoutIds.get(0);
194
195 Layout hitLayout = LayoutLocalServiceUtil.getLayout(
196 layout.getGroupId(), layout.isPrivateLayout(),
197 hitLayoutId.longValue());
198
199 return PortalUtil.getLayoutFriendlyURL(hitLayout, themeDisplay);
200 }
201 else {
202 long plid = PortalUtil.getPlidFromFriendlyURL(
203 feed.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
204
205 String portletId = PortletKeys.JOURNAL_CONTENT;
206
207 if (Validator.isNotNull(feed.getTargetPortletId())) {
208 portletId = feed.getTargetPortletId();
209 }
210
211 PortletURL entryURL = new PortletURLImpl(
212 (PortletRequestImpl)resourceRequest, portletId, plid,
213 PortletRequest.RENDER_PHASE);
214
215 entryURL.setParameter("struts_action", "/journal_content/view");
216 entryURL.setParameter(
217 "groupId", String.valueOf(article.getGroupId()));
218 entryURL.setParameter("articleId", article.getArticleId());
219
220 return entryURL.toString();
221 }
222 }
223
224 protected byte[] getRSS(
225 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
226 throws Exception {
227
228 ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute(
229 WebKeys.THEME_DISPLAY);
230
231 JournalFeed feed = null;
232
233 long id = ParamUtil.getLong(resourceRequest, "id");
234
235 long groupId = ParamUtil.getLong(resourceRequest, "groupId");
236 String feedId = ParamUtil.getString(resourceRequest, "feedId");
237
238 if (id > 0) {
239 feed = JournalFeedLocalServiceUtil.getFeed(id);
240 }
241 else {
242 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
243 }
244
245 String languageId = LanguageUtil.getLanguageId(resourceRequest);
246
247 long plid = PortalUtil.getPlidFromFriendlyURL(
248 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
249
250 Layout layout = themeDisplay.getLayout();
251
252 if (plid > 0) {
253 try {
254 layout = LayoutLocalServiceUtil.getLayout(plid);
255 }
256 catch (NoSuchLayoutException nsle) {
257 }
258 }
259
260 String rss = exportToRSS(
261 resourceRequest, resourceResponse, feed, languageId, layout,
262 themeDisplay);
263
264 return rss.getBytes(StringPool.UTF8);
265 }
266
267 protected String processContent(
268 JournalFeed feed, JournalArticle article, String languageId,
269 ThemeDisplay themeDisplay, SyndEntry syndEntry,
270 SyndContent syndContent)
271 throws Exception {
272
273 String content = article.getDescription();
274
275 String contentField = feed.getContentField();
276
277 if (contentField.equals(JournalFeedConstants.RENDERED_WEB_CONTENT)) {
278 String rendererTemplateId = article.getTemplateId();
279
280 if (Validator.isNotNull(feed.getRendererTemplateId())) {
281 rendererTemplateId = feed.getRendererTemplateId();
282 }
283
284 JournalArticleDisplay articleDisplay =
285 JournalContentUtil.getDisplay(
286 feed.getGroupId(), article.getArticleId(),
287 rendererTemplateId, null, languageId, themeDisplay, 1,
288 _XML_REQUUEST);
289
290 if (articleDisplay != null) {
291 content = articleDisplay.getContent();
292 }
293 }
294 else if (!contentField.equals(
295 JournalFeedConstants.WEB_CONTENT_DESCRIPTION)) {
296
297 Document doc = SAXReaderUtil.read(article.getContent());
298
299 XPath xpathSelector = SAXReaderUtil.createXPath(
300 "
301
302 List<Node> results = xpathSelector.selectNodes(doc);
303
304 if (results.size() == 0) {
305 return content;
306 }
307
308 Element el = (Element)results.get(0);
309
310 String elType = el.attributeValue("type");
311
312 if (elType.equals("document_library")) {
313 String url = el.elementText("dynamic-content");
314
315 url = processURL(feed, url, themeDisplay, syndEntry);
316 }
317 else if (elType.equals("image") || elType.equals("image_gallery")) {
318 String url = el.elementText("dynamic-content");
319
320 url = processURL(feed, url, themeDisplay, syndEntry);
321
322 content =
323 content + "<br /><br /><img alt='' src='" +
324 themeDisplay.getURLPortal() + url + "' />";
325 }
326 else if (elType.equals("text_box")) {
327 syndContent.setType("text");
328
329 content = el.elementText("dynamic-content");
330 }
331 else {
332 content = el.elementText("dynamic-content");
333 }
334 }
335
336 return content;
337 }
338
339 protected String processURL(
340 JournalFeed feed, String url, ThemeDisplay themeDisplay,
341 SyndEntry syndEntry) {
342
343 url = StringUtil.replace(
344 url,
345 new String[] {
346 "@group_id@",
347 "@image_path@",
348 "@main_path@"
349 },
350 new String[] {
351 String.valueOf(feed.getGroupId()),
352 themeDisplay.getPathImage(),
353 themeDisplay.getPathMain()
354 }
355 );
356
357 List<SyndLink> links = JournalRSSUtil.getDLLinks(
358 themeDisplay.getURLPortal(), url);
359 List<SyndEnclosure> enclosures = JournalRSSUtil.getDLEnclosures(
360 themeDisplay.getURLPortal(), url);
361
362 syndEntry.setLinks(links);
363 syndEntry.setEnclosures(enclosures);
364
365 return url;
366 }
367
368 private static final String _XML_REQUUEST =
369 "<request><parameters><parameter><name>rss</name><value>true</value>" +
370 "</parameter></parameters></request>";
371
372 private static Log _log = LogFactoryUtil.getLog(RSSAction.class);
373
374 }