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