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.portlet.LiferayWindowState;
29 import com.liferay.portal.kernel.util.ContentTypes;
30 import com.liferay.portal.kernel.util.ParamUtil;
31 import com.liferay.portal.kernel.util.StringMaker;
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.model.Layout;
36 import com.liferay.portal.service.LayoutLocalServiceUtil;
37 import com.liferay.portal.struts.ActionConstants;
38 import com.liferay.portal.struts.PortletAction;
39 import com.liferay.portal.theme.ThemeDisplay;
40 import com.liferay.portal.util.DocumentUtil;
41 import com.liferay.portal.util.PortalUtil;
42 import com.liferay.portal.util.PortletKeys;
43 import com.liferay.portal.util.WebKeys;
44 import com.liferay.portlet.journal.model.JournalArticle;
45 import com.liferay.portlet.journal.model.JournalArticleDisplay;
46 import com.liferay.portlet.journal.model.JournalFeed;
47 import com.liferay.portlet.journal.model.impl.JournalFeedImpl;
48 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
49 import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
50 import com.liferay.portlet.journal.util.JournalRSSUtil;
51 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
52 import com.liferay.util.RSSUtil;
53
54 import com.sun.syndication.feed.synd.SyndContent;
55 import com.sun.syndication.feed.synd.SyndContentImpl;
56 import com.sun.syndication.feed.synd.SyndEnclosure;
57 import com.sun.syndication.feed.synd.SyndEntry;
58 import com.sun.syndication.feed.synd.SyndEntryImpl;
59 import com.sun.syndication.feed.synd.SyndFeed;
60 import com.sun.syndication.feed.synd.SyndFeedImpl;
61 import com.sun.syndication.feed.synd.SyndLink;
62 import com.sun.syndication.io.FeedException;
63
64 import java.io.IOException;
65 import java.io.OutputStream;
66
67 import java.util.ArrayList;
68 import java.util.Iterator;
69 import java.util.List;
70
71 import javax.portlet.PortletConfig;
72 import javax.portlet.RenderRequest;
73 import javax.portlet.RenderResponse;
74
75 import org.apache.commons.logging.Log;
76 import org.apache.commons.logging.LogFactory;
77 import org.apache.struts.action.ActionForm;
78 import org.apache.struts.action.ActionForward;
79 import org.apache.struts.action.ActionMapping;
80
81 import org.dom4j.Document;
82 import org.dom4j.DocumentHelper;
83 import org.dom4j.Element;
84 import org.dom4j.XPath;
85
86
92 public class RSSAction extends PortletAction {
93
94 public ActionForward render(
95 ActionMapping mapping, ActionForm form, PortletConfig config,
96 RenderRequest req, RenderResponse res)
97 throws Exception {
98
99 if (req.getWindowState() == LiferayWindowState.EXCLUSIVE) {
100 res.setContentType(ContentTypes.TEXT_XML_UTF8);
101
102 OutputStream out = res.getPortletOutputStream();
103
104 try {
105 out.write(getRSS(req));
106 }
107 finally {
108 out.close();
109 }
110 }
111
112 return mapping.findForward(ActionConstants.COMMON_NULL);
113 }
114
115 protected String exportToRSS(
116 JournalFeed feed, String languageId, Layout layout,
117 ThemeDisplay themeDisplay)
118 throws Exception {
119
120 String feedURL =
121 PortalUtil.getLayoutFriendlyURL(layout, themeDisplay) +
122 "/journal/rss/" + feed.getGroupId() + "/" + 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);
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(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.setPublishedDate(article.getDisplayDate());
156
157 SyndContent syndContent = new SyndContentImpl();
158
159 String value = article.getDescription();
160
161 try {
162 value = processContent(
163 feed, article, languageId, themeDisplay, syndEntry,
164 syndContent);
165 }
166 catch (Exception e) {
167 if (_log.isWarnEnabled()) {
168 _log.warn(e, e);
169 }
170 }
171
172 syndContent.setType("html");
173 syndContent.setValue(value);
174
175 syndEntry.setDescription(syndContent);
176
177 entries.add(syndEntry);
178 }
179
180 try {
181 return RSSUtil.export(syndFeed);
182 }
183 catch (FeedException fe) {
184 throw new SystemException(fe);
185 }
186 catch (IOException ioe) {
187 throw new SystemException(ioe);
188 }
189 }
190
191 protected String getEntryURL(
192 JournalFeed feed, JournalArticle article, Layout layout,
193 ThemeDisplay themeDisplay)
194 throws Exception {
195
196 StringMaker sm = new StringMaker();
197
198 List<Long> hitLayoutIds =
199 JournalContentSearchLocalServiceUtil.getLayoutIds(
200 layout.getGroupId(), layout.isPrivateLayout(),
201 article.getArticleId());
202
203 if (hitLayoutIds.size() > 0) {
204 Long hitLayoutId = hitLayoutIds.get(0);
205
206 Layout hitLayout = LayoutLocalServiceUtil.getLayout(
207 layout.getGroupId(), layout.isPrivateLayout(),
208 hitLayoutId.longValue());
209
210 return PortalUtil.getLayoutFriendlyURL(hitLayout, themeDisplay);
211 }
212 else if (Validator.isNotNull(feed.getTargetLayoutFriendlyUrl())) {
213 long plid = PortalUtil.getPlidIdFromFriendlyURL(
214 feed.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
215
216 Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
217
218 sm.append(
219 PortalUtil.getLayoutFriendlyURL(targetLayout, themeDisplay));
220 }
221 else {
222 sm.append(PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
223 }
224
225 sm.append("/journal_content/");
226
227 if (Validator.isNotNull(feed.getTargetPortletId())) {
228 sm.append(feed.getTargetPortletId());
229 }
230 else {
231 sm.append(PortletKeys.JOURNAL_CONTENT);
232 }
233
234 sm.append(StringPool.SLASH);
235 sm.append(article.getGroupId());
236 sm.append(StringPool.SLASH);
237 sm.append(article.getArticleId());
238
239 return sm.toString();
240 }
241
242 protected byte[] getRSS(RenderRequest req) throws Exception {
243 ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
244 WebKeys.THEME_DISPLAY);
245
246 JournalFeed feed = null;
247
248 long id = ParamUtil.getLong(req, "id");
249
250 long groupId = ParamUtil.getLong(req, "groupId");
251 String feedId = ParamUtil.getString(req, "feedId");
252
253 if (id > 0) {
254 feed = JournalFeedLocalServiceUtil.getFeed(id);
255 }
256 else {
257 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
258 }
259
260 String languageId = LanguageUtil.getLanguageId(req);
261
262 long plid = PortalUtil.getPlidIdFromFriendlyURL(
263 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
264
265 Layout layout = themeDisplay.getLayout();
266
267 if (plid > 0) {
268 try {
269 layout = LayoutLocalServiceUtil.getLayout(plid);
270 }
271 catch (NoSuchLayoutException nsle) {
272 }
273 }
274
275 String rss = exportToRSS(feed, languageId, layout, themeDisplay);
276
277 return rss.getBytes(StringPool.UTF8);
278 }
279
280 protected String processContent(
281 JournalFeed feed, JournalArticle article, String languageId,
282 ThemeDisplay themeDisplay, SyndEntry syndEntry,
283 SyndContent syndContent)
284 throws Exception {
285
286 String content = article.getDescription();
287
288 String contentField = feed.getContentField();
289
290 if (contentField.equals(JournalFeedImpl.RENDERED_ARTICLE)) {
291 String rendererTemplateId = article.getTemplateId();
292
293 if (Validator.isNotNull(feed.getRendererTemplateId())) {
294 rendererTemplateId = feed.getRendererTemplateId();
295 }
296
297 JournalArticleDisplay articleDisplay =
298 JournalContentUtil.getDisplay(
299 feed.getGroupId(), article.getArticleId(),
300 rendererTemplateId, languageId, themeDisplay, 1,
301 _XML_REQUUEST);
302
303 if (articleDisplay != null) {
304 content = articleDisplay.getContent();
305 }
306 }
307 else if (!contentField.equals(JournalFeedImpl.ARTICLE_DESCRIPTION)) {
308 Document doc = DocumentUtil.readDocumentFromXML(
309 article.getContent());
310
311 XPath xpathSelector = DocumentHelper.createXPath(
312 "//dynamic-element[@name='" + contentField + "']");
313
314 List<Element> results = xpathSelector.selectNodes(doc);
315
316 if (results.size() == 0) {
317 return content;
318 }
319
320 Element el = results.get(0);
321
322 String elType = el.attributeValue("type");
323
324 if (elType.equals("document_library")) {
325 String url = el.elementText("dynamic-content");
326
327 url = processURL(feed, url, themeDisplay, syndEntry);
328 }
329 else if (elType.equals("image") || elType.equals("image_gallery")) {
330 String url = el.elementText("dynamic-content");
331
332 url = processURL(feed, url, themeDisplay, syndEntry);
333
334 content =
335 content + "<br /><br /><img src='" +
336 themeDisplay.getURLPortal() + url + "' />";
337 }
338 else if (elType.equals("text_box")) {
339 syndContent.setType("text");
340
341 content = el.elementText("dynamic-content");
342 }
343 else {
344 content = el.elementText("dynamic-content");
345 }
346 }
347
348 return content;
349 }
350
351 protected String processURL(
352 JournalFeed feed, String url, ThemeDisplay themeDisplay,
353 SyndEntry syndEntry) {
354
355 url = StringUtil.replace(
356 url,
357 new String[] {
358 "@group_id@",
359 "@image_path@",
360 "@main_path@"
361 },
362 new String[] {
363 String.valueOf(feed.getGroupId()),
364 themeDisplay.getPathImage(),
365 themeDisplay.getPathMain()
366 }
367 );
368
369 List<SyndLink> links = JournalRSSUtil.getDLLinks(
370 themeDisplay.getURLPortal(), url);
371 List<SyndEnclosure> enclosures = JournalRSSUtil.getDLEnclosures(
372 themeDisplay.getURLPortal(), url);
373
374 syndEntry.setLinks(links);
375 syndEntry.setEnclosures(enclosures);
376
377 return url;
378 }
379
380 private static final String _XML_REQUUEST =
381 "<request><parameters><parameter><name>rss</name><value>true</value>" +
382 "</parameter></parameters></request>";
383
384 private static Log _log = LogFactory.getLog(RSSAction.class);
385
386 }