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.PortalUtil;
41 import com.liferay.portal.util.PortletKeys;
42 import com.liferay.portal.util.WebKeys;
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.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.io.FeedException;
60
61 import java.io.IOException;
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.RenderRequest;
70 import javax.portlet.RenderResponse;
71
72 import org.apache.commons.logging.Log;
73 import org.apache.commons.logging.LogFactory;
74 import org.apache.struts.action.ActionForm;
75 import org.apache.struts.action.ActionForward;
76 import org.apache.struts.action.ActionMapping;
77
78 import org.dom4j.Document;
79 import org.dom4j.DocumentHelper;
80 import org.dom4j.Element;
81 import org.dom4j.XPath;
82
83
89 public class RSSAction extends PortletAction {
90
91 public ActionForward render(
92 ActionMapping mapping, ActionForm form, PortletConfig config,
93 RenderRequest req, RenderResponse res)
94 throws Exception {
95
96 if (req.getWindowState() == LiferayWindowState.EXCLUSIVE) {
97 res.setContentType(ContentTypes.TEXT_XML_UTF8);
98
99 OutputStream out = res.getPortletOutputStream();
100
101 try {
102 out.write(getRSS(req));
103 }
104 finally {
105 out.close();
106 }
107 }
108
109 return mapping.findForward(ActionConstants.COMMON_NULL);
110 }
111
112 protected String exportToRSS(
113 JournalFeed feed, String languageId, Layout layout,
114 ThemeDisplay themeDisplay)
115 throws Exception {
116
117 String feedURL =
118 PortalUtil.getLayoutFriendlyURL(layout, themeDisplay) +
119 "/journal/rss/" + feed.getGroupId() + "/" + feed.getFeedId();
120
121 SyndFeed syndFeed = new SyndFeedImpl();
122
123 syndFeed.setFeedType(feed.getFeedType() + "_" + feed.getFeedVersion());
124 syndFeed.setTitle(feed.getName());
125 syndFeed.setLink(feedURL);
126 syndFeed.setDescription(feed.getDescription());
127
128 List entries = new ArrayList();
129
130 syndFeed.setEntries(entries);
131
132 List articles = JournalRSSUtil.getArticles(feed);
133
134 if (_log.isDebugEnabled()) {
135 _log.debug("Syndicating " + articles.size() + " articles");
136 }
137
138 Iterator itr = articles.iterator();
139
140 while (itr.hasNext()) {
141 JournalArticle article = (JournalArticle)itr.next();
142
143 String author = PortalUtil.getUserName(
144 article.getUserId(), article.getUserName());
145 String link = getEntryURL(feed, article, layout, themeDisplay);
146
147 SyndEntry syndEntry = new SyndEntryImpl();
148
149 syndEntry.setAuthor(author);
150 syndEntry.setTitle(article.getTitle());
151 syndEntry.setLink(link);
152 syndEntry.setPublishedDate(article.getDisplayDate());
153
154 SyndContent syndContent = new SyndContentImpl();
155
156 String value = article.getDescription();
157
158 try {
159 value = processContent(
160 feed, article, languageId, themeDisplay, syndEntry,
161 syndContent);
162 }
163 catch (Exception e) {
164 if (_log.isWarnEnabled()) {
165 _log.warn(e, e);
166 }
167 }
168
169 syndContent.setType("html");
170 syndContent.setValue(value);
171
172 syndEntry.setDescription(syndContent);
173
174 entries.add(syndEntry);
175 }
176
177 try {
178 return RSSUtil.export(syndFeed);
179 }
180 catch (FeedException fe) {
181 throw new SystemException(fe);
182 }
183 catch (IOException ioe) {
184 throw new SystemException(ioe);
185 }
186 }
187
188 protected String getEntryURL(
189 JournalFeed feed, JournalArticle article, Layout layout,
190 ThemeDisplay themeDisplay)
191 throws Exception {
192
193 StringMaker sm = new StringMaker();
194
195 List hitLayoutIds = JournalContentSearchLocalServiceUtil.getLayoutIds(
196 layout.getGroupId(), layout.isPrivateLayout(),
197 article.getArticleId());
198
199 if (hitLayoutIds.size() > 0) {
200 Long hitLayoutId = (Long)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 if (Validator.isNotNull(feed.getTargetLayoutFriendlyUrl())) {
209 long plid = PortalUtil.getPlidIdFromFriendlyURL(
210 feed.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
211
212 Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
213
214 sm.append(
215 PortalUtil.getLayoutFriendlyURL(targetLayout, themeDisplay));
216 }
217 else {
218 sm.append(PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
219 }
220
221 sm.append("/journal_content/");
222
223 if (Validator.isNotNull(feed.getTargetPortletId())) {
224 sm.append(feed.getTargetPortletId());
225 }
226 else {
227 sm.append(PortletKeys.JOURNAL_CONTENT);
228 }
229
230 sm.append(StringPool.SLASH);
231 sm.append(article.getGroupId());
232 sm.append(StringPool.SLASH);
233 sm.append(article.getArticleId());
234
235 return sm.toString();
236 }
237
238 protected byte[] getRSS(RenderRequest req) throws Exception {
239 ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
240 WebKeys.THEME_DISPLAY);
241
242 JournalFeed feed = null;
243
244 long id = ParamUtil.getLong(req, "id");
245
246 long groupId = ParamUtil.getLong(req, "groupId");
247 String feedId = ParamUtil.getString(req, "feedId");
248
249 if (id > 0) {
250 feed = JournalFeedLocalServiceUtil.getFeed(id);
251 }
252 else {
253 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
254 }
255
256 String languageId = LanguageUtil.getLanguageId(req);
257
258 long plid = PortalUtil.getPlidIdFromFriendlyURL(
259 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
260
261 Layout layout = themeDisplay.getLayout();
262
263 if (plid > 0) {
264 try {
265 layout = LayoutLocalServiceUtil.getLayout(plid);
266 }
267 catch (NoSuchLayoutException nsle) {
268 }
269 }
270
271 String rss = exportToRSS(feed, languageId, layout, themeDisplay);
272
273 return rss.getBytes(StringPool.UTF8);
274 }
275
276 protected String processContent(
277 JournalFeed feed, JournalArticle article, String languageId,
278 ThemeDisplay themeDisplay, SyndEntry syndEntry,
279 SyndContent syndContent)
280 throws Exception {
281
282 String content = article.getDescription();
283
284 String contentField = feed.getContentField();
285
286 if (contentField.equals(JournalFeedImpl.RENDERED_ARTICLE)) {
287 String rendererTemplateId = article.getTemplateId();
288
289 if (Validator.isNotNull(feed.getRendererTemplateId())) {
290 rendererTemplateId = feed.getRendererTemplateId();
291 }
292
293 JournalArticleDisplay articleDisplay =
294 JournalContentUtil.getDisplay(
295 feed.getGroupId(), article.getArticleId(),
296 rendererTemplateId, languageId, themeDisplay, 1,
297 _XML_REQUUEST);
298
299 if (articleDisplay != null) {
300 content = articleDisplay.getContent();
301 }
302 }
303 else if (!contentField.equals(JournalFeedImpl.ARTICLE_DESCRIPTION)) {
304 Document doc = PortalUtil.readDocumentFromXML(article.getContent());
305
306 XPath xpathSelector = DocumentHelper.createXPath(
307 "//dynamic-element[@name='" + contentField + "']");
308
309 List 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 links = JournalRSSUtil.getDLLinks(
365 themeDisplay.getURLPortal(), url);
366 List 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 = LogFactory.getLog(RSSAction.class);
380
381 }