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 themeDisplay.getURLPortal() +
119 PortalUtil.getLayoutFriendlyURL(layout, themeDisplay) +
120 "/journal/rss/" + feed.getId();
121
122 SyndFeed syndFeed = new SyndFeedImpl();
123
124 syndFeed.setFeedType(feed.getFeedType() + "_" + feed.getFeedVersion());
125 syndFeed.setTitle(feed.getName());
126 syndFeed.setLink(feedURL);
127 syndFeed.setDescription(feed.getDescription());
128
129 List entries = new ArrayList();
130
131 syndFeed.setEntries(entries);
132
133 List articles = JournalRSSUtil.getArticles(feed);
134
135 if (_log.isDebugEnabled()) {
136 _log.debug("Syndicating " + articles.size() + " articles");
137 }
138
139 Iterator itr = articles.iterator();
140
141 while (itr.hasNext()) {
142 JournalArticle article = (JournalArticle)itr.next();
143
144 String author = PortalUtil.getUserName(
145 article.getUserId(), article.getUserName());
146 String link = getEntryURL(feed, article, layout, themeDisplay);
147
148 SyndEntry syndEntry = new SyndEntryImpl();
149
150 syndEntry.setAuthor(author);
151 syndEntry.setTitle(article.getTitle());
152 syndEntry.setLink(link);
153 syndEntry.setPublishedDate(article.getDisplayDate());
154
155 SyndContent syndContent = new SyndContentImpl();
156
157 String value = article.getDescription();
158
159 try {
160 value = processContent(
161 feed, article, languageId, themeDisplay, syndEntry,
162 syndContent);
163 }
164 catch (Exception e) {
165 if (_log.isWarnEnabled()) {
166 _log.warn(e, e);
167 }
168 }
169
170 syndContent.setType("html");
171 syndContent.setValue(value);
172
173 syndEntry.setDescription(syndContent);
174
175 entries.add(syndEntry);
176 }
177
178 try {
179 return RSSUtil.export(syndFeed);
180 }
181 catch (FeedException fe) {
182 throw new SystemException(fe);
183 }
184 catch (IOException ioe) {
185 throw new SystemException(ioe);
186 }
187 }
188
189 protected String getEntryURL(
190 JournalFeed feed, JournalArticle article, Layout layout,
191 ThemeDisplay themeDisplay)
192 throws Exception {
193
194 StringMaker sm = new StringMaker();
195
196 List hitLayoutIds = JournalContentSearchLocalServiceUtil.getLayoutIds(
197 layout.getGroupId(), layout.isPrivateLayout(),
198 article.getArticleId());
199
200 if (hitLayoutIds.size() > 0) {
201 Long hitLayoutId = (Long)hitLayoutIds.get(0);
202
203 Layout hitLayout = LayoutLocalServiceUtil.getLayout(
204 layout.getGroupId(), layout.isPrivateLayout(),
205 hitLayoutId.longValue());
206
207 return themeDisplay.getURLPortal() +
208 PortalUtil.getLayoutURL(hitLayout, themeDisplay);
209 }
210 else if (Validator.isNotNull(feed.getTargetLayoutFriendlyUrl())) {
211 sm.append(themeDisplay.getURLPortal());
212 sm.append(feed.getTargetLayoutFriendlyUrl());
213 }
214 else {
215 sm.append(themeDisplay.getURLPortal());
216 sm.append(PortalUtil.getLayoutFriendlyURL(layout, themeDisplay));
217 }
218
219 sm.append("/journal_content/");
220
221 if (Validator.isNotNull(feed.getTargetPortletId())) {
222 sm.append(feed.getTargetPortletId());
223 }
224 else {
225 sm.append(PortletKeys.JOURNAL_CONTENT);
226 }
227
228 sm.append(StringPool.SLASH);
229 sm.append(article.getGroupId());
230 sm.append(StringPool.SLASH);
231 sm.append(article.getArticleId());
232
233 return sm.toString();
234 }
235
236 protected byte[] getRSS(RenderRequest req) throws Exception {
237 ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
238 WebKeys.THEME_DISPLAY);
239
240 JournalFeed feed = null;
241
242 long id = ParamUtil.getLong(req, "id");
243
244 long groupId = ParamUtil.getLong(req, "groupId");
245 String feedId = ParamUtil.getString(req, "feedId");
246
247 if (id > 0) {
248 feed = JournalFeedLocalServiceUtil.getFeed(id);
249 }
250 else {
251 feed = JournalFeedLocalServiceUtil.getFeed(groupId, feedId);
252 }
253
254 String languageId = LanguageUtil.getLanguageId(req);
255
256 long plid = PortalUtil.getPlidIdFromFriendlyURL(
257 themeDisplay.getCompanyId(), feed.getTargetLayoutFriendlyUrl());
258
259 Layout layout = themeDisplay.getLayout();
260
261 if (plid > 0) {
262 try {
263 layout = LayoutLocalServiceUtil.getLayout(plid);
264 }
265 catch (NoSuchLayoutException nsle) {
266 }
267 }
268
269 String rss = exportToRSS(feed, languageId, layout, 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_ARTICLE)) {
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, languageId, themeDisplay, 1,
295 _XML_REQUUEST);
296
297 if (articleDisplay != null) {
298 content = articleDisplay.getContent();
299 }
300 }
301 else if (!contentField.equals(JournalFeedImpl.ARTICLE_DESCRIPTION)) {
302 Document doc = PortalUtil.readDocumentFromXML(article.getContent());
303
304 XPath xpathSelector = DocumentHelper.createXPath(
305 "//dynamic-element[@name='" + contentField + "']");
306
307 List results = xpathSelector.selectNodes(doc);
308
309 if (results.size() == 0) {
310 return content;
311 }
312
313 Element el = (Element)results.get(0);
314
315 String elType = el.attributeValue("type");
316
317 if (elType.equals("document_library")) {
318 String url = el.elementText("dynamic-content");
319
320 url = processURL(feed, url, themeDisplay, syndEntry);
321 }
322 else if (elType.equals("image") || elType.equals("image_gallery")) {
323 String url = el.elementText("dynamic-content");
324
325 url = processURL(feed, url, themeDisplay, syndEntry);
326
327 content =
328 content + "<br /><br /><img src='" +
329 themeDisplay.getURLPortal() + url + "' />";
330 }
331 else if (elType.equals("text_box")) {
332 syndContent.setType("text");
333
334 content = el.elementText("dynamic-content");
335 }
336 else {
337 content = el.elementText("dynamic-content");
338 }
339 }
340
341 return content;
342 }
343
344 protected String processURL(
345 JournalFeed feed, String url, ThemeDisplay themeDisplay,
346 SyndEntry syndEntry) {
347
348 url = StringUtil.replace(
349 url,
350 new String[] {
351 "@group_id@",
352 "@image_path@",
353 "@main_path@"
354 },
355 new String[] {
356 String.valueOf(feed.getGroupId()),
357 themeDisplay.getPathImage(),
358 themeDisplay.getPathMain()
359 }
360 );
361
362 List links = JournalRSSUtil.getDLLinks(
363 themeDisplay.getURLPortal(), url);
364 List enclosures = JournalRSSUtil.getDLEnclosures(
365 themeDisplay.getURLPortal(), url);
366
367 syndEntry.setLinks(links);
368 syndEntry.setEnclosures(enclosures);
369
370 return url;
371 }
372
373 private static final String _XML_REQUUEST =
374 "<request><parameters><parameter><name>rss</name><value>true</value>" +
375 "</parameter></parameters></request>";
376
377 private static Log _log = LogFactory.getLog(RSSAction.class);
378
379 }