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