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