001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
024    import com.liferay.portal.kernel.search.Document;
025    import com.liferay.portal.kernel.search.Field;
026    import com.liferay.portal.kernel.search.Hits;
027    import com.liferay.portal.kernel.util.ArrayUtil;
028    import com.liferay.portal.kernel.util.DiffHtmlUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.HtmlUtil;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.InstancePool;
033    import com.liferay.portal.kernel.util.ListUtil;
034    import com.liferay.portal.kernel.util.OrderByComparator;
035    import com.liferay.portal.kernel.util.ParamUtil;
036    import com.liferay.portal.kernel.util.PropsKeys;
037    import com.liferay.portal.kernel.util.StringBundler;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.StringUtil;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.security.permission.ActionKeys;
042    import com.liferay.portal.security.permission.PermissionChecker;
043    import com.liferay.portal.theme.ThemeDisplay;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PropsUtil;
046    import com.liferay.portal.util.PropsValues;
047    import com.liferay.portal.util.WebKeys;
048    import com.liferay.portlet.PortletURLUtil;
049    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
050    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
051    import com.liferay.portlet.messageboards.model.MBMessage;
052    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
053    import com.liferay.portlet.wiki.PageContentException;
054    import com.liferay.portlet.wiki.WikiFormatException;
055    import com.liferay.portlet.wiki.engines.WikiEngine;
056    import com.liferay.portlet.wiki.model.WikiNode;
057    import com.liferay.portlet.wiki.model.WikiPage;
058    import com.liferay.portlet.wiki.model.WikiPageDisplay;
059    import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
060    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
061    import com.liferay.portlet.wiki.service.permission.WikiNodePermission;
062    import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
063    import com.liferay.portlet.wiki.util.comparator.PageTitleComparator;
064    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
065    import com.liferay.util.ContentUtil;
066    
067    import java.io.IOException;
068    
069    import java.util.ArrayList;
070    import java.util.Arrays;
071    import java.util.Collections;
072    import java.util.HashSet;
073    import java.util.Iterator;
074    import java.util.List;
075    import java.util.Map;
076    import java.util.Set;
077    import java.util.concurrent.ConcurrentHashMap;
078    import java.util.regex.Matcher;
079    import java.util.regex.Pattern;
080    
081    import javax.portlet.PortletPreferences;
082    import javax.portlet.PortletRequest;
083    import javax.portlet.PortletURL;
084    import javax.portlet.RenderRequest;
085    import javax.portlet.RenderResponse;
086    
087    /**
088     * @author Brian Wing Shun Chan
089     * @author Jorge Ferrer
090     */
091    public class WikiUtil {
092    
093            public static String convert(
094                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
095                            String attachmentURLPrefix)
096                    throws PageContentException, WikiFormatException {
097    
098                    return _instance._convert(
099                            page, viewPageURL, editPageURL, attachmentURLPrefix);
100            }
101    
102            public static String diffHtml(
103                            WikiPage sourcePage, WikiPage targetPage, PortletURL viewPageURL,
104                            PortletURL editPageURL, String attachmentURLPrefix)
105                    throws Exception {
106    
107                    String sourceContent = StringPool.BLANK;
108                    String targetContent = StringPool.BLANK;
109    
110                    if (sourcePage != null) {
111                            sourceContent = convert(
112                                    sourcePage, viewPageURL, editPageURL, attachmentURLPrefix);
113                    }
114    
115                    if (targetPage != null) {
116                            targetContent = convert(
117                                    targetPage, viewPageURL, editPageURL, attachmentURLPrefix);
118                    }
119    
120                    return DiffHtmlUtil.diff(
121                            new UnsyncStringReader(sourceContent),
122                            new UnsyncStringReader(targetContent));
123            }
124    
125            public static List<WikiPage> filterOrphans(List<WikiPage> pages)
126                    throws PortalException {
127    
128                    List<Map<String, Boolean>> pageTitles =
129                            new ArrayList<Map<String, Boolean>>();
130    
131                    for (WikiPage page : pages) {
132                            pageTitles.add(WikiCacheUtil.getOutgoingLinks(page));
133                    }
134    
135                    Set<WikiPage> notOrphans = new HashSet<WikiPage>();
136    
137                    for (WikiPage page : pages) {
138                            for (Map<String, Boolean> pageTitle : pageTitles) {
139                                    String pageTitleLowerCase = page.getTitle();
140    
141                                    pageTitleLowerCase = pageTitleLowerCase.toLowerCase();
142    
143                                    if (pageTitle.get(pageTitleLowerCase) != null) {
144                                            notOrphans.add(page);
145    
146                                            break;
147                                    }
148                            }
149                    }
150    
151                    List<WikiPage> orphans = new ArrayList<WikiPage>();
152    
153                    for (WikiPage page : pages) {
154                            if (!notOrphans.contains(page)) {
155                                    orphans.add(page);
156                            }
157                    }
158    
159                    orphans = ListUtil.sort(orphans);
160    
161                    return orphans;
162            }
163    
164            public static String getAttachmentURLPrefix(
165                    String mainPath, long plid, long nodeId, String title) {
166    
167                    StringBundler sb = new StringBundler(8);
168    
169                    sb.append(mainPath);
170                    sb.append("/wiki/get_page_attachment?p_l_id=");
171                    sb.append(plid);
172                    sb.append("&nodeId=");
173                    sb.append(nodeId);
174                    sb.append("&title=");
175                    sb.append(HttpUtil.encodeURL(title));
176                    sb.append("&fileName=");
177    
178                    return sb.toString();
179            }
180    
181            public static String getEditPage(String format) {
182                    return _instance._getEditPage(format);
183            }
184    
185            public static String getEmailFromAddress(
186                            PortletPreferences preferences, long companyId)
187                    throws SystemException {
188    
189                    return PortalUtil.getEmailFromAddress(
190                            preferences, companyId, PropsValues.WIKI_EMAIL_FROM_ADDRESS);
191            }
192    
193            public static String getEmailFromName(
194                            PortletPreferences preferences, long companyId)
195                    throws SystemException {
196    
197                    return PortalUtil.getEmailFromName(
198                            preferences, companyId, PropsValues.WIKI_EMAIL_FROM_NAME);
199            }
200    
201            public static String getEmailPageAddedBody(PortletPreferences preferences) {
202                    String emailPageAddedBody = preferences.getValue(
203                            "emailPageAddedBody", StringPool.BLANK);
204    
205                    if (Validator.isNotNull(emailPageAddedBody)) {
206                            return emailPageAddedBody;
207                    }
208                    else {
209                            return ContentUtil.get(
210                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_BODY));
211                    }
212            }
213    
214            public static boolean getEmailPageAddedEnabled(
215                    PortletPreferences preferences) {
216    
217                    String emailPageAddedEnabled = preferences.getValue(
218                            "emailPageAddedEnabled", StringPool.BLANK);
219    
220                    if (Validator.isNotNull(emailPageAddedEnabled)) {
221                            return GetterUtil.getBoolean(emailPageAddedEnabled);
222                    }
223                    else {
224                            return GetterUtil.getBoolean(
225                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_ENABLED));
226                    }
227            }
228    
229            public static String getEmailPageAddedSignature(
230                    PortletPreferences preferences) {
231    
232                    String emailPageAddedSignature = preferences.getValue(
233                            "emailPageAddedSignature", StringPool.BLANK);
234    
235                    if (Validator.isNotNull(emailPageAddedSignature)) {
236                            return emailPageAddedSignature;
237                    }
238                    else {
239                            return ContentUtil.get(
240                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_SIGNATURE));
241                    }
242            }
243    
244            public static String getEmailPageAddedSubject(
245                    PortletPreferences preferences) {
246    
247                    String emailPageAddedSubject = preferences.getValue(
248                            "emailPageAddedSubject", StringPool.BLANK);
249    
250                    if (Validator.isNotNull(emailPageAddedSubject)) {
251                            return emailPageAddedSubject;
252                    }
253                    else {
254                            return ContentUtil.get(
255                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_ADDED_SUBJECT));
256                    }
257            }
258    
259            public static String getEmailPageUpdatedBody(
260                    PortletPreferences preferences) {
261    
262                    String emailPageUpdatedBody = preferences.getValue(
263                            "emailPageUpdatedBody", StringPool.BLANK);
264    
265                    if (Validator.isNotNull(emailPageUpdatedBody)) {
266                            return emailPageUpdatedBody;
267                    }
268                    else {
269                            return ContentUtil.get(
270                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_BODY));
271                    }
272            }
273    
274            public static boolean getEmailPageUpdatedEnabled(
275                    PortletPreferences preferences) {
276    
277                    String emailPageUpdatedEnabled = preferences.getValue(
278                            "emailPageUpdatedEnabled", StringPool.BLANK);
279    
280                    if (Validator.isNotNull(emailPageUpdatedEnabled)) {
281                            return GetterUtil.getBoolean(emailPageUpdatedEnabled);
282                    }
283                    else {
284                            return GetterUtil.getBoolean(
285                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_ENABLED));
286                    }
287            }
288    
289            public static String getEmailPageUpdatedSignature(
290                    PortletPreferences preferences) {
291    
292                    String emailPageUpdatedSignature = preferences.getValue(
293                            "emailPageUpdatedSignature", StringPool.BLANK);
294    
295                    if (Validator.isNotNull(emailPageUpdatedSignature)) {
296                            return emailPageUpdatedSignature;
297                    }
298                    else {
299                            return ContentUtil.get(
300                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SIGNATURE));
301                    }
302            }
303    
304            public static String getEmailPageUpdatedSubject(
305                    PortletPreferences preferences) {
306    
307                    String emailPageUpdatedSubject = preferences.getValue(
308                            "emailPageUpdatedSubject", StringPool.BLANK);
309    
310                    if (Validator.isNotNull(emailPageUpdatedSubject)) {
311                            return emailPageUpdatedSubject;
312                    }
313                    else {
314                            return ContentUtil.get(
315                                    PropsUtil.get(PropsKeys.WIKI_EMAIL_PAGE_UPDATED_SUBJECT));
316                    }
317            }
318    
319            public static List<Object> getEntries(Hits hits) {
320                    List<Object> entries = new ArrayList<Object>();
321    
322                    for (Document document : hits.getDocs()) {
323                            String entryClassName = GetterUtil.getString(
324                                    document.get(Field.ENTRY_CLASS_NAME));
325                            long entryClassPK = GetterUtil.getLong(
326                                    document.get(Field.ENTRY_CLASS_PK));
327    
328                            try {
329                                    Object obj = null;
330    
331                                    if (entryClassName.equals(DLFileEntry.class.getName())) {
332                                            long classPK = GetterUtil.getLong(
333                                                    document.get(Field.CLASS_PK));
334    
335                                            WikiPageLocalServiceUtil.getPage(classPK);
336    
337                                            obj = DLFileEntryLocalServiceUtil.getDLFileEntry(
338                                                    entryClassPK);
339                                    }
340                                    else if (entryClassName.equals(MBMessage.class.getName())) {
341                                            long classPK = GetterUtil.getLong(
342                                                    document.get(Field.CLASS_PK));
343    
344                                            WikiPageLocalServiceUtil.getPage(classPK);
345    
346                                            obj = MBMessageLocalServiceUtil.getMessage(entryClassPK);
347                                    }
348                                    else if (entryClassName.equals(WikiPage.class.getName())) {
349                                            obj = WikiPageLocalServiceUtil.getPage(entryClassPK);
350                                    }
351    
352                                    entries.add(obj);
353                            }
354                            catch (Exception e) {
355                                    if (_log.isWarnEnabled()) {
356                                            _log.warn(
357                                                    "Wiki search index is stale and contains entry " +
358                                                            "{className=" + entryClassName + ", classPK=" +
359                                                                    entryClassPK + "}");
360                                    }
361                            }
362                    }
363    
364                    return entries;
365            }
366    
367            public static WikiNode getFirstNode(PortletRequest portletRequest)
368                    throws PortalException, SystemException {
369    
370                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
371                            WebKeys.THEME_DISPLAY);
372                    long groupId = themeDisplay.getScopeGroupId();
373                    PermissionChecker permissionChecker =
374                            themeDisplay.getPermissionChecker();
375    
376                    List<WikiNode> nodes = WikiNodeLocalServiceUtil.getNodes(groupId);
377    
378                    PortletPreferences preferences = portletRequest.getPreferences();
379                    String[] visibleNodeNames = StringUtil.split(
380                            preferences.getValue("visibleNodes", null));
381                    nodes = orderNodes(nodes, visibleNodeNames);
382    
383                    String[] hiddenNodes = StringUtil.split(
384                            preferences.getValue("hiddenNodes", StringPool.BLANK));
385                    Arrays.sort(hiddenNodes);
386    
387                    for (WikiNode node : nodes) {
388                            if ((Arrays.binarySearch(hiddenNodes, node.getName()) < 0) &&
389                                    WikiNodePermission.contains(
390                                            permissionChecker, node, ActionKeys.VIEW)) {
391    
392                                    return node;
393                            }
394                    }
395    
396                    return null;
397            }
398    
399            public static String getFormattedContent(
400                            RenderRequest renderRequest, RenderResponse renderResponse,
401                            WikiPage wikiPage, PortletURL viewPageURL, PortletURL editPageURL,
402                            String title, boolean preview)
403                    throws Exception {
404    
405                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
406                            WebKeys.THEME_DISPLAY);
407    
408                    double version = ParamUtil.getDouble(renderRequest, "version");
409    
410                    PortletURL curViewPageURL = PortletURLUtil.clone(
411                            viewPageURL, renderResponse);
412                    PortletURL curEditPageURL = PortletURLUtil.clone(
413                            editPageURL, renderResponse);
414    
415                    StringBundler sb = new StringBundler();
416    
417                    sb.append(themeDisplay.getPathMain());
418                    sb.append("/wiki/get_page_attachment?p_l_id=");
419                    sb.append(themeDisplay.getPlid());
420                    sb.append("&nodeId=");
421                    sb.append(wikiPage.getNodeId());
422                    sb.append("&title=");
423                    sb.append(HttpUtil.encodeURL(wikiPage.getTitle()));
424                    sb.append("&fileName=");
425    
426                    String attachmentURLPrefix = sb.toString();
427    
428                    if (!preview && (version == 0)) {
429                            WikiPageDisplay pageDisplay = WikiCacheUtil.getDisplay(
430                                    wikiPage.getNodeId(), title, curViewPageURL, curEditPageURL,
431                                    attachmentURLPrefix);
432    
433                            if (pageDisplay != null) {
434                                    return pageDisplay.getFormattedContent();
435                            }
436                    }
437    
438                    return convert(
439                            wikiPage, curViewPageURL, curEditPageURL, attachmentURLPrefix);
440            }
441    
442            public static String getHelpPage(String format) {
443                    return _instance._getHelpPage(format);
444            }
445    
446            public static String getHelpURL(String format) {
447                    return _instance._getHelpURL(format);
448            }
449    
450            public static Map<String, Boolean> getLinks(WikiPage page)
451                    throws PageContentException {
452    
453                    return _instance._getLinks(page);
454            }
455    
456            public static List<String> getNodeNames(List<WikiNode> nodes) {
457                    List<String> nodeNames = new ArrayList<String>(nodes.size());
458    
459                    for (WikiNode node : nodes) {
460                            nodeNames.add(node.getName());
461                    }
462    
463                    return nodeNames;
464            }
465    
466            public static List<WikiNode> getNodes(
467                    List<WikiNode> nodes, String[] hiddenNodes,
468                    PermissionChecker permissionChecker) {
469    
470                    nodes = ListUtil.copy(nodes);
471    
472                    Arrays.sort(hiddenNodes);
473    
474                    Iterator<WikiNode> itr = nodes.iterator();
475    
476                    while (itr.hasNext()) {
477                            WikiNode node = itr.next();
478    
479                            if (!(Arrays.binarySearch(hiddenNodes, node.getName()) < 0) ||
480                                    !WikiNodePermission.contains(
481                                            permissionChecker, node, ActionKeys.VIEW)) {
482    
483                                    itr.remove();
484                            }
485                    }
486    
487                    return nodes;
488            }
489    
490            public static OrderByComparator getPageOrderByComparator(
491                    String orderByCol, String orderByType) {
492    
493                    boolean orderByAsc = false;
494    
495                    if (orderByType.equals("asc")) {
496                            orderByAsc = true;
497                    }
498    
499                    OrderByComparator orderByComparator = null;
500    
501                    if (orderByCol.equals("modifiedDate")) {
502                            orderByComparator = new PageCreateDateComparator(orderByAsc);
503                    }
504                    else if (orderByCol.equals("title")) {
505                            orderByComparator = new PageTitleComparator(orderByAsc);
506                    }
507                    else if (orderByCol.equals("version")) {
508                            orderByComparator = new PageVersionComparator(orderByAsc);
509                    }
510    
511                    return orderByComparator;
512            }
513    
514            public static List<WikiNode> orderNodes(
515                    List<WikiNode> nodes, String[] visibleNodeNames) {
516    
517                    if (ArrayUtil.isEmpty(visibleNodeNames)) {
518                            return nodes;
519                    }
520    
521                    nodes = ListUtil.copy(nodes);
522    
523                    List<WikiNode> orderedNodes = new ArrayList<WikiNode>(nodes.size());
524    
525                    for (String visibleNodeName : visibleNodeNames) {
526                            for (WikiNode node : nodes) {
527                                    if (node.getName().equals(visibleNodeName)) {
528                                            orderedNodes.add(node);
529    
530                                            nodes.remove(node);
531    
532                                            break;
533                                    }
534                            }
535                    }
536    
537                    orderedNodes.addAll(nodes);
538    
539                    return orderedNodes;
540            }
541    
542            public static String processContent(String content) {
543                    content = content.replaceAll("</p>", "</p>\n");
544                    content = content.replaceAll("</br>", "</br>\n");
545                    content = content.replaceAll("</div>", "</div>\n");
546    
547                    return content;
548            }
549    
550            public static boolean validate(long nodeId, String content, String format)
551                    throws WikiFormatException {
552    
553                    return _instance._validate(nodeId, content, format);
554            }
555    
556            private String _convert(
557                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
558                            String attachmentURLPrefix)
559                    throws PageContentException, WikiFormatException {
560    
561                    LiferayPortletURL liferayViewPageURL = (LiferayPortletURL)viewPageURL;
562                    LiferayPortletURL liferayEditPageURL = (LiferayPortletURL)editPageURL;
563    
564                    WikiEngine engine = _getEngine(page.getFormat());
565    
566                    String content = engine.convert(
567                            page, viewPageURL, editPageURL, attachmentURLPrefix);
568    
569                    String editPageURLString = StringPool.BLANK;
570    
571                    if (editPageURL != null) {
572                            liferayEditPageURL.setParameter("title", "__REPLACEMENT__", false);
573    
574                            editPageURLString = editPageURL.toString();
575    
576                            editPageURLString = StringUtil.replace(
577                                    editPageURLString, "__REPLACEMENT__", "$1");
578                    }
579    
580                    Matcher matcher = _editPageURLPattern.matcher(content);
581    
582                    content = _convertURLs(editPageURLString, matcher);
583    
584                    String viewPageURLString = StringPool.BLANK;
585    
586                    if (viewPageURL != null) {
587                            liferayViewPageURL.setParameter("title", "__REPLACEMENT__", false);
588    
589                            viewPageURLString = viewPageURL.toString();
590    
591                            viewPageURLString = StringUtil.replace(
592                                    viewPageURLString, "__REPLACEMENT__", "$1");
593                    }
594    
595                    matcher = _viewPageURLPattern.matcher(content);
596    
597                    content = _convertURLs(viewPageURLString, matcher);
598    
599                    content = _replaceAttachments(
600                            content, page.getTitle(), attachmentURLPrefix);
601    
602                    return content;
603            }
604    
605            private String _convertURLs(String url, Matcher matcher) {
606                    StringBuffer sb = new StringBuffer();
607    
608                    while (matcher.find()) {
609                            String replacement = null;
610    
611                            if (matcher.groupCount() >= 1) {
612                                    String encodedTitle = HttpUtil.encodeURL(
613                                            HtmlUtil.unescape(matcher.group(1)));
614    
615                                    replacement = url.replace("$1", encodedTitle);
616                            }
617                            else {
618                                    replacement = url;
619                            }
620    
621                            matcher.appendReplacement(sb, replacement);
622                    }
623    
624                    return matcher.appendTail(sb).toString();
625            }
626    
627            private String _getEditPage(String format) {
628                    return PropsUtil.get(
629                            PropsKeys.WIKI_FORMATS_EDIT_PAGE, new Filter(format));
630            }
631    
632            private WikiEngine _getEngine(String format) throws WikiFormatException {
633                    WikiEngine engine = _engines.get(format);
634    
635                    if (engine != null) {
636                            return engine;
637                    }
638    
639                    synchronized (_engines) {
640                            engine = _engines.get(format);
641    
642                            if (engine != null) {
643                                    return engine;
644                            }
645    
646                            try {
647                                    String engineClass = PropsUtil.get(
648                                            PropsKeys.WIKI_FORMATS_ENGINE, new Filter(format));
649    
650                                    if (engineClass == null) {
651                                            throw new WikiFormatException(format);
652                                    }
653    
654                                    if (!InstancePool.contains(engineClass)) {
655                                            engine = (WikiEngine)InstancePool.get(engineClass);
656    
657                                            engine.setMainConfiguration(
658                                                    _readConfigurationFile(
659                                                            PropsKeys.WIKI_FORMATS_CONFIGURATION_MAIN, format));
660    
661                                            engine.setInterWikiConfiguration(
662                                                    _readConfigurationFile(
663                                                            PropsKeys.WIKI_FORMATS_CONFIGURATION_INTERWIKI,
664                                                            format));
665                                    }
666                                    else {
667                                            engine = (WikiEngine)InstancePool.get(engineClass);
668                                    }
669    
670                                    _engines.put(format, engine);
671    
672                                    return engine;
673                            }
674                            catch (Exception e) {
675                                    throw new WikiFormatException(e);
676                            }
677                    }
678            }
679    
680            private String _getHelpPage(String format) {
681                    return PropsUtil.get(
682                            PropsKeys.WIKI_FORMATS_HELP_PAGE, new Filter(format));
683            }
684    
685            private String _getHelpURL(String format) {
686                    return PropsUtil.get(
687                            PropsKeys.WIKI_FORMATS_HELP_URL, new Filter(format));
688            }
689    
690            private Map<String, Boolean> _getLinks(WikiPage page)
691                    throws PageContentException {
692    
693                    try {
694                            return _getEngine(page.getFormat()).getOutgoingLinks(page);
695                    }
696                    catch (WikiFormatException wfe) {
697                            return Collections.emptyMap();
698                    }
699            }
700    
701            private String _readConfigurationFile(String propertyName, String format)
702                    throws IOException {
703    
704                    ClassLoader classLoader = getClass().getClassLoader();
705    
706                    String configurationFile = PropsUtil.get(
707                            propertyName, new Filter(format));
708    
709                    if (Validator.isNotNull(configurationFile)) {
710                            return HttpUtil.URLtoString(
711                                    classLoader.getResource(configurationFile));
712                    }
713                    else {
714                            return StringPool.BLANK;
715                    }
716            }
717    
718            private String _replaceAttachments(
719                    String content, String title, String attachmentURLPrefix) {
720    
721                    content = StringUtil.replace(content, "[$WIKI_PAGE_NAME$]", title);
722    
723                    content = StringUtil.replace(
724                            content, "[$ATTACHMENT_URL_PREFIX$]", attachmentURLPrefix);
725    
726                    return content;
727            }
728    
729            private boolean _validate(long nodeId, String content, String format)
730                    throws WikiFormatException {
731    
732                    return _getEngine(format).validate(nodeId, content);
733            }
734    
735            private static Log _log = LogFactoryUtil.getLog(WikiUtil.class);
736    
737            private static WikiUtil _instance = new WikiUtil();
738    
739            private static Pattern _editPageURLPattern = Pattern.compile(
740                    "\\[\\$BEGIN_PAGE_TITLE_EDIT\\$\\](.*?)" +
741                            "\\[\\$END_PAGE_TITLE_EDIT\\$\\]");
742            private static Pattern _viewPageURLPattern = Pattern.compile(
743                    "\\[\\$BEGIN_PAGE_TITLE\\$\\](.*?)\\[\\$END_PAGE_TITLE\\$\\]");
744    
745            private Map<String, WikiEngine> _engines =
746                    new ConcurrentHashMap<String, WikiEngine>();
747    
748    }