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