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