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.engines.mediawiki;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.util.LocaleUtil;
019    import com.liferay.portal.kernel.util.StringPool;
020    import com.liferay.portal.kernel.util.StringUtil;
021    import com.liferay.portal.util.ClassLoaderUtil;
022    import com.liferay.portlet.wiki.PageContentException;
023    import com.liferay.portlet.wiki.engines.WikiEngine;
024    import com.liferay.portlet.wiki.engines.mediawiki.matchers.DirectTagMatcher;
025    import com.liferay.portlet.wiki.engines.mediawiki.matchers.DirectURLMatcher;
026    import com.liferay.portlet.wiki.engines.mediawiki.matchers.EditURLMatcher;
027    import com.liferay.portlet.wiki.engines.mediawiki.matchers.ImageTagMatcher;
028    import com.liferay.portlet.wiki.engines.mediawiki.matchers.ImageURLMatcher;
029    import com.liferay.portlet.wiki.engines.mediawiki.matchers.ViewURLMatcher;
030    import com.liferay.portlet.wiki.model.WikiPage;
031    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
032    
033    import java.util.HashMap;
034    import java.util.Map;
035    
036    import javax.portlet.PortletURL;
037    
038    import org.jamwiki.model.WikiUser;
039    import org.jamwiki.parser.ParserException;
040    import org.jamwiki.parser.ParserInput;
041    import org.jamwiki.parser.ParserOutput;
042    import org.jamwiki.parser.ParserUtil;
043    import org.jamwiki.parser.TableOfContents;
044    
045    /**
046     * @author Jonathan Potter
047     */
048    public class MediaWikiEngine implements WikiEngine {
049    
050            @Override
051            public String convert(
052                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
053                            String attachmentURLPrefix)
054                    throws PageContentException {
055    
056                    return parsePage(
057                            page, new ParserOutput(), viewPageURL, editPageURL,
058                            attachmentURLPrefix);
059            }
060    
061            @Override
062            public Map<String, Boolean> getOutgoingLinks(WikiPage page)
063                    throws PageContentException {
064    
065                    ParserOutput parserOutput = getParserOutput(page);
066    
067                    Map<String, Boolean> outgoingLinks = new HashMap<String, Boolean>();
068    
069                    for (String title : parserOutput.getLinks()) {
070                            Boolean existsObj = outgoingLinks.get(title);
071    
072                            if (existsObj == null) {
073                                    int pagesCount = 0;
074    
075                                    try {
076                                            pagesCount = WikiPageLocalServiceUtil.getPagesCount(
077                                                    page.getNodeId(), title, true);
078                                    }
079                                    catch (SystemException se) {
080                                            throw new PageContentException(se);
081                                    }
082    
083                                    if (pagesCount > 0) {
084                                            title = StringUtil.toLowerCase(title);
085    
086                                            existsObj = Boolean.TRUE;
087                                    }
088                                    else {
089                                            existsObj = Boolean.FALSE;
090    
091                                            // JAMWiki turns images into links. The postProcess method
092                                            // turns them back to images, but the getOutgoingLinks does
093                                            // not call postProcess, so we must manual process this
094                                            // case.
095    
096                                            if (StringUtil.startsWith(title, "image:")) {
097                                                    continue;
098                                            }
099                                    }
100    
101                                    outgoingLinks.put(title, existsObj);
102                            }
103                    }
104    
105                    return outgoingLinks;
106            }
107    
108            @Override
109            public void setInterWikiConfiguration(String interWikiConfiguration) {
110            }
111    
112            @Override
113            public void setMainConfiguration(String mainConfiguration) {
114            }
115    
116            @Override
117            public boolean validate(long nodeId, String content) {
118                    return true;
119            }
120    
121            protected ParserInput getParserInput(long nodeId, String topicName) {
122                    ParserInput parserInput = new ParserInput(
123                            "Special:Node:" + nodeId, topicName);
124    
125                    // Dummy values
126    
127                    parserInput.setContext("/wiki");
128                    parserInput.setLocale(LocaleUtil.getDefault());
129                    parserInput.setUserDisplay("0.0.0.0");
130                    parserInput.setWikiUser(new WikiUser("DummyUser"));
131    
132                    // Useful values
133    
134                    parserInput.setAllowSectionEdit(false);
135    
136                    // Table of contents
137    
138                    TableOfContents tableOfContents = new TableOfContents();
139    
140                    tableOfContents.setForceTOC(true);
141    
142                    parserInput.setTableOfContents(tableOfContents);
143    
144                    return parserInput;
145            }
146    
147            protected ParserOutput getParserOutput(WikiPage page)
148                    throws PageContentException {
149    
150                    ParserInput parserInput = getParserInput(
151                            page.getNodeId(), page.getTitle());
152    
153                    ParserOutput parserOutput = null;
154    
155                    Thread currentThread = Thread.currentThread();
156    
157                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
158    
159                    currentThread.setContextClassLoader(
160                            ClassLoaderUtil.getPortalClassLoader());
161    
162                    try {
163                            parserOutput = ParserUtil.parseMetadata(
164                                    parserInput, page.getContent());
165                    }
166                    catch (ParserException pe) {
167                            throw new PageContentException(pe);
168                    }
169                    finally {
170                            currentThread.setContextClassLoader(contextClassLoader);
171                    }
172    
173                    return parserOutput;
174            }
175    
176            protected String parsePage(
177                            WikiPage page, ParserOutput parserOutput, PortletURL viewPageURL,
178                            PortletURL editPageURL, String attachmentURLPrefix)
179                    throws PageContentException {
180    
181                    ParserInput parserInput = getParserInput(
182                            page.getNodeId(), page.getTitle());
183    
184                    String content = StringPool.BLANK;
185    
186                    Thread currentThread = Thread.currentThread();
187    
188                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
189    
190                    currentThread.setContextClassLoader(
191                            ClassLoaderUtil.getPortalClassLoader());
192    
193                    try {
194                            content = page.getContent();
195    
196                            DirectTagMatcher directTagMatcher = new DirectTagMatcher(page);
197    
198                            content = directTagMatcher.replaceMatches(content);
199    
200                            ImageTagMatcher imageTagMatcher = new ImageTagMatcher();
201    
202                            content = ParserUtil.parse(
203                                    parserInput, parserOutput,
204                                    imageTagMatcher.replaceMatches(content));
205                    }
206                    catch (ParserException pe) {
207                            throw new PageContentException(pe);
208                    }
209                    finally {
210                            currentThread.setContextClassLoader(contextClassLoader);
211                    }
212    
213                    // Post parse
214    
215                    if (attachmentURLPrefix != null) {
216                            DirectURLMatcher attachmentURLMatcher = new DirectURLMatcher(
217                                    page, attachmentURLPrefix);
218    
219                            content = attachmentURLMatcher.replaceMatches(content);
220    
221                            ImageURLMatcher imageURLMatcher = new ImageURLMatcher(
222                                    attachmentURLPrefix);
223    
224                            content = imageURLMatcher.replaceMatches(content);
225                    }
226    
227                    if (editPageURL != null) {
228                            EditURLMatcher editURLMatcher = new EditURLMatcher(editPageURL);
229    
230                            content = editURLMatcher.replaceMatches(content);
231                    }
232    
233                    if (viewPageURL != null) {
234                            ViewURLMatcher viewURLMatcher = new ViewURLMatcher(viewPageURL);
235    
236                            content = viewURLMatcher.replaceMatches(content);
237                    }
238    
239                    return content;
240            }
241    
242    }