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                                            existsObj = Boolean.TRUE;
085                                    }
086                                    else {
087                                            existsObj = Boolean.FALSE;
088    
089                                            // JAMWiki turns images into links. The postProcess method
090                                            // turns them back to images, but the getOutgoingLinks does
091                                            // not call postProcess, so we must manual process this
092                                            // case.
093    
094                                            if (StringUtil.startsWith(title, "image:")) {
095                                                    continue;
096                                            }
097                                    }
098    
099                                    outgoingLinks.put(title, existsObj);
100                            }
101                    }
102    
103                    return outgoingLinks;
104            }
105    
106            @Override
107            public void setInterWikiConfiguration(String interWikiConfiguration) {
108            }
109    
110            @Override
111            public void setMainConfiguration(String mainConfiguration) {
112            }
113    
114            @Override
115            public boolean validate(long nodeId, String content) {
116                    return true;
117            }
118    
119            protected ParserInput getParserInput(long nodeId, String topicName) {
120                    ParserInput parserInput = new ParserInput(
121                            "Special:Node:" + nodeId, topicName);
122    
123                    // Dummy values
124    
125                    parserInput.setContext("/wiki");
126                    parserInput.setLocale(LocaleUtil.getDefault());
127                    parserInput.setUserDisplay("0.0.0.0");
128                    parserInput.setWikiUser(new WikiUser("DummyUser"));
129    
130                    // Useful values
131    
132                    parserInput.setAllowSectionEdit(false);
133    
134                    // Table of contents
135    
136                    TableOfContents tableOfContents = new TableOfContents();
137    
138                    tableOfContents.setForceTOC(true);
139    
140                    parserInput.setTableOfContents(tableOfContents);
141    
142                    return parserInput;
143            }
144    
145            protected ParserOutput getParserOutput(WikiPage page)
146                    throws PageContentException {
147    
148                    ParserInput parserInput = getParserInput(
149                            page.getNodeId(), page.getTitle());
150    
151                    ParserOutput parserOutput = null;
152    
153                    Thread currentThread = Thread.currentThread();
154    
155                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
156    
157                    currentThread.setContextClassLoader(
158                            ClassLoaderUtil.getPortalClassLoader());
159    
160                    try {
161                            parserOutput = ParserUtil.parseMetadata(
162                                    parserInput, page.getContent());
163                    }
164                    catch (ParserException pe) {
165                            throw new PageContentException(pe);
166                    }
167                    finally {
168                            currentThread.setContextClassLoader(contextClassLoader);
169                    }
170    
171                    return parserOutput;
172            }
173    
174            protected String parsePage(
175                            WikiPage page, ParserOutput parserOutput, PortletURL viewPageURL,
176                            PortletURL editPageURL, String attachmentURLPrefix)
177                    throws PageContentException {
178    
179                    ParserInput parserInput = getParserInput(
180                            page.getNodeId(), page.getTitle());
181    
182                    String content = StringPool.BLANK;
183    
184                    Thread currentThread = Thread.currentThread();
185    
186                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
187    
188                    currentThread.setContextClassLoader(
189                            ClassLoaderUtil.getPortalClassLoader());
190    
191                    try {
192                            content = page.getContent();
193    
194                            DirectTagMatcher directTagMatcher = new DirectTagMatcher(page);
195    
196                            content = directTagMatcher.replaceMatches(content);
197    
198                            ImageTagMatcher imageTagMatcher = new ImageTagMatcher();
199    
200                            content = ParserUtil.parse(
201                                    parserInput, parserOutput,
202                                    imageTagMatcher.replaceMatches(content));
203                    }
204                    catch (ParserException pe) {
205                            throw new PageContentException(pe);
206                    }
207                    finally {
208                            currentThread.setContextClassLoader(contextClassLoader);
209                    }
210    
211                    // Post parse
212    
213                    if (attachmentURLPrefix != null) {
214                            DirectURLMatcher attachmentURLMatcher = new DirectURLMatcher(
215                                    page, attachmentURLPrefix);
216    
217                            content = attachmentURLMatcher.replaceMatches(content);
218    
219                            ImageURLMatcher imageURLMatcher = new ImageURLMatcher(
220                                    attachmentURLPrefix);
221    
222                            content = imageURLMatcher.replaceMatches(content);
223                    }
224    
225                    if (editPageURL != null) {
226                            EditURLMatcher editURLMatcher = new EditURLMatcher(editPageURL);
227    
228                            content = editURLMatcher.replaceMatches(content);
229                    }
230    
231                    if (viewPageURL != null) {
232                            ViewURLMatcher viewURLMatcher = new ViewURLMatcher(viewPageURL);
233    
234                            content = viewURLMatcher.replaceMatches(content);
235                    }
236    
237                    return content;
238            }
239    
240    }