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