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