1
22
23 package com.liferay.portlet.journal.action;
24
25 import com.liferay.portal.NoSuchLayoutException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.language.LanguageUtil;
28 import com.liferay.portal.kernel.log.Log;
29 import com.liferay.portal.kernel.log.LogFactoryUtil;
30 import com.liferay.portal.kernel.util.ContentTypes;
31 import com.liferay.portal.kernel.util.ParamUtil;
32 import com.liferay.portal.kernel.util.StringPool;
33 import com.liferay.portal.kernel.util.StringUtil;
34 import com.liferay.portal.kernel.util.Validator;
35 import com.liferay.portal.kernel.xml.Document;
36 import com.liferay.portal.kernel.xml.Element;
37 import com.liferay.portal.kernel.xml.Node;
38 import com.liferay.portal.kernel.xml.SAXReaderUtil;
39 import com.liferay.portal.kernel.xml.XPath;
40 import com.liferay.portal.model.Layout;
41 import com.liferay.portal.service.LayoutLocalServiceUtil;
42 import com.liferay.portal.struts.PortletAction;
43 import com.liferay.portal.theme.ThemeDisplay;
44 import com.liferay.portal.util.PortalUtil;
45 import com.liferay.portal.util.PortletKeys;
46 import com.liferay.portal.util.WebKeys;
47 import com.liferay.portlet.PortletRequestImpl;
48 import com.liferay.portlet.PortletURLImpl;
49 import com.liferay.portlet.journal.model.JournalArticle;
50 import com.liferay.portlet.journal.model.JournalArticleDisplay;
51 import com.liferay.portlet.journal.model.JournalFeed;
52 import com.liferay.portlet.journal.model.impl.JournalFeedImpl;
53 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
54 import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
55 import com.liferay.portlet.journal.util.JournalRSSUtil;
56 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
57 import com.liferay.util.RSSUtil;
58
59 import com.sun.syndication.feed.synd.SyndContent;
60 import com.sun.syndication.feed.synd.SyndContentImpl;
61 import com.sun.syndication.feed.synd.SyndEnclosure;
62 import com.sun.syndication.feed.synd.SyndEntry;
63 import com.sun.syndication.feed.synd.SyndEntryImpl;
64 import com.sun.syndication.feed.synd.SyndFeed;
65 import com.sun.syndication.feed.synd.SyndFeedImpl;
66 import com.sun.syndication.feed.synd.SyndLink;
67 import com.sun.syndication.io.FeedException;
68
69 import java.io.OutputStream;
70
71 import java.util.ArrayList;
72 import java.util.Iterator;
73 import java.util.List;
74
75 import javax.portlet.PortletConfig;
76 import javax.portlet.PortletRequest;
77 import javax.portlet.PortletURL;
78 import javax.portlet.ResourceRequest;
79 import javax.portlet.ResourceResponse;
80 import javax.portlet.ResourceURL;
81
82 import org.apache.struts.action.ActionForm;
83 import org.apache.struts.action.ActionMapping;
84
85
91 public class RSSAction extends PortletAction {
92
93 public void serveResource(
94 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
95 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
96 throws Exception {
97
98 resourceResponse.setContentType(ContentTypes.TEXT_XML_UTF8);
99
100 OutputStream os = resourceResponse.getPortletOutputStream();
101
102 try {
103 os.write(getRSS(resourceRequest, resourceResponse));
104 }
105 finally {
106 os.close();
107 }
108 }
109
110 protected String exportToRSS(
111 ResourceRequest resourceRequest, ResourceResponse resourceResponse,
112 JournalFeed feed, String languageId, Layout layout,
113 ThemeDisplay themeDisplay)
114 throws Exception {
115
116 ResourceURL feedURL = resourceResponse.createResourceURL();
117
118 feedURL.setCacheability(ResourceURL.FULL);
119
120 feedURL.setParameter("struts_action", "/journal/rss");
121 feedURL.setParameter("groupId", String.valueOf(feed.getGroupId()));
122 feedURL.setParameter("feedId", String.valueOf(feed.getFeedId()));
123
124 SyndFeed syndFeed = new SyndFeedImpl();
125
126 syndFeed.setFeedType(feed.getFeedType() + "_" + feed.getFeedVersion());
127 syndFeed.setTitle(feed.getName());
128 syndFeed.setLink(feedURL.toString());
129 syndFeed.setDescription(feed.getDescription());
130
131 List<SyndEntry> entries = new ArrayList<SyndEntry>();
132
133 syndFeed.setEntries(entries);
134
135 List<JournalArticle> articles = JournalRSSUtil.getArticles(feed);
136
137 if (_log.isDebugEnabled()) {
138 _log.debug("Syndicating " + articles.size() + " articles");
139 }
140
141 Iterator<JournalArticle> itr = articles.iterator();
142
143 while (itr.hasNext()) {
144 JournalArticle article = itr.next();
145
146 String author = PortalUtil.getUserName(
147 article.getUserId(), article.getUserName());
148 String link = getEntryURL(
149 resourceRequest, feed, article, layout, themeDisplay);
150
151 SyndEntry syndEntry = new SyndEntryImpl();
152
153 syndEntry.setAuthor(author);
154 syndEntry.setTitle(article.getTitle());
155 syndEntry.setLink(link);
156 syndEntry.setUri(syndEntry.getLink());
157 syndEntry.setPublishedDate(article.getDisplayDate());
158 syndEntry.setUpdatedDate(article.getModifiedDate());
159
160 SyndContent syndContent = new SyndContentImpl();
161
162 String value = article.getDescription();
163
164 try {
165 value = processContent(
166 feed, article, languageId, themeDisplay, syndEntry,
167 syndContent);
168 }
169 catch (Exception e) {
170 if (_log.isWarnEnabled()) {
171 _log.warn(e, e);
172 }
173 }
174
175 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
176 syndContent.setValue(value);
177
178 syndEntry.setDescription(syndContent);
179
180 entries.add(syndEntry);
181 }
182
183 try {
184 return RSSUtil.export(syndFeed);
185 }
186 catch (FeedException fe) {
187 throw new SystemException(fe);
188 }
189 }
190
191 protected String getEntryURL(
192 ResourceRequest resourceRequest, JournalFeed feed,
193 JournalArticle article, Layout layout, ThemeDisplay themeDisplay)
194 throws Exception {
195
196 List<Long> hitLayoutIds =
197 JournalContentSearchLocalServiceUtil.getLayoutIds(
198 layout.getGroupId(), layout.isPrivateLayout(),
199 article.getArticleId());
200
201 if (hitLayoutIds.size() > 0) {
202 Long hitLayoutId = hitLayoutIds.get(0);
203
204 Layout hitLayout = LayoutLocalServiceUtil.getLayout(
205 layout.getGroupId(), layout.isPrivateLayout(),
206 hitLayoutId.longValue());
207
208 return PortalUtil.getLayoutFriendlyURL(hitLayout, themeDisplay);
209 }
210 else {
211 long plid = PortalUtil.getPlidFromFriendlyURL(
212 feed.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
213
214 String portletId = PortletKeys.JOURNAL_CONTENT;
215
216 if (Validator.isNotNull(feed.getTargetPortletId())) {
217 portletId = feed.getTargetPortletId();
218 }
219
220 PortletURL entryURL = new PortletURLImpl(
221 (PortletRequestImpl)resourceRequest, portletId, plid,
222 PortletRequest.RENDER_PHASE);
223
224 entryURL.setParameter("struts_action", "/journal_content/view");
225 entryURL.setParameter(
226 "groupId", String.valueOf(article.getGroupId()));
227 entryURL.setParameter("articleId", article.getArticleId());
228
229 return entryURL.toString();
230 }
231 }
232
233 protected byte[] getRSS(
234 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
235 throws Exception {
236
237 ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute(
238 WebKeys.THEME_DISPLAY);
239
240 JournalFeed feed = null;
241
242 long id = ParamUtil.getLong(resourceRequest, "id");
243
244 long groupId = ParamUtil.getLong(resourceRequest, "groupId");
245 String feedId = ParamUtil.getString(resourceRequest, "feedId");
246
247 if (id > 0) {
248 feed = JournalFeedLocalServiceUtil.getFeed(id);
249 }
250 else {
251 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
252 }
253
254 String languageId = LanguageUtil.getLanguageId(resourceRequest);
255
256 long plid = PortalUtil.getPlidFromFriendlyURL(
257 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
258
259 Layout layout = themeDisplay.getLayout();
260
261 if (plid > 0) {
262 try {
263 layout = LayoutLocalServiceUtil.getLayout(plid);
264 }
265 catch (NoSuchLayoutException nsle) {
266 }
267 }
268
269 String rss = exportToRSS(
270 resourceRequest, resourceResponse, feed, languageId, layout,
271 themeDisplay);
272
273 return rss.getBytes(StringPool.UTF8);
274 }
275
276 protected String processContent(
277 JournalFeed feed, JournalArticle article, String languageId,
278 ThemeDisplay themeDisplay, SyndEntry syndEntry,
279 SyndContent syndContent)
280 throws Exception {
281
282 String content = article.getDescription();
283
284 String contentField = feed.getContentField();
285
286 if (contentField.equals(JournalFeedImpl.RENDERED_WEB_CONTENT)) {
287 String rendererTemplateId = article.getTemplateId();
288
289 if (Validator.isNotNull(feed.getRendererTemplateId())) {
290 rendererTemplateId = feed.getRendererTemplateId();
291 }
292
293 JournalArticleDisplay articleDisplay =
294 JournalContentUtil.getDisplay(
295 feed.getGroupId(), article.getArticleId(),
296 rendererTemplateId, null, languageId, themeDisplay, 1,
297 _XML_REQUUEST);
298
299 if (articleDisplay != null) {
300 content = articleDisplay.getContent();
301 }
302 }
303 else if (
304 !contentField.equals(JournalFeedImpl.WEB_CONTENT_DESCRIPTION)) {
305
306 Document doc = SAXReaderUtil.read(article.getContent());
307
308 XPath xpathSelector = SAXReaderUtil.createXPath(
309 "//dynamic-element[@name='" + contentField + "']");
310
311 List<Node> results = xpathSelector.selectNodes(doc);
312
313 if (results.size() == 0) {
314 return content;
315 }
316
317 Element el = (Element)results.get(0);
318
319 String elType = el.attributeValue("type");
320
321 if (elType.equals("document_library")) {
322 String url = el.elementText("dynamic-content");
323
324 url = processURL(feed, url, themeDisplay, syndEntry);
325 }
326 else if (elType.equals("image") || elType.equals("image_gallery")) {
327 String url = el.elementText("dynamic-content");
328
329 url = processURL(feed, url, themeDisplay, syndEntry);
330
331 content =
332 content + "<br /><br /><img src='" +
333 themeDisplay.getURLPortal() + url + "' />";
334 }
335 else if (elType.equals("text_box")) {
336 syndContent.setType("text");
337
338 content = el.elementText("dynamic-content");
339 }
340 else {
341 content = el.elementText("dynamic-content");
342 }
343 }
344
345 return content;
346 }
347
348 protected String processURL(
349 JournalFeed feed, String url, ThemeDisplay themeDisplay,
350 SyndEntry syndEntry) {
351
352 url = StringUtil.replace(
353 url,
354 new String[] {
355 "@group_id@",
356 "@image_path@",
357 "@main_path@"
358 },
359 new String[] {
360 String.valueOf(feed.getGroupId()),
361 themeDisplay.getPathImage(),
362 themeDisplay.getPathMain()
363 }
364 );
365
366 List<SyndLink> links = JournalRSSUtil.getDLLinks(
367 themeDisplay.getURLPortal(), url);
368 List<SyndEnclosure> enclosures = JournalRSSUtil.getDLEnclosures(
369 themeDisplay.getURLPortal(), url);
370
371 syndEntry.setLinks(links);
372 syndEntry.setEnclosures(enclosures);
373
374 return url;
375 }
376
377 private static final String _XML_REQUUEST =
378 "<request><parameters><parameter><name>rss</name><value>true</value>" +
379 "</parameter></parameters></request>";
380
381 private static Log _log = LogFactoryUtil.getLog(RSSAction.class);
382
383 }