1
14
15 package com.liferay.portlet.wiki.util;
16
17 import com.liferay.portal.kernel.configuration.Filter;
18 import com.liferay.portal.kernel.exception.PortalException;
19 import com.liferay.portal.kernel.exception.SystemException;
20 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
21 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
22 import com.liferay.portal.kernel.util.ArrayUtil;
23 import com.liferay.portal.kernel.util.DiffHtmlUtil;
24 import com.liferay.portal.kernel.util.GetterUtil;
25 import com.liferay.portal.kernel.util.HttpUtil;
26 import com.liferay.portal.kernel.util.InstancePool;
27 import com.liferay.portal.kernel.util.ListUtil;
28 import com.liferay.portal.kernel.util.PropsKeys;
29 import com.liferay.portal.kernel.util.StringBundler;
30 import com.liferay.portal.kernel.util.StringPool;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Validator;
33 import com.liferay.portal.security.permission.ActionKeys;
34 import com.liferay.portal.security.permission.PermissionChecker;
35 import com.liferay.portal.theme.ThemeDisplay;
36 import com.liferay.portal.util.ContentUtil;
37 import com.liferay.portal.util.PropsUtil;
38 import com.liferay.portal.util.PropsValues;
39 import com.liferay.portal.util.WebKeys;
40 import com.liferay.portlet.wiki.PageContentException;
41 import com.liferay.portlet.wiki.WikiFormatException;
42 import com.liferay.portlet.wiki.engines.WikiEngine;
43 import com.liferay.portlet.wiki.model.WikiNode;
44 import com.liferay.portlet.wiki.model.WikiPage;
45 import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
46 import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
47
48 import java.io.IOException;
49
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.regex.Matcher;
57 import java.util.regex.Pattern;
58
59 import javax.portlet.PortletPreferences;
60 import javax.portlet.PortletURL;
61 import javax.portlet.RenderRequest;
62
63
69 public class WikiUtil {
70
71 public static final String POP_PORTLET_PREFIX = "wiki.";
72
73 public static String convert(
74 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
75 String attachmentURLPrefix)
76 throws PageContentException, WikiFormatException {
77
78 return _instance._convert(
79 page, viewPageURL, editPageURL, attachmentURLPrefix);
80 }
81
82 public static String diffHtml (
83 WikiPage sourcePage, WikiPage targetPage, PortletURL viewPageURL,
84 PortletURL editPageURL, String attachmentURLPrefix)
85 throws Exception {
86
87 String sourceContent = StringPool.BLANK;
88 String targetContent = StringPool.BLANK;
89
90 if (sourcePage != null) {
91 sourceContent = WikiUtil.convert(
92 sourcePage, viewPageURL, editPageURL,attachmentURLPrefix);
93 }
94
95 if (targetPage != null) {
96 targetContent = WikiUtil.convert(
97 targetPage, viewPageURL, editPageURL, attachmentURLPrefix);
98 }
99
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(PortletPreferences preferences) {
110 String emailFromAddress = PropsUtil.get(
111 PropsKeys.WIKI_EMAIL_FROM_ADDRESS);
112
113 return preferences.getValue("email-from-address", emailFromAddress);
114 }
115
116 public static String getEmailFromName(PortletPreferences preferences) {
117 String emailFromName = PropsUtil.get(PropsKeys.WIKI_EMAIL_FROM_NAME);
118
119 return preferences.getValue("email-from-name", emailFromName);
120 }
121
122 public static boolean getEmailPageAddedEnabled(
123 PortletPreferences preferences) {
124
125 String emailPageAddedEnabled = preferences.getValue(
126 "email-page-added-enabled", StringPool.BLANK);
127
128 if (Validator.isNotNull(emailPageAddedEnabled)) {
129 return GetterUtil.getBoolean(emailPageAddedEnabled);
130 }
131 else {
132 return GetterUtil.getBoolean(PropsUtil.get(
133 PropsKeys.WIKI_EMAIL_PAGE_ADDED_ENABLED));
134 }
135 }
136
137 public static String getEmailPageAddedBody(PortletPreferences preferences) {
138 String emailPageAddedBody = preferences.getValue(
139 "email-page-added-body", StringPool.BLANK);
140
141 if (Validator.isNotNull(emailPageAddedBody)) {
142 return emailPageAddedBody;
143 }
144 else {
145 return ContentUtil.get(PropsUtil.get(
146 PropsKeys.WIKI_EMAIL_PAGE_ADDED_BODY));
147 }
148 }
149
150 public static String getEmailPageAddedSignature(
151 PortletPreferences preferences) {
152
153 String emailPageAddedSignature = preferences.getValue(
154 "email-page-added-signature", StringPool.BLANK);
155
156 if (Validator.isNotNull(emailPageAddedSignature)) {
157 return emailPageAddedSignature;
158 }
159 else {
160 return ContentUtil.get(PropsUtil.get(
161 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
162 }
163 }
164
165 public static String getEmailPageAddedSubjectPrefix(
166 PortletPreferences preferences) {
167
168 String emailPageAddedSubjectPrefix = preferences.getValue(
169 "email-page-added-subject-prefix", StringPool.BLANK);
170
171 if (Validator.isNotNull(emailPageAddedSubjectPrefix)) {
172 return emailPageAddedSubjectPrefix;
173 }
174 else {
175 return ContentUtil.get(PropsUtil.get(
176 PropsKeys.WIKI_EMAIL_PAGE_ADDED_SUBJECT_PREFIX));
177 }
178 }
179
180 public static boolean getEmailPageUpdatedEnabled(
181 PortletPreferences preferences) {
182
183 String emailPageUpdatedEnabled = preferences.getValue(
184 "email-page-updated-enabled", StringPool.BLANK);
185
186 if (Validator.isNotNull(emailPageUpdatedEnabled)) {
187 return GetterUtil.getBoolean(emailPageUpdatedEnabled);
188 }
189 else {
190 return GetterUtil.getBoolean(PropsUtil.get(
191 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
192 }
193 }
194
195 public static String getEmailPageUpdatedBody(
196 PortletPreferences preferences) {
197
198 String emailPageUpdatedBody = preferences.getValue(
199 "email-page-updated-body", StringPool.BLANK);
200
201 if (Validator.isNotNull(emailPageUpdatedBody)) {
202 return emailPageUpdatedBody;
203 }
204 else {
205 return ContentUtil.get(PropsUtil.get(
206 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_BODY));
207 }
208 }
209
210 public static String getEmailPageUpdatedSignature(
211 PortletPreferences preferences) {
212
213 String emailPageUpdatedSignature = preferences.getValue(
214 "email-page-updated-signature", StringPool.BLANK);
215
216 if (Validator.isNotNull(emailPageUpdatedSignature)) {
217 return emailPageUpdatedSignature;
218 }
219 else {
220 return ContentUtil.get(PropsUtil.get(
221 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
222 }
223 }
224
225 public static String getEmailPageUpdatedSubjectPrefix(
226 PortletPreferences preferences) {
227
228 String emailPageUpdatedSubject = preferences.getValue(
229 "email-page-updated-subject-prefix", StringPool.BLANK);
230
231 if (Validator.isNotNull(emailPageUpdatedSubject)) {
232 return emailPageUpdatedSubject;
233 }
234 else {
235 return ContentUtil.get(PropsUtil.get(
236 PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SUBJECT_PREFIX));
237 }
238 }
239
240 public static String getHelpPage(String format) {
241 return _instance._getHelpPage(format);
242 }
243
244 public static String getHelpURL(String format) {
245 return _instance._getHelpURL(format);
246 }
247
248 public static Map<String, Boolean> getLinks(WikiPage page)
249 throws PageContentException {
250
251 return _instance._getLinks(page);
252 }
253
254 public static String getMailId(String mx, long nodeId, long pageId) {
255 StringBundler sb = new StringBundler(10);
256
257 sb.append(StringPool.LESS_THAN);
258 sb.append(POP_PORTLET_PREFIX);
259 sb.append(nodeId);
260 sb.append(StringPool.PERIOD);
261 sb.append(pageId);
262 sb.append(StringPool.AT);
263 sb.append(PropsValues.POP_SERVER_SUBDOMAIN);
264 sb.append(StringPool.PERIOD);
265 sb.append(mx);
266 sb.append(StringPool.GREATER_THAN);
267
268 return sb.toString();
269 }
270
271 public static List<WikiNode> getNodes(RenderRequest renderRequest)
272 throws PortalException, SystemException {
273
274 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
275 WebKeys.THEME_DISPLAY);
276
277 long groupId = themeDisplay.getScopeGroupId();
278
279 String allNodes = ListUtil.toString(
280 WikiNodeLocalServiceUtil.getNodes(groupId), "name");
281
282 String[] visibleNodes = StringUtil.split(
283 renderRequest.getPreferences().getValue("visible-nodes", allNodes));
284 String[] hiddenNodes = StringUtil.split(
285 renderRequest.getPreferences().getValue(
286 "hidden-nodes", StringPool.BLANK));
287
288 return getNodes(
289 groupId, visibleNodes, hiddenNodes,
290 themeDisplay.getPermissionChecker());
291 }
292
293 public static List<WikiNode> getNodes(
294 long groupId, String[] visibleNodes, String[] hiddenNodes,
295 PermissionChecker permissionChecker)
296 throws PortalException, SystemException {
297
298 List<WikiNode> nodes = WikiNodeLocalServiceUtil.getNodes(groupId);
299
300 nodes = ListUtil.copy(nodes);
301 nodes = _orderNodes(nodes, visibleNodes);
302
303 Iterator<WikiNode> itr = nodes.iterator();
304
305 while (itr.hasNext()) {
306 WikiNode node = itr.next();
307
308 if (ArrayUtil.contains(hiddenNodes, node.getName()) ||
309 !WikiNodePermission.contains(
310 permissionChecker, node.getNodeId(), ActionKeys.VIEW)) {
311
312 itr.remove();
313 }
314 }
315
316 return nodes;
317 }
318
319 public static String processContent(String content) {
320 content = content.replaceAll("</p>", "</p>\n");
321 content = content.replaceAll("</br>", "</br>\n");
322 content = content.replaceAll("</div>", "</div>\n");
323
324 return content;
325 }
326
327 public static boolean validate(
328 long nodeId, String content, String format)
329 throws WikiFormatException {
330
331 return _instance._validate(nodeId, content, format);
332 }
333
334 private static List<WikiNode> _orderNodes(
335 List<WikiNode> nodes, String[] nodeNames) {
336
337 List<WikiNode> orderedNodes = new ArrayList<WikiNode>();
338
339 for (String nodeName : nodeNames) {
340 for (WikiNode node : nodes) {
341 if (node.getName().equals(nodeName)) {
342 orderedNodes.add(node);
343
344 nodes.remove(node);
345
346 break;
347 }
348 }
349 }
350
351 orderedNodes.addAll(nodes);
352
353 return orderedNodes;
354 }
355
356 private String _convert(
357 WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
358 String attachmentURLPrefix)
359 throws PageContentException, WikiFormatException {
360
361 LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
362 LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
363
364 WikiEngine engine = _getEngine(page.getFormat());
365
366 String content = engine.convert(page, editPageURL);
367
368 String editPageURLString = StringPool.BLANK;
369
370 if (editPageURL != null) {
371 liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
372
373 editPageURLString = editPageURL.toString();
374
375 editPageURLString = StringUtil.replace(
376 editPageURLString, "__REPLACEMENT__", "$1");
377 }
378
379 Matcher matcher = _editPageURLPattern.matcher(content);
380
381 content = matcher.replaceAll(editPageURLString);
382
383 String viewPageURLString = StringPool.BLANK;
384
385 if (viewPageURL != null) {
386 liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
387
388 viewPageURLString = viewPageURL.toString();
389
390 viewPageURLString = StringUtil.replace(
391 viewPageURLString, "__REPLACEMENT__", "$1");
392 }
393
394 matcher = _viewPageURLPattern.matcher(content);
395
396 content = matcher.replaceAll(viewPageURLString);
397
398 content = _replaceAttachments(
399 content, page.getTitle(), attachmentURLPrefix);
400
401 return content;
402 }
403
404 private String _getEditPage(String format) {
405 return PropsUtil.get(
406 PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
407 }
408
409 private WikiEngine _getEngine(String format) throws WikiFormatException {
410 WikiEngine engine = _engines.get(format);
411
412 if (engine == null) {
413 try {
414 String engineClass = PropsUtil.get(
415 PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
416
417 if (engineClass != null) {
418 if (!InstancePool.contains(engineClass)) {
419 engine = (WikiEngine)InstancePool.get(engineClass);
420
421 engine.setMainConfiguration(
422 _readConfigurationFile(
423 PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN,
424 format));
425
426 engine.setInterWikiConfiguration(
427 _readConfigurationFile(
428 PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
429 format));
430 }
431 else {
432 engine = (WikiEngine)InstancePool.get(engineClass);
433 }
434
435 _engines.put(format, engine);
436 }
437 }
438 catch (Exception e) {
439 throw new WikiFormatException(e);
440 }
441
442 if (engine == null) {
443 throw new WikiFormatException(format);
444 }
445 }
446
447 return engine;
448 }
449
450 private String _getHelpPage(String format) {
451 return PropsUtil.get(
452 PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
453 }
454
455 private String _getHelpURL(String format) {
456 return PropsUtil.get(
457 PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
458 }
459
460 private Map<String, Boolean> _getLinks(WikiPage page)
461 throws PageContentException {
462
463 try {
464 return _getEngine(page.getFormat()).getOutgoingLinks(page);
465 }
466 catch (WikiFormatException wfe) {
467 return Collections.EMPTY_MAP;
468 }
469 }
470
471 private String _readConfigurationFile(String propertyName, String format)
472 throws IOException {
473
474 ClassLoader classLoader = getClass().getClassLoader();
475
476 String configurationFile = PropsUtil.get(
477 propertyName, new Filter(format));
478
479 if (Validator.isNotNull(configurationFile)) {
480 return HttpUtil.URLtoString(
481 classLoader.getResource(configurationFile));
482 }
483 else {
484 return StringPool.BLANK;
485 }
486 }
487
488 private String _replaceAttachments(
489 String content, String title, String attachmentURLPrefix) {
490
491 content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
492
493 content = StringUtil.replace(
494 content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
495
496 return content;
497 }
498
499 private boolean _validate(long nodeId, String content, String format)
500 throws WikiFormatException {
501
502 return _getEngine(format).validate(nodeId, content);
503 }
504
505 private static WikiUtil _instance = new WikiUtil();
506
507 private static Pattern _editPageURLPattern = Pattern.compile(
508 "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
509 private static Pattern _viewPageURLPattern = Pattern.compile(
510 "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
511
512 private Map<String, WikiEngine> _engines =
513 new HashMap<String, WikiEngine>();
514
515 }