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