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