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.setPublishedDate(article.getDisplayDate());
157
158 SyndContent syndContent = new SyndContentImpl();
159
160 String value = article.getDescription();
161
162 try {
163 value = processContent(
164 feed, article, languageId, themeDisplay, syndEntry,
165 syndContent);
166 }
167 catch (Exception e) {
168 if (_log.isWarnEnabled()) {
169 _log.warn(e, e);
170 }
171 }
172
173 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
174 syndContent.setValue(value);
175
176 syndEntry.setDescription(syndContent);
177
178 entries.add(syndEntry);
179 }
180
181 try {
182 return RSSUtil.export(syndFeed);
183 }
184 catch (FeedException fe) {
185 throw new SystemException(fe);
186 }
187 }
188
189 protected String getEntryURL(
190 ResourceRequest resourceRequest, JournalFeed feed,
191 JournalArticle article, Layout layout, ThemeDisplay themeDisplay)
192 throws Exception {
193
194 List<Long> hitLayoutIds =
195 JournalContentSearchLocalServiceUtil.getLayoutIds(
196 layout.getGroupId(), layout.isPrivateLayout(),
197 article.getArticleId());
198
199 if (hitLayoutIds.size() > 0) {
200 Long hitLayoutId = hitLayoutIds.get(0);
201
202 Layout hitLayout = LayoutLocalServiceUtil.getLayout(
203 layout.getGroupId(), layout.isPrivateLayout(),
204 hitLayoutId.longValue());
205
206 return PortalUtil.getLayoutFriendlyURL(hitLayout, themeDisplay);
207 }
208 else {
209 long plid = PortalUtil.getPlidFromFriendlyURL(
210 feed.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
211
212 String portletId = PortletKeys.JOURNAL_CONTENT;
213
214 if (Validator.isNotNull(feed.getTargetPortletId())) {
215 portletId = feed.getTargetPortletId();
216 }
217
218 PortletURL entryURL = new PortletURLImpl(
219 (PortletRequestImpl)resourceRequest, portletId, plid,
220 PortletRequest.RENDER_PHASE);
221
222 entryURL.setParameter("struts_action", "/journal_content/view");
223 entryURL.setParameter(
224 "groupId", String.valueOf(article.getGroupId()));
225 entryURL.setParameter("articleId", article.getArticleId());
226
227 return entryURL.toString();
228 }
229 }
230
231 protected byte[] getRSS(
232 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
233 throws Exception {
234
235 ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute(
236 WebKeys.THEME_DISPLAY);
237
238 JournalFeed feed = null;
239
240 long id = ParamUtil.getLong(resourceRequest, "id");
241
242 long groupId = ParamUtil.getLong(resourceRequest, "groupId");
243 String feedId = ParamUtil.getString(resourceRequest, "feedId");
244
245 if (id > 0) {
246 feed = JournalFeedLocalServiceUtil.getFeed(id);
247 }
248 else {
249 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
250 }
251
252 String languageId = LanguageUtil.getLanguageId(resourceRequest);
253
254 long plid = PortalUtil.getPlidFromFriendlyURL(
255 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
256
257 Layout layout = themeDisplay.getLayout();
258
259 if (plid > 0) {
260 try {
261 layout = LayoutLocalServiceUtil.getLayout(plid);
262 }
263 catch (NoSuchLayoutException nsle) {
264 }
265 }
266
267 String rss = exportToRSS(
268 resourceRequest, resourceResponse, feed, languageId, layout,
269 themeDisplay);
270
271 return rss.getBytes(StringPool.UTF8);
272 }
273
274 protected String processContent(
275 JournalFeed feed, JournalArticle article, String languageId,
276 ThemeDisplay themeDisplay, SyndEntry syndEntry,
277 SyndContent syndContent)
278 throws Exception {
279
280 String content = article.getDescription();
281
282 String contentField = feed.getContentField();
283
284 if (contentField.equals(JournalFeedImpl.RENDERED_WEB_CONTENT)) {
285 String rendererTemplateId = article.getTemplateId();
286
287 if (Validator.isNotNull(feed.getRendererTemplateId())) {
288 rendererTemplateId = feed.getRendererTemplateId();
289 }
290
291 JournalArticleDisplay articleDisplay =
292 JournalContentUtil.getDisplay(
293 feed.getGroupId(), article.getArticleId(),
294 rendererTemplateId, null, languageId, themeDisplay, 1,
295 _XML_REQUUEST);
296
297 if (articleDisplay != null) {
298 content = articleDisplay.getContent();
299 }
300 }
301 else if (
302 !contentField.equals(JournalFeedImpl.WEB_CONTENT_DESCRIPTION)) {
303
304 Document doc = SAXReaderUtil.read(article.getContent());
305
306 XPath xpathSelector = SAXReaderUtil.createXPath(
307 "//dynamic-element[@name='" + contentField + "']");
308
309 List<Node> results = xpathSelector.selectNodes(doc);
310
311 if (results.size() == 0) {
312 return content;
313 }
314
315 Element el = (Element)results.get(0);
316
317 String elType = el.attributeValue("type");
318
319 if (elType.equals("document_library")) {
320 String url = el.elementText("dynamic-content");
321
322 url = processURL(feed, url, themeDisplay, syndEntry);
323 }
324 else if (elType.equals("image") || elType.equals("image_gallery")) {
325 String url = el.elementText("dynamic-content");
326
327 url = processURL(feed, url, themeDisplay, syndEntry);
328
329 content =
330 content + "<br /><br /><img src='" +
331 themeDisplay.getURLPortal() + url + "' />";
332 }
333 else if (elType.equals("text_box")) {
334 syndContent.setType("text");
335
336 content = el.elementText("dynamic-content");
337 }
338 else {
339 content = el.elementText("dynamic-content");
340 }
341 }
342
343 return content;
344 }
345
346 protected String processURL(
347 JournalFeed feed, String url, ThemeDisplay themeDisplay,
348 SyndEntry syndEntry) {
349
350 url = StringUtil.replace(
351 url,
352 new String[] {
353 "@group_id@",
354 "@image_path@",
355 "@main_path@"
356 },
357 new String[] {
358 String.valueOf(feed.getGroupId()),
359 themeDisplay.getPathImage(),
360 themeDisplay.getPathMain()
361 }
362 );
363
364 List<SyndLink> links = JournalRSSUtil.getDLLinks(
365 themeDisplay.getURLPortal(), url);
366 List<SyndEnclosure> enclosures = JournalRSSUtil.getDLEnclosures(
367 themeDisplay.getURLPortal(), url);
368
369 syndEntry.setLinks(links);
370 syndEntry.setEnclosures(enclosures);
371
372 return url;
373 }
374
375 private static final String _XML_REQUUEST =
376 "<request><parameters><parameter><name>rss</name><value>true</value>" +
377 "</parameter></parameters></request>";
378
379 private static Log _log = LogFactoryUtil.getLog(RSSAction.class);
380
381 }