001
014
015 package com.liferay.portlet.wiki.util;
016
017 import com.liferay.portal.kernel.configuration.Filter;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
022 import com.liferay.portal.kernel.util.DiffHtmlUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.HtmlUtil;
025 import com.liferay.portal.kernel.util.HttpUtil;
026 import com.liferay.portal.kernel.util.InstancePool;
027 import com.liferay.portal.kernel.util.ListUtil;
028 import com.liferay.portal.kernel.util.OrderByComparator;
029 import com.liferay.portal.kernel.util.ParamUtil;
030 import com.liferay.portal.kernel.util.PropsKeys;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.security.permission.ActionKeys;
036 import com.liferay.portal.security.permission.PermissionChecker;
037 import com.liferay.portal.theme.ThemeDisplay;
038 import com.liferay.portal.util.PortalUtil;
039 import com.liferay.portal.util.PropsUtil;
040 import com.liferay.portal.util.PropsValues;
041 import com.liferay.portal.util.WebKeys;
042 import com.liferay.portlet.PortletURLUtil;
043 import com.liferay.portlet.wiki.PageContentException;
044 import com.liferay.portlet.wiki.WikiFormatException;
045 import com.liferay.portlet.wiki.engines.WikiEngine;
046 import com.liferay.portlet.wiki.model.WikiNode;
047 import com.liferay.portlet.wiki.model.WikiPage;
048 import com.liferay.portlet.wiki.model.WikiPageDisplay;
049 import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
050 import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
051 import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
052 import com.liferay.portlet.wiki.util.comparator.PageTitleComparator;
053 import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
054 import com.liferay.util.ContentUtil;
055
056 import java.io.IOException;
057
058 import java.util.ArrayList;
059 import java.util.Arrays;
060 import java.util.Collections;
061 import java.util.Iterator;
062 import java.util.List;
063 import java.util.Map;
064 import java.util.concurrent.ConcurrentHashMap;
065 import java.util.regex.Matcher;
066 import java.util.regex.Pattern;
067
068 import javax.portlet.PortletPreferences;
069 import javax.portlet.PortletRequest;
070 import javax.portlet.PortletURL;
071 import javax.portlet.RenderRequest;
072 import javax.portlet.RenderResponse;
073
074
078 public class WikiUtil {
079
080 public static String convert(
081 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
082 String attachmentURLPrefix)
083 throws PageContentException, WikiFormatException {
084
085 return _instance._convert(
086 page, viewPageURL, editPageURL, attachmentURLPrefix);
087 }
088
089 public static String diffHtml(
090 WikiPage sourcePage, WikiPage targetPage, PortletURL viewPageURL,
091 PortletURL editPageURL, String attachmentURLPrefix)
092 throws Exception {
093
094 String sourceContent = StringPool.BLANK;
095 String targetContent = StringPool.BLANK;
096
097 if (sourcePage != null) {
098 sourceContent = WikiUtil.convert(
099 sourcePage, viewPageURL, editPageURL, attachmentURLPrefix);
100 }
101
102 if (targetPage != null) {
103 targetContent = WikiUtil.convert(
104 targetPage, viewPageURL, editPageURL, attachmentURLPrefix);
105 }
106
107 return DiffHtmlUtil.diff(
108 new UnsyncStringReader(sourceContent),
109 new UnsyncStringReader(targetContent));
110 }
111
112 public static String getEditPage(String format) {
113 return _instance._getEditPage(format);
114 }
115
116 public static String getEmailFromAddress(
117 PortletPreferences preferences, long companyId)
118 throws SystemException {
119
120 return PortalUtil.getEmailFromAddress(
121 preferences, companyId, PropsValues.WIKI_EMAIL_FROM_ADDRESS);
122 }
123
124 public static String getEmailFromName(
125 PortletPreferences preferences, long companyId)
126 throws SystemException {
127
128 return PortalUtil.getEmailFromName(
129 preferences, companyId, PropsValues.WIKI_EMAIL_FROM_NAME);
130 }
131
132 public static String getEmailPageAddedBody(PortletPreferences preferences) {
133 String emailPageAddedBody = preferences.getValue(
134 "emailPageAddedBody", StringPool.BLANK);
135
136 if (Validator.isNotNull(emailPageAddedBody)) {
137 return emailPageAddedBody;
138 }
139 else {
140 return ContentUtil.get(
141 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_BODY));
142 }
143 }
144
145 public static boolean getEmailPageAddedEnabled(
146 PortletPreferences preferences) {
147
148 String emailPageAddedEnabled = preferences.getValue(
149 "emailPageAddedEnabled", StringPool.BLANK);
150
151 if (Validator.isNotNull(emailPageAddedEnabled)) {
152 return GetterUtil.getBoolean(emailPageAddedEnabled);
153 }
154 else {
155 return GetterUtil.getBoolean(
156 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_ENABLED));
157 }
158 }
159
160 public static String getEmailPageAddedSignature(
161 PortletPreferences preferences) {
162
163 String emailPageAddedSignature = preferences.getValue(
164 "emailPageAddedSignature", StringPool.BLANK);
165
166 if (Validator.isNotNull(emailPageAddedSignature)) {
167 return emailPageAddedSignature;
168 }
169 else {
170 return ContentUtil.get(
171 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
172 }
173 }
174
175 public static String getEmailPageAddedSubjectPrefix(
176 PortletPreferences preferences) {
177
178 String emailPageAddedSubjectPrefix = preferences.getValue(
179 "emailPageAddedSubjectPrefix", StringPool.BLANK);
180
181 if (Validator.isNotNull(emailPageAddedSubjectPrefix)) {
182 return emailPageAddedSubjectPrefix;
183 }
184 else {
185 return ContentUtil.get(
186 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_SUBJECT_PREFIX));
187 }
188 }
189
190 public static String getEmailPageUpdatedBody(
191 PortletPreferences preferences) {
192
193 String emailPageUpdatedBody = preferences.getValue(
194 "emailPageUpdatedBody", StringPool.BLANK);
195
196 if (Validator.isNotNull(emailPageUpdatedBody)) {
197 return emailPageUpdatedBody;
198 }
199 else {
200 return ContentUtil.get(
201 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_BODY));
202 }
203 }
204
205 public static boolean getEmailPageUpdatedEnabled(
206 PortletPreferences preferences) {
207
208 String emailPageUpdatedEnabled = preferences.getValue(
209 "emailPageUpdatedEnabled", StringPool.BLANK);
210
211 if (Validator.isNotNull(emailPageUpdatedEnabled)) {
212 return GetterUtil.getBoolean(emailPageUpdatedEnabled);
213 }
214 else {
215 return GetterUtil.getBoolean(
216 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
217 }
218 }
219
220 public static String getEmailPageUpdatedSignature(
221 PortletPreferences preferences) {
222
223 String emailPageUpdatedSignature = preferences.getValue(
224 "emailPageUpdatedSignature", StringPool.BLANK);
225
226 if (Validator.isNotNull(emailPageUpdatedSignature)) {
227 return emailPageUpdatedSignature;
228 }
229 else {
230 return ContentUtil.get(
231 PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
232 }
233 }
234
235 public static String getEmailPageUpdatedSubjectPrefix(
236 PortletPreferences preferences) {
237
238 String emailPageUpdatedSubject = preferences.getValue(
239 "emailPageUpdatedSubjectPrefix", StringPool.BLANK);
240
241 if (Validator.isNotNull(emailPageUpdatedSubject)) {
242 return emailPageUpdatedSubject;
243 }
244 else {
245 return ContentUtil.get(
246 PropsUtil.get(
247 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SUBJECT_PREFIX));
248 }
249 }
250
251 public static WikiNode getFirstNode(PortletRequest portletRequest)
252 throws PortalException, SystemException {
253
254 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
255 WebKeys.THEME_DISPLAY);
256 long groupId = themeDisplay.getScopeGroupId();
257 PermissionChecker permissionChecker =
258 themeDisplay.getPermissionChecker();
259
260 List<WikiNode> nodes = WikiNodeLocalServiceUtil.getNodes(groupId);
261
262 PortletPreferences preferences = portletRequest.getPreferences();
263 String[] visibleNodeNames = StringUtil.split(
264 preferences.getValue("visibleNodes", null));
265 nodes = orderNodes(nodes, visibleNodeNames);
266
267 String[] hiddenNodes = StringUtil.split(
268 preferences.getValue("hiddenNodes", StringPool.BLANK));
269 Arrays.sort(hiddenNodes);
270
271 for (WikiNode node : nodes) {
272 if ((Arrays.binarySearch(hiddenNodes, node.getName()) < 0) &&
273 (WikiNodePermission.contains(
274 permissionChecker, node, ActionKeys.VIEW))) {
275
276 return node;
277 }
278 }
279
280 return null;
281 }
282
283 public static String getFormattedContent(
284 RenderRequest renderRequest, RenderResponse renderResponse,
285 WikiPage wikiPage, PortletURL viewPageURL, PortletURL editPageURL,
286 String title, boolean preview)
287 throws Exception {
288
289 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
290 WebKeys.THEME_DISPLAY);
291
292 double version = ParamUtil.getDouble(renderRequest, "version");
293
294 PortletURL curViewPageURL = PortletURLUtil.clone(
295 viewPageURL, renderResponse);
296 PortletURL curEditPageURL = PortletURLUtil.clone(
297 editPageURL, renderResponse);
298
299 StringBundler sb = new StringBundler();
300
301 sb.append(themeDisplay.getPathMain());
302 sb.append("/wiki/get_page_attachment?p_l_id=");
303 sb.append(themeDisplay.getPlid());
304 sb.append("&nodeId=");
305 sb.append(wikiPage.getNodeId());
306 sb.append("&title=");
307 sb.append(HttpUtil.encodeURL(wikiPage.getTitle()));
308 sb.append("&fileName=");
309
310 String attachmentURLPrefix = sb.toString();
311
312 if (!preview && (version == 0)) {
313 WikiPageDisplay pageDisplay = WikiCacheUtil.getDisplay(
314 wikiPage.getNodeId(), title, curViewPageURL, curEditPageURL,
315 attachmentURLPrefix);
316
317 if (pageDisplay != null) {
318 return pageDisplay.getFormattedContent();
319 }
320 }
321
322 return WikiUtil.convert(
323 wikiPage, curViewPageURL, curEditPageURL, attachmentURLPrefix);
324 }
325
326 public static String getHelpPage(String format) {
327 return _instance._getHelpPage(format);
328 }
329
330 public static String getHelpURL(String format) {
331 return _instance._getHelpURL(format);
332 }
333
334 public static Map<String, Boolean> getLinks(WikiPage page)
335 throws PageContentException {
336
337 return _instance._getLinks(page);
338 }
339
340 public static List<String> getNodeNames(List<WikiNode> nodes) {
341 List<String> nodeNames = new ArrayList<String>(nodes.size());
342
343 for (WikiNode node : nodes) {
344 nodeNames.add(node.getName());
345 }
346
347 return nodeNames;
348 }
349
350 public static List<WikiNode> getNodes(
351 List<WikiNode> nodes, String[] hiddenNodes,
352 PermissionChecker permissionChecker) {
353
354 nodes = ListUtil.copy(nodes);
355
356 Arrays.sort(hiddenNodes);
357
358 Iterator<WikiNode> itr = nodes.iterator();
359
360 while (itr.hasNext()) {
361 WikiNode node = itr.next();
362
363 if (!(Arrays.binarySearch(hiddenNodes, node.getName()) < 0) ||
364 !WikiNodePermission.contains(
365 permissionChecker, node, ActionKeys.VIEW)) {
366
367 itr.remove();
368 }
369 }
370
371 return nodes;
372 }
373
374 public static OrderByComparator getPageOrderByComparator(
375 String orderByCol, String orderByType) {
376
377 boolean orderByAsc = false;
378
379 if (orderByType.equals("asc")) {
380 orderByAsc = true;
381 }
382
383 OrderByComparator orderByComparator = null;
384
385 if (orderByCol.equals("modifiedDate")) {
386 orderByComparator = new PageCreateDateComparator(orderByAsc);
387 }
388 else if (orderByCol.equals("title")) {
389 orderByComparator = new PageTitleComparator(orderByAsc);
390 }
391 else if (orderByCol.equals("version")) {
392 orderByComparator = new PageVersionComparator(orderByAsc);
393 }
394
395 return orderByComparator;
396 }
397
398 public static List<WikiNode> orderNodes(
399 List<WikiNode> nodes, String[] visibleNodeNames) {
400
401 if ((visibleNodeNames == null) || (visibleNodeNames.length == 0)) {
402 return nodes;
403 }
404
405 nodes = ListUtil.copy(nodes);
406
407 List<WikiNode> orderedNodes = new ArrayList<WikiNode>(nodes.size());
408
409 for (String visibleNodeName : visibleNodeNames) {
410 for (WikiNode node : nodes) {
411 if (node.getName().equals(visibleNodeName)) {
412 orderedNodes.add(node);
413
414 nodes.remove(node);
415
416 break;
417 }
418 }
419 }
420
421 orderedNodes.addAll(nodes);
422
423 return orderedNodes;
424 }
425
426 public static String processContent(String content) {
427 content = content.replaceAll("</p>", "</p>\n");
428 content = content.replaceAll("</br>", "</br>\n");
429 content = content.replaceAll("</div>", "</div>\n");
430
431 return content;
432 }
433
434 public static boolean validate(long nodeId, String content, String format)
435 throws WikiFormatException {
436
437 return _instance._validate(nodeId, content, format);
438 }
439
440 private String _convert(
441 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
442 String attachmentURLPrefix)
443 throws PageContentException, WikiFormatException {
444
445 LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
446 LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
447
448 WikiEngine engine = _getEngine(page.getFormat());
449
450 String content = engine.convert(
451 page, viewPageURL, editPageURL, attachmentURLPrefix);
452
453 String editPageURLString = StringPool.BLANK;
454
455 if (editPageURL != null) {
456 liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
457
458 editPageURLString = editPageURL.toString();
459
460 editPageURLString = StringUtil.replace(
461 editPageURLString, "__REPLACEMENT__", "$1");
462 }
463
464 Matcher matcher = _editPageURLPattern.matcher(content);
465
466 content = _convertURLs(editPageURLString, matcher);
467
468 String viewPageURLString = StringPool.BLANK;
469
470 if (viewPageURL != null) {
471 liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
472
473 viewPageURLString = viewPageURL.toString();
474
475 viewPageURLString = StringUtil.replace(
476 viewPageURLString, "__REPLACEMENT__", "$1");
477 }
478
479 matcher = _viewPageURLPattern.matcher(content);
480
481 content = _convertURLs(viewPageURLString, matcher);
482
483 content = _replaceAttachments(
484 content, page.getTitle(), attachmentURLPrefix);
485
486 return content;
487 }
488
489 private String _convertURLs(String url, Matcher matcher) {
490 StringBuffer sb = new StringBuffer();
491
492 while (matcher.find()) {
493 String replacement = null;
494
495 if (matcher.groupCount() >= 1) {
496 String encodedTitle = HttpUtil.encodeURL(
497 HtmlUtil.unescape(matcher.group(1)));
498
499 replacement = url.replace("$1", encodedTitle);
500 }
501 else {
502 replacement = url;
503 }
504
505 matcher.appendReplacement(sb, replacement);
506 }
507
508 return matcher.appendTail(sb).toString();
509 }
510
511 private String _getEditPage(String format) {
512 return PropsUtil.get(
513 PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
514 }
515
516 private WikiEngine _getEngine(String format) throws WikiFormatException {
517 WikiEngine engine = _engines.get(format);
518
519 if (engine != null) {
520 return engine;
521 }
522
523 synchronized (_engines) {
524 engine = _engines.get(format);
525
526 if (engine != null) {
527 return engine;
528 }
529
530 try {
531 String engineClass = PropsUtil.get(
532 PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
533
534 if (engineClass == null) {
535 throw new WikiFormatException(format);
536 }
537
538 if (!InstancePool.contains(engineClass)) {
539 engine = (WikiEngine)InstancePool.get(engineClass);
540
541 engine.setMainConfiguration(
542 _readConfigurationFile(
543 PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN, format));
544
545 engine.setInterWikiConfiguration(
546 _readConfigurationFile(
547 PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
548 format));
549 }
550 else {
551 engine = (WikiEngine)InstancePool.get(engineClass);
552 }
553
554 _engines.put(format, engine);
555
556 return engine;
557 }
558 catch (Exception e) {
559 throw new WikiFormatException(e);
560 }
561 }
562 }
563
564 private String _getHelpPage(String format) {
565 return PropsUtil.get(
566 PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
567 }
568
569 private String _getHelpURL(String format) {
570 return PropsUtil.get(
571 PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
572 }
573
574 private Map<String, Boolean> _getLinks(WikiPage page)
575 throws PageContentException {
576
577 try {
578 return _getEngine(page.getFormat()).getOutgoingLinks(page);
579 }
580 catch (WikiFormatException wfe) {
581 return Collections.emptyMap();
582 }
583 }
584
585 private String _readConfigurationFile(String propertyName, String format)
586 throws IOException {
587
588 ClassLoader classLoader = getClass().getClassLoader();
589
590 String configurationFile = PropsUtil.get(
591 propertyName, new Filter(format));
592
593 if (Validator.isNotNull(configurationFile)) {
594 return HttpUtil.URLtoString(
595 classLoader.getResource(configurationFile));
596 }
597 else {
598 return StringPool.BLANK;
599 }
600 }
601
602 private String _replaceAttachments(
603 String content, String title, String attachmentURLPrefix) {
604
605 content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
606
607 content = StringUtil.replace(
608 content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
609
610 return content;
611 }
612
613 private boolean _validate(long nodeId, String content, String format)
614 throws WikiFormatException {
615
616 return _getEngine(format).validate(nodeId, content);
617 }
618
619 private static WikiUtil _instance = new WikiUtil();
620
621 private static Pattern _editPageURLPattern = Pattern.compile(
622 "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)" +
623 "\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
624 private static Pattern _viewPageURLPattern = Pattern.compile(
625 "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
626
627 private Map<String, WikiEngine> _engines =
628 new ConcurrentHashMap<String, WikiEngine>();
629
630 }