001
014
015 package com.liferay.portlet.wiki.engines.jspwiki;
016
017 import com.ecyrd.jspwiki.WikiContext;
018 import com.ecyrd.jspwiki.WikiException;
019 import com.ecyrd.jspwiki.WikiPage;
020
021 import com.liferay.portal.kernel.exception.SystemException;
022 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
023 import com.liferay.portal.kernel.log.Log;
024 import com.liferay.portal.kernel.log.LogFactoryUtil;
025 import com.liferay.portal.kernel.util.CharPool;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portlet.wiki.PageContentException;
031 import com.liferay.portlet.wiki.engines.WikiEngine;
032 import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
033
034 import java.io.IOException;
035 import java.io.InputStream;
036
037 import java.util.Collection;
038 import java.util.Collections;
039 import java.util.HashMap;
040 import java.util.Map;
041 import java.util.Properties;
042 import java.util.concurrent.ConcurrentHashMap;
043 import java.util.regex.Matcher;
044 import java.util.regex.Pattern;
045
046 import javax.portlet.PortletURL;
047
048
051 public class JSPWikiEngine implements WikiEngine {
052
053 public static String decodeJSPWikiName(String jspWikiName) {
054 return StringUtil.replace(
055 jspWikiName, _JSP_WIKI_NAME_2, _JSP_WIKI_NAME_1);
056 }
057
058 public String convert(
059 com.liferay.portlet.wiki.model.WikiPage page,
060 PortletURL viewPageURL, PortletURL editPageURL,
061 String attachmentURLPrefix)
062 throws PageContentException {
063
064 try {
065 return convert(page);
066 }
067 catch (WikiException we) {
068 throw new PageContentException(we);
069 }
070 }
071
072 public Map<String, Boolean> getOutgoingLinks(
073 com.liferay.portlet.wiki.model.WikiPage page)
074 throws PageContentException {
075
076 if (Validator.isNull(page.getContent())) {
077 return Collections.emptyMap();
078 }
079
080 try {
081 LiferayJSPWikiEngine engine = getEngine(page.getNodeId());
082
083 WikiPage jspWikiPage = LiferayPageProvider.toJSPWikiPage(
084 page, engine);
085
086 Collection<String> titles = engine.scanWikiLinks(
087 jspWikiPage, _encodeJSPWikiContent(page.getContent()));
088
089 Map<String, Boolean> links = new HashMap<String, Boolean>();
090
091 for (String title : titles) {
092 if (title.startsWith("[[")) {
093 title = title.substring(2);
094 }
095 else if (title.startsWith("[")) {
096 title = title.substring(1);
097 }
098
099 if (title.endsWith("]]")) {
100 title = title.substring(0, title.length() - 2);
101 }
102 else if (title.endsWith("]")) {
103 title = title.substring(0, title.length() - 1);
104 }
105
106 Boolean existsObj = links.get(title);
107
108 if (existsObj == null) {
109 if (WikiPageLocalServiceUtil.getPagesCount(
110 page.getNodeId(), title, true) > 0) {
111
112 existsObj = Boolean.TRUE;
113 }
114 else {
115 existsObj = Boolean.FALSE;
116 }
117
118 links.put(title, existsObj);
119 }
120 }
121
122 return links;
123 }
124 catch (SystemException se) {
125 throw new PageContentException(se);
126 }
127 catch (WikiException we) {
128 throw new PageContentException(we);
129 }
130 }
131
132 public void setInterWikiConfiguration(String interWikiConfiguration) {
133 }
134
135 public void setMainConfiguration(String mainConfiguration) {
136 setProperties(mainConfiguration);
137 }
138
139 public boolean validate(long nodeId, String newContent) {
140 return true;
141 }
142
143 protected String convert(com.liferay.portlet.wiki.model.WikiPage page)
144 throws WikiException {
145
146 String content = _encodeJSPWikiContent(page.getContent());
147
148 if (Validator.isNull(content)) {
149 return StringPool.BLANK;
150 }
151
152 com.ecyrd.jspwiki.WikiEngine engine = getEngine(page.getNodeId());
153
154 WikiPage jspWikiPage = LiferayPageProvider.toJSPWikiPage(page, engine);
155
156 WikiContext wikiContext = new WikiContext(engine, jspWikiPage);
157
158 return _decodeJSPWikiContent(engine.textToHTML(wikiContext, content));
159 }
160
161 protected LiferayJSPWikiEngine getEngine(long nodeId) throws WikiException {
162 LiferayJSPWikiEngine engine = _engines.get(nodeId);
163
164 if (engine != null) {
165 return engine;
166 }
167
168 synchronized (_engines) {
169 engine = _engines.get(nodeId);
170
171 if (engine != null) {
172 return engine;
173 }
174
175 Properties nodeProperties = new Properties(_properties);
176
177 nodeProperties.setProperty("nodeId", String.valueOf(nodeId));
178
179 String appName = nodeProperties.getProperty(
180 "jspwiki.applicationName");
181
182 nodeProperties.setProperty(
183 "jspwiki.applicationName", appName + " for node " + nodeId);
184
185 engine = new LiferayJSPWikiEngine(nodeProperties);
186
187 _engines.put(nodeId, engine);
188
189 return engine;
190 }
191 }
192
193 protected synchronized void setProperties(String configuration) {
194 _properties = new Properties();
195
196 InputStream is = new UnsyncByteArrayInputStream(
197 configuration.getBytes());
198
199 try {
200 _properties.load(is);
201 }
202 catch (IOException ioe) {
203 _log.error(ioe, ioe);
204 }
205 }
206
207 private static String _decodeJSPWikiContent(String jspWikiContent) {
208 return StringUtil.replace(
209 jspWikiContent, _JSP_WIKI_NAME_2, _JSP_WIKI_NAME_1);
210 }
211
212 private static String _encodeJSPWikiContent(String content) {
213 StringBundler encodedContent = new StringBundler();
214
215 Matcher commentMatcher = _wikiCommentPattern.matcher(content);
216
217 int start = 0;
218 int end = 0;
219
220 while (commentMatcher.find()) {
221 end = commentMatcher.start();
222
223 String oldContent = content.substring(start, end);
224
225 Matcher wikiLinkMatcher = _wikiLinkPattern.matcher(oldContent);
226
227 encodedContent.append(_encodeLink(oldContent, wikiLinkMatcher));
228 encodedContent.append(
229 content.substring(
230 commentMatcher.start(), commentMatcher.end()));
231
232 start = commentMatcher.end();
233 }
234
235 if (start < content.length()) {
236 content = content.substring(start);
237
238 Matcher wikiLinkMatcher = _wikiLinkPattern.matcher(content);
239
240 encodedContent.append(_encodeLink(content, wikiLinkMatcher));
241 }
242
243 return encodedContent.toString();
244 }
245
246 private static String _encodeJSPWikiName(String name) {
247 if (name == null) {
248 return StringPool.BLANK;
249 }
250
251 return StringUtil.replace(name, _JSP_WIKI_NAME_1, _JSP_WIKI_NAME_2);
252 }
253
254 private static String _encodeLink(String content, Matcher wikiLinkMatcher) {
255 while (wikiLinkMatcher.find()) {
256 String link = wikiLinkMatcher.group();
257 String linkValues = wikiLinkMatcher.group(1);
258
259 String name = linkValues;
260 String url = linkValues;
261
262 int pos = linkValues.indexOf(CharPool.PIPE);
263
264 if (pos != -1) {
265 name = linkValues.substring(pos + 1);
266 url = linkValues.substring(0, pos);
267 }
268
269 String newLink =
270 "[[" + _encodeJSPWikiName(url) + "|" +
271 _encodeJSPWikiName(name) + "]]";
272
273 content = StringUtil.replace(content, link, newLink);
274 }
275
276 return content;
277 }
278
279 private static final String[] _JSP_WIKI_NAME_1 = {
280 StringPool.APOSTROPHE, StringPool.AT, StringPool.CARET,
281 StringPool.EXCLAMATION, StringPool.INVERTED_EXCLAMATION,
282 StringPool.INVERTED_QUESTION, StringPool.GRAVE_ACCENT,
283 StringPool.QUESTION, StringPool.SLASH, StringPool.STAR
284 };
285
286 private static final String[] _JSP_WIKI_NAME_2 = {
287 "__APO__", "__AT__", "__CAR__", "__EXM__", "__INE__", "__INQ__",
288 "__GRA__", "__QUE__", "__SLA__", "__STA__"
289 };
290
291 private static Log _log = LogFactoryUtil.getLog(JSPWikiEngine.class);
292
293 private static Pattern _wikiCommentPattern = Pattern.compile(
294 "[\\{]{3,3}(.*?)[\\}]{3,3}", Pattern.DOTALL);
295 private static Pattern _wikiLinkPattern = Pattern.compile(
296 "[\\[]{1,2}(.+?)[\\]]{1,2}", Pattern.DOTALL);
297
298 private Map<Long, LiferayJSPWikiEngine> _engines =
299 new ConcurrentHashMap<Long, LiferayJSPWikiEngine>();
300 private Properties _properties;
301
302 }