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