1
22
23 package com.liferay.portlet.wiki.service.impl;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.language.LanguageUtil;
28 import com.liferay.portal.kernel.util.GetterUtil;
29 import com.liferay.portal.kernel.util.HtmlUtil;
30 import com.liferay.portal.kernel.util.ObjectValuePair;
31 import com.liferay.portal.kernel.util.StringPool;
32 import com.liferay.portal.kernel.util.StringUtil;
33 import com.liferay.portal.security.permission.ActionKeys;
34 import com.liferay.portal.theme.ThemeDisplay;
35 import com.liferay.portal.util.ContentUtil;
36 import com.liferay.portal.util.PortalUtil;
37 import com.liferay.portal.util.PortletKeys;
38 import com.liferay.portal.util.PropsKeys;
39 import com.liferay.portal.util.PropsUtil;
40 import com.liferay.portal.velocity.VelocityUtil;
41 import com.liferay.portlet.wiki.model.WikiNode;
42 import com.liferay.portlet.wiki.model.WikiPage;
43 import com.liferay.portlet.wiki.service.base.WikiPageServiceBaseImpl;
44 import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
45 import com.liferay.portlet.wiki.service.permission.WikiPagePermission;
46 import com.liferay.portlet.wiki.util.WikiUtil;
47 import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
48 import com.liferay.util.RSSUtil;
49 import com.liferay.util.diff.DiffResult;
50 import com.liferay.util.diff.DiffUtil;
51
52 import com.sun.syndication.feed.synd.SyndContent;
53 import com.sun.syndication.feed.synd.SyndContentImpl;
54 import com.sun.syndication.feed.synd.SyndEntry;
55 import com.sun.syndication.feed.synd.SyndEntryImpl;
56 import com.sun.syndication.feed.synd.SyndFeed;
57 import com.sun.syndication.feed.synd.SyndFeedImpl;
58 import com.sun.syndication.io.FeedException;
59
60 import java.io.IOException;
61 import java.io.StringReader;
62
63 import java.util.ArrayList;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Locale;
68 import java.util.Map;
69
70 import javax.portlet.PortletPreferences;
71
72
79 public class WikiPageServiceImpl extends WikiPageServiceBaseImpl {
80
81 public WikiPage addPage(
82 long nodeId, String title, String content, String summary,
83 boolean minorEdit, PortletPreferences prefs,
84 ThemeDisplay themeDisplay)
85 throws PortalException, SystemException {
86
87 WikiNodePermission.check(
88 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
89
90 return wikiPageLocalService.addPage(
91 getUserId(), nodeId, title, content, summary, minorEdit, prefs,
92 themeDisplay);
93 }
94
95 public void addPageAttachments(
96 long nodeId, String title,
97 List<ObjectValuePair<String, byte[]>> files)
98 throws PortalException, SystemException {
99
100 WikiNodePermission.check(
101 getPermissionChecker(), nodeId, ActionKeys.ADD_ATTACHMENT);
102
103 wikiPageLocalService.addPageAttachments(nodeId, title, files);
104 }
105
106 public void changeParent(
107 long nodeId, String title, String newParentTitle,
108 PortletPreferences prefs, ThemeDisplay themeDisplay)
109 throws PortalException, SystemException {
110
111 WikiNodePermission.check(
112 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
113
114 WikiPagePermission.check(
115 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
116
117 wikiPageLocalService.changeParent(
118 getUserId(), nodeId, title, newParentTitle, prefs, themeDisplay);
119 }
120
121 public void deletePage(long nodeId, String title)
122 throws PortalException, SystemException {
123
124 WikiPagePermission.check(
125 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
126
127 wikiPageLocalService.deletePage(nodeId, title);
128 }
129
130 public void deletePageAttachment(long nodeId, String title, String fileName)
131 throws PortalException, SystemException {
132
133 WikiPagePermission.check(
134 getPermissionChecker(), nodeId, title, ActionKeys.DELETE);
135
136 wikiPageLocalService.deletePageAttachment(nodeId, title, fileName);
137 }
138
139 public List<WikiPage> getNodePages(long nodeId, int max)
140 throws PortalException, SystemException {
141
142 List<WikiPage> pages = new ArrayList<WikiPage>();
143
144 int lastIntervalStart = 0;
145 boolean listNotExhausted = true;
146
147 while ((pages.size() < max) && listNotExhausted) {
148 List<WikiPage> pageList = wikiPageLocalService.getPages(
149 nodeId, true, lastIntervalStart, lastIntervalStart + max);
150
151 Iterator<WikiPage> itr = pageList.iterator();
152
153 lastIntervalStart += max;
154 listNotExhausted = (pageList.size() == max);
155
156 while (itr.hasNext() && (pages.size() < max)) {
157 WikiPage page = itr.next();
158
159 if (WikiPagePermission.contains(getPermissionChecker(), page,
160 ActionKeys.VIEW)) {
161
162 pages.add(page);
163 }
164 }
165 }
166
167 return pages;
168 }
169
170 public String getNodePagesRSS(
171 long nodeId, int max, String type, double version,
172 String displayStyle, String feedURL, String entryURL)
173 throws PortalException, SystemException {
174
175 WikiNodePermission.check(
176 getPermissionChecker(), nodeId, ActionKeys.VIEW);
177
178 WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
179
180 long companyId = node.getCompanyId();
181 String name = node.getName();
182 String description = node.getDescription();
183 List<WikiPage> pages = getNodePages(nodeId, max);
184 boolean diff = false;
185 Locale locale = null;
186
187 return exportToRSS(
188 companyId, name, description, type, version, displayStyle,
189 feedURL, entryURL, pages, diff, locale);
190 }
191
192 public WikiPage getPage(long nodeId, String title)
193 throws PortalException, SystemException {
194
195 WikiPagePermission.check(
196 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
197
198 return wikiPageLocalService.getPage(nodeId, title);
199 }
200
201 public WikiPage getPage(long nodeId, String title, double version)
202 throws PortalException, SystemException {
203
204 WikiPagePermission.check(
205 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
206
207 return wikiPageLocalService.getPage(nodeId, title, version);
208 }
209
210 public String getPagesRSS(
211 long companyId, long nodeId, String title, int max, String type,
212 double version, String displayStyle, String feedURL,
213 String entryURL, Locale locale)
214 throws PortalException, SystemException {
215
216 WikiPagePermission.check(
217 getPermissionChecker(), nodeId, title, ActionKeys.VIEW);
218
219 String description = title;
220 List<WikiPage> pages = wikiPageLocalService.getPages(
221 nodeId, title, 0, max, new PageCreateDateComparator(true));
222 boolean diff = true;
223
224 return exportToRSS(
225 companyId, title, description, type, version, displayStyle, feedURL,
226 entryURL, pages, diff, locale);
227 }
228
229 public void movePage(
230 long nodeId, String title, String newTitle,
231 PortletPreferences prefs, ThemeDisplay themeDisplay)
232 throws PortalException, SystemException {
233
234 WikiNodePermission.check(
235 getPermissionChecker(), nodeId, ActionKeys.ADD_PAGE);
236
237 WikiPagePermission.check(
238 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
239
240 wikiPageLocalService.movePage(
241 getUserId(), nodeId, title, newTitle, prefs, themeDisplay);
242 }
243
244 public WikiPage revertPage(
245 long nodeId, String title, double version, PortletPreferences prefs,
246 ThemeDisplay themeDisplay)
247 throws PortalException, SystemException {
248
249 WikiPagePermission.check(
250 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
251
252 return wikiPageLocalService.revertPage(
253 getUserId(), nodeId, title, version, prefs, themeDisplay);
254 }
255
256 public void subscribePage(long nodeId, String title)
257 throws PortalException, SystemException {
258
259 WikiPagePermission.check(
260 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
261
262 wikiPageLocalService.subscribePage(getUserId(), nodeId, title);
263 }
264
265 public void unsubscribePage(long nodeId, String title)
266 throws PortalException, SystemException {
267
268 WikiPagePermission.check(
269 getPermissionChecker(), nodeId, title, ActionKeys.SUBSCRIBE);
270
271 wikiPageLocalService.unsubscribePage(getUserId(), nodeId, title);
272 }
273
274 public WikiPage updatePage(
275 long nodeId, String title, double version, String content,
276 String summary, boolean minorEdit, String format,
277 String parentTitle, String redirectTitle, String[] tagsEntries,
278 PortletPreferences prefs, ThemeDisplay themeDisplay)
279 throws PortalException, SystemException {
280
281 WikiPagePermission.check(
282 getPermissionChecker(), nodeId, title, ActionKeys.UPDATE);
283
284 return wikiPageLocalService.updatePage(
285 getUserId(), nodeId, title, version, content, summary, minorEdit,
286 format, parentTitle, redirectTitle, tagsEntries, prefs,
287 themeDisplay);
288 }
289
290 protected String exportToRSS(
291 long companyId, String name, String description, String type,
292 double version, String displayStyle, String feedURL,
293 String entryURL, List<WikiPage> pages, boolean diff, Locale locale)
294 throws SystemException {
295
296 SyndFeed syndFeed = new SyndFeedImpl();
297
298 syndFeed.setFeedType(RSSUtil.getFeedType(type, version));
299 syndFeed.setTitle(name);
300 syndFeed.setLink(feedURL);
301 syndFeed.setDescription(description);
302
303 List<SyndEntry> entries = new ArrayList<SyndEntry>();
304
305 syndFeed.setEntries(entries);
306
307 WikiPage latestPage = null;
308
309 for (WikiPage page : pages) {
310 String author = PortalUtil.getUserName(
311 page.getUserId(), page.getUserName());
312
313 String link = entryURL;
314
315 SyndEntry syndEntry = new SyndEntryImpl();
316
317 syndEntry.setAuthor(author);
318 syndEntry.setTitle(
319 page.getTitle() + StringPool.SPACE + page.getVersion());
320 syndEntry.setPublishedDate(page.getCreateDate());
321
322 SyndContent syndContent = new SyndContentImpl();
323
324 syndContent.setType(RSSUtil.DEFAULT_ENTRY_TYPE);
325
326 if (diff) {
327 if (latestPage != null) {
328 link +=
329 "?" + PortalUtil.getPortletNamespace(PortletKeys.WIKI) +
330 "version=" + page.getVersion();
331
332 String value = getPageDiff(
333 companyId, latestPage, page, locale);
334
335 syndContent.setValue(value);
336
337 syndEntry.setDescription(syndContent);
338
339 entries.add(syndEntry);
340 }
341 }
342 else {
343 String value = null;
344
345 if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_ABSTRACT)) {
346 value = StringUtil.shorten(
347 HtmlUtil.extractText(page.getContent()),
348 _RSS_ABSTRACT_LENGTH, StringPool.BLANK);
349 }
350 else if (displayStyle.equals(RSSUtil.DISPLAY_STYLE_TITLE)) {
351 value = StringPool.BLANK;
352 }
353 else {
354 value = page.getContent();
355 }
356
357 syndContent.setValue(value);
358
359 syndEntry.setDescription(syndContent);
360
361 entries.add(syndEntry);
362 }
363
364 syndEntry.setLink(link);
365
366 latestPage = page;
367 }
368
369 try {
370 return RSSUtil.export(syndFeed);
371 }
372 catch (FeedException fe) {
373 throw new SystemException(fe);
374 }
375 catch (IOException ioe) {
376 throw new SystemException(ioe);
377 }
378 }
379
380 protected String getPageDiff(
381 long companyId, WikiPage latestPage, WikiPage page,
382 Locale locale)
383 throws SystemException {
384
385 String sourceContent = WikiUtil.processContent(latestPage.getContent());
386 String targetContent = WikiUtil.processContent(page.getContent());
387
388 sourceContent = HtmlUtil.escape(sourceContent);
389 targetContent = HtmlUtil.escape(targetContent);
390
391 List<DiffResult>[] diffResults = DiffUtil.diff(
392 new StringReader(sourceContent), new StringReader(targetContent));
393
394 String template = ContentUtil.get(
395 "com/liferay/portlet/wiki/dependencies/rss.vm");
396
397 Map<String, Object> variables = new HashMap<String, Object>();
398
399 variables.put("companyId", companyId);
400 variables.put("contextLine", DiffUtil.CONTEXT_LINE);
401 variables.put("diffUtil", new DiffUtil());
402 variables.put("languageUtil", LanguageUtil.getLanguage());
403 variables.put("locale", locale);
404 variables.put("sourceResults", diffResults[0]);
405 variables.put("targetResults", diffResults[1]);
406
407 try {
408 return VelocityUtil.evaluate(template, variables);
409 }
410 catch (Exception e) {
411 throw new SystemException(e);
412 }
413 }
414
415 private static final int _RSS_ABSTRACT_LENGTH = GetterUtil.getInteger(
416 PropsUtil.get(PropsKeys.WIKI_RSS_ABSTRACT_LENGTH));
417
418 }