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 = StringUtil.split(
256 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(long nodeId, String content, String format)
382 throws WikiFormatException {
383
384 return _instance._validate(nodeId, content, format);
385 }
386
387 private String _convert(
388 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
389 String attachmentURLPrefix)
390 throws PageContentException, WikiFormatException {
391
392 LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
393 LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
394
395 WikiEngine engine = _getEngine(page.getFormat());
396
397 String content = engine.convert(
398 page, viewPageURL, editPageURL, attachmentURLPrefix);
399
400 String editPageURLString = StringPool.BLANK;
401
402 if (editPageURL != null) {
403 liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
404
405 editPageURLString = editPageURL.toString();
406
407 editPageURLString = StringUtil.replace(
408 editPageURLString, "__REPLACEMENT__", "$1");
409 }
410
411 Matcher matcher = _editPageURLPattern.matcher(content);
412
413 content = _convertURLs(editPageURLString, matcher);
414
415 String viewPageURLString = StringPool.BLANK;
416
417 if (viewPageURL != null) {
418 liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
419
420 viewPageURLString = viewPageURL.toString();
421
422 viewPageURLString = StringUtil.replace(
423 viewPageURLString, "__REPLACEMENT__", "$1");
424 }
425
426 matcher = _viewPageURLPattern.matcher(content);
427
428 content = _convertURLs(viewPageURLString, matcher);
429
430 content = _replaceAttachments(
431 content, page.getTitle(), attachmentURLPrefix);
432
433 return content;
434 }
435
436 private String _convertURLs(String url, Matcher matcher) {
437 StringBuffer sb = new StringBuffer();
438
439 while (matcher.find()) {
440 String replacement = null;
441
442 if (matcher.groupCount() >= 1) {
443 String encodedTitle = HttpUtil.encodeURL(matcher.group(1));
444
445 replacement = url.replace("$1", encodedTitle);
446 }
447 else {
448 replacement = url;
449 }
450
451 matcher.appendReplacement(sb, replacement);
452 }
453
454 return matcher.appendTail(sb).toString();
455 }
456
457 private String _getEditPage(String format) {
458 return PropsUtil.get(
459 PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
460 }
461
462 private WikiEngine _getEngine(String format) throws WikiFormatException {
463 WikiEngine engine = _engines.get(format);
464
465 if (engine != null) {
466 return engine;
467 }
468
469 synchronized (_engines) {
470 engine = _engines.get(format);
471
472 if (engine != null) {
473 return engine;
474 }
475
476 try {
477 String engineClass = PropsUtil.get(
478 PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
479
480 if (engineClass == null) {
481 throw new WikiFormatException(format);
482 }
483
484 if (!InstancePool.contains(engineClass)) {
485 engine = (WikiEngine)InstancePool.get(engineClass);
486
487 engine.setMainConfiguration(
488 _readConfigurationFile(
489 PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN, format));
490
491 engine.setInterWikiConfiguration(
492 _readConfigurationFile(
493 PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
494 format));
495 }
496 else {
497 engine = (WikiEngine)InstancePool.get(engineClass);
498 }
499
500 _engines.put(format, engine);
501
502 return engine;
503 }
504 catch (Exception e) {
505 throw new WikiFormatException(e);
506 }
507 }
508 }
509
510 private String _getHelpPage(String format) {
511 return PropsUtil.get(
512 PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
513 }
514
515 private String _getHelpURL(String format) {
516 return PropsUtil.get(
517 PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
518 }
519
520 private Map<String, Boolean> _getLinks(WikiPage page)
521 throws PageContentException {
522
523 try {
524 return _getEngine(page.getFormat()).getOutgoingLinks(page);
525 }
526 catch (WikiFormatException wfe) {
527 return Collections.emptyMap();
528 }
529 }
530
531 private String _readConfigurationFile(String propertyName, String format)
532 throws IOException {
533
534 ClassLoader classLoader = getClass().getClassLoader();
535
536 String configurationFile = PropsUtil.get(
537 propertyName, new Filter(format));
538
539 if (Validator.isNotNull(configurationFile)) {
540 return HttpUtil.URLtoString(
541 classLoader.getResource(configurationFile));
542 }
543 else {
544 return StringPool.BLANK;
545 }
546 }
547
548 private String _replaceAttachments(
549 String content, String title, String attachmentURLPrefix) {
550
551 content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
552
553 content = StringUtil.replace(
554 content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
555
556 return content;
557 }
558
559 private boolean _validate(long nodeId, String content, String format)
560 throws WikiFormatException {
561
562 return _getEngine(format).validate(nodeId, content);
563 }
564
565 private static WikiUtil _instance = new WikiUtil();
566
567 private static Pattern _editPageURLPattern = Pattern.compile(
568 "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)" +
569 "\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
570 private static Pattern _viewPageURLPattern = Pattern.compile(
571 "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
572
573 private Map<String, WikiEngine> _engines =
574 new ConcurrentHashMap<String, WikiEngine>();
575
576 }