1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.wiki.util;
24  
25  import com.germinus.easyconf.Filter;
26  
27  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
28  import com.liferay.portal.kernel.util.GetterUtil;
29  import com.liferay.portal.kernel.util.HttpUtil;
30  import com.liferay.portal.kernel.util.InstancePool;
31  import com.liferay.portal.kernel.util.StringMaker;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.util.ContentUtil;
36  import com.liferay.portal.util.PropsUtil;
37  import com.liferay.portal.util.PropsValues;
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.WikiPage;
42  
43  import java.io.IOException;
44  
45  import java.util.Collections;
46  import java.util.HashMap;
47  import java.util.Map;
48  import java.util.regex.Matcher;
49  import java.util.regex.Pattern;
50  
51  import javax.portlet.PortletPreferences;
52  import javax.portlet.PortletURL;
53  
54  /**
55   * <a href="WikiUtil.java.html"><b><i>View Source</i></b></a>
56   *
57   * @author Brian Wing Shun Chan
58   * @author Jorge Ferrer
59   *
60   */
61  public class WikiUtil {
62  
63      public static final String POP_PORTLET_PREFIX = "wiki.";
64  
65      public static String convert(
66              WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
67              String attachmentURLPrefix)
68          throws PageContentException, WikiFormatException {
69  
70          return _instance._convert(
71              page, viewPageURL, editPageURL, attachmentURLPrefix);
72      }
73  
74      public static String getEditPage(String format) {
75          return _instance._getEditPage(format);
76      }
77  
78      public static String getEmailFromAddress(PortletPreferences prefs) {
79          String emailFromAddress = PropsUtil.get(
80              PropsUtil.WIKI_EMAIL_FROM_ADDRESS);
81  
82          return prefs.getValue("email-from-address", emailFromAddress);
83      }
84  
85      public static String getEmailFromName(PortletPreferences prefs) {
86          String emailFromName = PropsUtil.get(PropsUtil.WIKI_EMAIL_FROM_NAME);
87  
88          return prefs.getValue("email-from-name", emailFromName);
89      }
90  
91      public static boolean getEmailPageAddedEnabled(
92          PortletPreferences prefs) {
93  
94          String emailPageAddedEnabled = prefs.getValue(
95              "email-page-added-enabled", StringPool.BLANK);
96  
97          if (Validator.isNotNull(emailPageAddedEnabled)) {
98              return GetterUtil.getBoolean(emailPageAddedEnabled);
99          }
100         else {
101             return GetterUtil.getBoolean(PropsUtil.get(
102                 PropsUtil.WIKI_EMAIL_PAGE_ADDED_ENABLED));
103         }
104     }
105 
106     public static String getEmailPageAddedBody(PortletPreferences prefs)
107         throws IOException {
108 
109         String emailPageAddedBody = prefs.getValue(
110             "email-page-added-body", StringPool.BLANK);
111 
112         if (Validator.isNotNull(emailPageAddedBody)) {
113             return emailPageAddedBody;
114         }
115         else {
116             return ContentUtil.get(PropsUtil.get(
117                 PropsUtil.WIKI_EMAIL_PAGE_ADDED_BODY));
118         }
119     }
120 
121     public static String getEmailPageAddedSignature(PortletPreferences prefs)
122         throws IOException {
123 
124         String emailPageAddedSignature = prefs.getValue(
125             "email-page-added-signature", StringPool.BLANK);
126 
127         if (Validator.isNotNull(emailPageAddedSignature)) {
128             return emailPageAddedSignature;
129         }
130         else {
131             return ContentUtil.get(PropsUtil.get(
132                 PropsUtil.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
133         }
134     }
135 
136     public static String getEmailPageAddedSubjectPrefix(
137             PortletPreferences prefs)
138         throws IOException {
139 
140         String emailPageAddedSubjectPrefix = prefs.getValue(
141             "email-page-added-subject-prefix", StringPool.BLANK);
142 
143         if (Validator.isNotNull(emailPageAddedSubjectPrefix)) {
144             return emailPageAddedSubjectPrefix;
145         }
146         else {
147             return ContentUtil.get(PropsUtil.get(
148                 PropsUtil.WIKI_EMAIL_PAGE_ADDED_SUBJECT_PREFIX));
149         }
150     }
151 
152     public static boolean getEmailPageUpdatedEnabled(
153         PortletPreferences prefs) {
154 
155         String emailPageUpdatedEnabled = prefs.getValue(
156             "email-page-updated-enabled", StringPool.BLANK);
157 
158         if (Validator.isNotNull(emailPageUpdatedEnabled)) {
159             return GetterUtil.getBoolean(emailPageUpdatedEnabled);
160         }
161         else {
162             return GetterUtil.getBoolean(PropsUtil.get(
163                 PropsUtil.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
164         }
165     }
166 
167     public static String getEmailPageUpdatedBody(PortletPreferences prefs)
168         throws IOException {
169 
170         String emailPageUpdatedBody = prefs.getValue(
171             "email-page-updated-body", StringPool.BLANK);
172 
173         if (Validator.isNotNull(emailPageUpdatedBody)) {
174             return emailPageUpdatedBody;
175         }
176         else {
177             return ContentUtil.get(PropsUtil.get(
178                 PropsUtil.WIKI_EMAIL_PAGE_UPDATED_BODY));
179         }
180     }
181 
182     public static String getEmailPageUpdatedSignature(
183             PortletPreferences prefs)
184         throws IOException {
185 
186         String emailPageUpdatedSignature = prefs.getValue(
187             "email-page-updated-signature", StringPool.BLANK);
188 
189         if (Validator.isNotNull(emailPageUpdatedSignature)) {
190             return emailPageUpdatedSignature;
191         }
192         else {
193             return ContentUtil.get(PropsUtil.get(
194                 PropsUtil.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
195         }
196     }
197 
198     public static String getEmailPageUpdatedSubjectPrefix(
199             PortletPreferences prefs)
200         throws IOException {
201 
202         String emailPageUpdatedSubject = prefs.getValue(
203             "email-page-updated-subject-prefix", StringPool.BLANK);
204 
205         if (Validator.isNotNull(emailPageUpdatedSubject)) {
206             return emailPageUpdatedSubject;
207         }
208         else {
209             return ContentUtil.get(PropsUtil.get(
210                 PropsUtil.WIKI_EMAIL_PAGE_UPDATED_SUBJECT_PREFIX));
211         }
212     }
213 
214     public static String getHelpPage(String format) {
215         return _instance._getHelpPage(format);
216     }
217 
218     public static String getHelpURL(String format) {
219         return _instance._getHelpURL(format);
220     }
221 
222     public static Map<String, Boolean> getLinks(WikiPage page)
223         throws PageContentException, WikiFormatException {
224 
225         return _instance._getLinks(page);
226     }
227 
228     public static boolean isLinkedTo(WikiPage page, String title)
229         throws PageContentException, WikiFormatException {
230 
231         return _instance._isLinkedTo(page, title);
232     }
233 
234     public static String getMailId(String mx, long nodeId, long pageId) {
235         StringMaker sm = new StringMaker();
236 
237         sm.append(StringPool.LESS_THAN);
238         sm.append(POP_PORTLET_PREFIX);
239         sm.append(nodeId);
240         sm.append(StringPool.PERIOD);
241         sm.append(pageId);
242         sm.append(StringPool.AT);
243         sm.append(PropsValues.POP_SERVER_SUBDOMAIN);
244         sm.append(StringPool.PERIOD);
245         sm.append(mx);
246         sm.append(StringPool.GREATER_THAN);
247 
248         return sm.toString();
249     }
250 
251     public static String processContent(String content) {
252         content = content.replaceAll("</p>", "</p>\n");
253         content = content.replaceAll("</br>", "</br>\n");
254         content = content.replaceAll("</div>", "</div>\n");
255 
256         return content;
257     }
258 
259     public static boolean validate(
260             long nodeId, String content, String format)
261         throws WikiFormatException {
262 
263         return _instance._validate(nodeId, content, format);
264     }
265 
266     private String _convert(
267             WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
268             String attachmentURLPrefix)
269         throws PageContentException, WikiFormatException {
270 
271         LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
272         LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
273 
274         WikiEngine engine = _getEngine(page.getFormat());
275 
276         String content = engine.convert(page, editPageURL);
277 
278         liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
279 
280         String editPageURLString = editPageURL.toString();
281 
282         editPageURLString = StringUtil.replace(
283             editPageURLString, "__REPLACEMENT__", "$1");
284 
285         Matcher matcher = _EDIT_PAGE_URL_PATTERN.matcher(content);
286 
287         content = matcher.replaceAll(editPageURLString);
288 
289         liferayViewPageURL.setParameter("title", "$1", false);
290 
291         matcher = _VIEW_PAGE_URL_PATTERN.matcher(content);
292 
293         content = matcher.replaceAll(liferayViewPageURL.toString());
294 
295         content = _replaceAttachments(
296             content, page.getTitle(), attachmentURLPrefix);
297 
298         return content;
299     }
300 
301     private String _getEditPage(String format) {
302         return PropsUtil.getComponentProperties().getString(
303             PropsUtil.WIKI_FORMATS_EDIT_PAGE, Filter.by(format));
304     }
305 
306     private WikiEngine _getEngine(String format) throws WikiFormatException {
307         WikiEngine engine = _engines.get(format);
308 
309         if (engine == null) {
310             try {
311                 String engineClass =
312                     PropsUtil.getComponentProperties().getString(
313                         PropsUtil.WIKI_FORMATS_ENGINE, Filter.by(format));
314 
315                 if (engineClass != null) {
316                     if (!InstancePool.contains(engineClass)) {
317                         engine = (WikiEngine)InstancePool.get(engineClass);
318 
319                         engine.setMainConfiguration(
320                             _readConfigurationFile(
321                                 PropsUtil.WIKI_FORMATS_CONFIGURATION_MAIN,
322                                 format));
323 
324                         engine.setInterWikiConfiguration(
325                             _readConfigurationFile(
326                                 PropsUtil.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
327                                 format));
328                     }
329                     else {
330                         engine = (WikiEngine)InstancePool.get(engineClass);
331                     }
332 
333                     _engines.put(format, engine);
334                 }
335             }
336             catch (Exception e) {
337                 throw new WikiFormatException(e);
338             }
339 
340             if (engine == null) {
341                 throw new WikiFormatException(format);
342             }
343         }
344 
345         return engine;
346     }
347 
348     private String _getHelpPage(String format) {
349         return PropsUtil.getComponentProperties().getString(
350             PropsUtil.WIKI_FORMATS_HELP_PAGE, Filter.by(format));
351     }
352 
353     private String _getHelpURL(String format) {
354         return PropsUtil.getComponentProperties().getString(
355             PropsUtil.WIKI_FORMATS_HELP_URL, Filter.by(format));
356     }
357 
358     private Map<String, Boolean> _getLinks(WikiPage page)
359         throws PageContentException, WikiFormatException{
360 
361         try {
362             return _getEngine(page.getFormat()).getOutgoingLinks(page);
363         }
364         catch (WikiFormatException wfe) {
365             return Collections.EMPTY_MAP;
366         }
367     }
368 
369     private boolean _isLinkedTo(WikiPage page, String targetTitle)
370         throws PageContentException, WikiFormatException {
371 
372         try {
373             return _getEngine(page.getFormat()).isLinkedTo(page, targetTitle);
374         }
375         catch (WikiFormatException wfe) {
376             return false;
377         }
378     }
379 
380     private String _readConfigurationFile(String propertyName, String format)
381         throws IOException {
382 
383         ClassLoader classLoader = getClass().getClassLoader();
384 
385         String configurationFile = PropsUtil.getComponentProperties().getString(
386             propertyName, Filter.by(format));
387 
388         if (Validator.isNotNull(configurationFile)) {
389             return HttpUtil.URLtoString(
390                 classLoader.getResource(configurationFile));
391         }
392         else {
393             return StringPool.BLANK;
394         }
395     }
396 
397     private String _replaceAttachments(
398         String content, String title, String attachmentURLPrefix) {
399 
400         content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
401 
402         content = StringUtil.replace(
403             content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
404 
405         return content;
406     }
407 
408     private boolean _validate(long nodeId, String content, String format)
409         throws WikiFormatException {
410 
411         return _getEngine(format).validate(nodeId, content);
412     }
413 
414     private static final Pattern _EDIT_PAGE_URL_PATTERN = Pattern.compile(
415         "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
416 
417     private static final Pattern _VIEW_PAGE_URL_PATTERN = Pattern.compile(
418         "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
419 
420     private static WikiUtil _instance = new WikiUtil();
421 
422     private Map<String, WikiEngine> _engines =
423         new HashMap<String, WikiEngine>();
424 
425 }