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(title.length() - 2, title.length());
101 }
102 else if (title.startsWith("[")) {
103 title = title.substring(title.length() - 1, title.length());
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)
162 throws WikiException {
163
164 LiferayJSPWikiEngine engine = _engines.get(nodeId);
165
166 if (engine != null) {
167 return engine;
168 }
169
170 synchronized (_engines) {
171 engine = _engines.get(nodeId);
172
173 if (engine != null) {
174 return engine;
175 }
176
177 Properties nodeProperties = new Properties(_properties);
178
179 nodeProperties.setProperty("nodeId", String.valueOf(nodeId));
180
181 String appName = nodeProperties.getProperty(
182 "jspwiki.applicationName");
183
184 nodeProperties.setProperty(
185 "jspwiki.applicationName", appName + " for node " + nodeId);
186
187 engine = new LiferayJSPWikiEngine(nodeProperties);
188
189 _engines.put(nodeId, engine);
190
191 return engine;
192 }
193 }
194
195 protected synchronized void setProperties(String configuration) {
196 _properties = new Properties();
197
198 InputStream is = new UnsyncByteArrayInputStream(
199 configuration.getBytes());
200
201 try {
202 _properties.load(is);
203 }
204 catch (IOException ioe) {
205 _log.error(ioe, ioe);
206 }
207 }
208
209 private static String _decodeJSPWikiContent(String jspWikiContent) {
210 return StringUtil.replace(
211 jspWikiContent, _JSP_WIKI_NAME_2, _JSP_WIKI_NAME_1);
212 }
213
214 private static String _encodeJSPWikiContent(String content) {
215
216 StringBundler encodedContent = new StringBundler();
217
218 Matcher commentMatcher = _wikiCommentPattern.matcher(content);
219
220 int start = 0;
221 int end = 0;
222
223 String oldContent = StringPool.BLANK;
224 String newContent = StringPool.BLANK;
225
226 while (commentMatcher.find()) {
227 end = commentMatcher.start();
228
229 oldContent = content.substring(start, end);
230
231 Matcher wikiLinkMatcher = _wikiLinkPattern.matcher(oldContent);
232
233 newContent = oldContent;
234
235 while (wikiLinkMatcher.find()) {
236 String link = wikiLinkMatcher.group();
237 String linkValues = wikiLinkMatcher.group(1);
238
239 String name = linkValues;
240 String url = linkValues;
241
242 int pos = linkValues.indexOf(CharPool.PIPE);
243
244 if (pos != -1) {
245 name = linkValues.substring(pos + 1, linkValues.length());
246 url = linkValues.substring(0, pos);
247 }
248
249 String newLink =
250 "[[" + _encodeJSPWikiName(url) + "|" + name + "]]";
251
252 newContent = StringUtil.replace(newContent, link, newLink);
253 }
254
255 encodedContent.append(newContent);
256 encodedContent.append(
257 content.substring(
258 commentMatcher.start(), commentMatcher.end()));
259
260 start = commentMatcher.end();
261 }
262
263 if (start != content.length()) {
264 encodedContent.append(content.substring(start));
265 }
266
267 return encodedContent.toString();
268 }
269
270 private static String _encodeJSPWikiName(String name) {
271 if (name == null) {
272 return StringPool.BLANK;
273 }
274
275 return StringUtil.replace(name, _JSP_WIKI_NAME_1, _JSP_WIKI_NAME_2);
276 }
277
278 private static final String[] _JSP_WIKI_NAME_1 = {
279 StringPool.APOSTROPHE, StringPool.AT, StringPool.CARET,
280 StringPool.EXCLAMATION, StringPool.INVERTED_EXCLAMATION,
281 StringPool.INVERTED_QUESTION, StringPool.GRAVE_ACCENT,
282 StringPool.QUESTION, StringPool.SLASH, StringPool.STAR
283 };
284
285 private static final String[] _JSP_WIKI_NAME_2 = {
286 "__APO__", "__AT__", "__CAR__", "__EXM__", "__INE__", "__INQ__",
287 "__GRA__", "__QUE__", "__SLA__", "__STA__"
288 };
289
290 private static Log _log = LogFactoryUtil.getLog(JSPWikiEngine.class);
291
292 private static Pattern _wikiCommentPattern = Pattern.compile(
293 "[\\{]{3,3}(.*?)[\\}]{3,3}", Pattern.DOTALL);
294 private static Pattern _wikiLinkPattern = Pattern.compile(
295 "[\\[]{2,2}(.+?)[\\]]{2,2}", Pattern.DOTALL);
296
297 private Map<Long, LiferayJSPWikiEngine> _engines =
298 new ConcurrentHashMap<Long, LiferayJSPWikiEngine>();
299 private Properties _properties;
300
301 }