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