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