PageRenderTime 58ms CodeModel.GetById 6ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/apps/wiki/wiki-web/src/main/java/com/liferay/wiki/web/internal/importer/MediaWikiImporter.java

http://github.com/liferay/liferay-portal
Java | 823 lines | 595 code | 210 blank | 18 comment | 78 complexity | ecc4499c9f971459b55acd154be7e945 MD5 | raw file
Possible License(s): LGPL-2.0
  1. /**
  2. * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. package com.liferay.wiki.web.internal.importer;
  15. import com.liferay.asset.kernel.model.AssetTag;
  16. import com.liferay.asset.kernel.service.AssetTagLocalService;
  17. import com.liferay.asset.util.AssetHelper;
  18. import com.liferay.document.library.kernel.store.DLStoreUtil;
  19. import com.liferay.petra.string.CharPool;
  20. import com.liferay.petra.string.StringBundler;
  21. import com.liferay.petra.string.StringPool;
  22. import com.liferay.portal.kernel.exception.PortalException;
  23. import com.liferay.portal.kernel.exception.SystemException;
  24. import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
  25. import com.liferay.portal.kernel.log.Log;
  26. import com.liferay.portal.kernel.log.LogFactoryUtil;
  27. import com.liferay.portal.kernel.model.Company;
  28. import com.liferay.portal.kernel.model.User;
  29. import com.liferay.portal.kernel.portletfilerepository.PortletFileRepository;
  30. import com.liferay.portal.kernel.repository.model.FileEntry;
  31. import com.liferay.portal.kernel.service.CompanyLocalService;
  32. import com.liferay.portal.kernel.service.ServiceContext;
  33. import com.liferay.portal.kernel.service.UserLocalService;
  34. import com.liferay.portal.kernel.util.ListUtil;
  35. import com.liferay.portal.kernel.util.MapUtil;
  36. import com.liferay.portal.kernel.util.ObjectValuePair;
  37. import com.liferay.portal.kernel.util.ProgressTracker;
  38. import com.liferay.portal.kernel.util.ProgressTrackerThreadLocal;
  39. import com.liferay.portal.kernel.util.SetUtil;
  40. import com.liferay.portal.kernel.util.StringUtil;
  41. import com.liferay.portal.kernel.util.Validator;
  42. import com.liferay.portal.kernel.xml.Attribute;
  43. import com.liferay.portal.kernel.xml.Document;
  44. import com.liferay.portal.kernel.xml.DocumentException;
  45. import com.liferay.portal.kernel.xml.Element;
  46. import com.liferay.portal.kernel.xml.SAXReaderUtil;
  47. import com.liferay.portal.kernel.zip.ZipReader;
  48. import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
  49. import com.liferay.wiki.configuration.WikiGroupServiceConfiguration;
  50. import com.liferay.wiki.constants.WikiPageConstants;
  51. import com.liferay.wiki.exception.ImportFilesException;
  52. import com.liferay.wiki.exception.NoSuchPageException;
  53. import com.liferay.wiki.importer.WikiImporter;
  54. import com.liferay.wiki.model.WikiNode;
  55. import com.liferay.wiki.model.WikiPage;
  56. import com.liferay.wiki.service.WikiPageLocalService;
  57. import com.liferay.wiki.validator.WikiPageTitleValidator;
  58. import com.liferay.wiki.web.internal.translator.MediaWikiToCreoleTranslator;
  59. import java.io.IOException;
  60. import java.io.InputStream;
  61. import java.io.InputStreamReader;
  62. import java.util.ArrayList;
  63. import java.util.Collections;
  64. import java.util.HashMap;
  65. import java.util.List;
  66. import java.util.Map;
  67. import java.util.Set;
  68. import java.util.regex.Matcher;
  69. import java.util.regex.Pattern;
  70. import org.osgi.service.component.annotations.Component;
  71. import org.osgi.service.component.annotations.Reference;
  72. /**
  73. * @author Alvaro del Castillo
  74. * @author Jorge Ferrer
  75. */
  76. @Component(
  77. property = {"importer=MediaWiki", "page=/wiki/import/mediawiki.jsp"},
  78. service = WikiImporter.class
  79. )
  80. public class MediaWikiImporter implements WikiImporter {
  81. public static final String FORMAT_CREOLE = "creole";
  82. public static final String OPTIONS_FRONT_PAGE = "OPTIONS_FRONT_PAGE";
  83. public static final String OPTIONS_IMPORT_LATEST_VERSION =
  84. "OPTIONS_IMPORT_LATEST_VERSION";
  85. public static final String OPTIONS_STRICT_IMPORT_MODE =
  86. "OPTIONS_STRICT_IMPORT_MODE";
  87. public static final String SHARED_IMAGES_CONTENT = "See attachments";
  88. public static final String SHARED_IMAGES_TITLE = "SharedImages";
  89. @Override
  90. public void importPages(
  91. long userId, WikiNode node, InputStream[] inputStreams,
  92. Map<String, String[]> options)
  93. throws PortalException {
  94. if ((inputStreams.length < 1) || (inputStreams[0] == null)) {
  95. throw new PortalException("The pages file is mandatory");
  96. }
  97. InputStream pagesInputStream = inputStreams[0];
  98. InputStream usersInputStream = null;
  99. if (inputStreams.length > 1) {
  100. usersInputStream = inputStreams[1];
  101. }
  102. InputStream imagesInputStream = null;
  103. if (inputStreams.length > 2) {
  104. imagesInputStream = inputStreams[2];
  105. }
  106. try {
  107. Document document = SAXReaderUtil.read(pagesInputStream);
  108. Map<String, String> usersMap = readUsersFile(usersInputStream);
  109. Element rootElement = document.getRootElement();
  110. List<String> specialNamespaces = readSpecialNamespaces(rootElement);
  111. processImages(userId, node, imagesInputStream);
  112. processSpecialPages(userId, node, rootElement, specialNamespaces);
  113. processRegularPages(
  114. userId, node, rootElement, specialNamespaces, usersMap,
  115. imagesInputStream, options);
  116. moveFrontPage(userId, node, options);
  117. }
  118. catch (DocumentException documentException) {
  119. throw new ImportFilesException(
  120. "Invalid XML file provided", documentException);
  121. }
  122. catch (IOException ioException) {
  123. throw new ImportFilesException(
  124. "Error reading the files provided", ioException);
  125. }
  126. catch (PortalException portalException) {
  127. throw portalException;
  128. }
  129. catch (Exception exception) {
  130. throw new PortalException(exception);
  131. }
  132. }
  133. protected String getCreoleRedirectContent(String redirectTitle) {
  134. return StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
  135. StringPool.DOUBLE_CLOSE_BRACKET;
  136. }
  137. protected long getUserId(
  138. long userId, WikiNode node, String author,
  139. Map<String, String> usersMap) {
  140. User user = null;
  141. String emailAddress = usersMap.get(author);
  142. if (Validator.isNotNull(emailAddress)) {
  143. user = _userLocalService.fetchUserByEmailAddress(
  144. node.getCompanyId(), emailAddress);
  145. }
  146. else {
  147. user = _userLocalService.fetchUserByScreenName(
  148. node.getCompanyId(), StringUtil.toLowerCase(author));
  149. }
  150. if (user != null) {
  151. return user.getUserId();
  152. }
  153. return userId;
  154. }
  155. protected void importPage(
  156. long userId, String author, WikiNode node, String title,
  157. String content, String summary, Map<String, String> usersMap,
  158. boolean strictImportMode)
  159. throws PortalException {
  160. try {
  161. long authorUserId = getUserId(userId, node, author, usersMap);
  162. String parentTitle = readParentTitle(content);
  163. String redirectTitle = readRedirectTitle(content);
  164. if (Validator.isNotNull(redirectTitle)) {
  165. content = getCreoleRedirectContent(redirectTitle);
  166. }
  167. else {
  168. content = translateMediaWikiToCreole(content, strictImportMode);
  169. content = translateMediaLinks(node, content);
  170. }
  171. ServiceContext serviceContext = new ServiceContext();
  172. serviceContext.setAddGroupPermissions(true);
  173. serviceContext.setAddGuestPermissions(true);
  174. serviceContext.setAssetTagNames(
  175. readAssetTagNames(userId, node, content));
  176. WikiPage page = null;
  177. try {
  178. page = _wikiPageLocalService.getPage(node.getNodeId(), title);
  179. }
  180. catch (NoSuchPageException noSuchPageException) {
  181. if (_log.isDebugEnabled()) {
  182. _log.debug(noSuchPageException, noSuchPageException);
  183. }
  184. page = _wikiPageLocalService.addPage(
  185. authorUserId, node.getNodeId(), title,
  186. WikiPageConstants.NEW, null, true, serviceContext);
  187. }
  188. _wikiPageLocalService.updatePage(
  189. authorUserId, node.getNodeId(), title, page.getVersion(),
  190. content, summary, true, FORMAT_CREOLE, parentTitle,
  191. redirectTitle, serviceContext);
  192. }
  193. catch (Exception exception) {
  194. throw new PortalException(
  195. "Error importing page " + title, exception);
  196. }
  197. }
  198. protected boolean isSpecialMediaWikiPage(
  199. String title, List<String> specialNamespaces) {
  200. for (String namespace : specialNamespaces) {
  201. if (title.startsWith(namespace + StringPool.COLON)) {
  202. return true;
  203. }
  204. }
  205. return false;
  206. }
  207. protected boolean isValidImage(String[] paths, InputStream inputStream) {
  208. if (_specialMediaWikiDirs.contains(paths[0]) ||
  209. ((paths.length > 1) && _specialMediaWikiDirs.contains(paths[1]))) {
  210. return false;
  211. }
  212. String fileName = paths[paths.length - 1];
  213. try {
  214. DLStoreUtil.validate(fileName, true, inputStream);
  215. }
  216. catch (PortalException | SystemException exception) {
  217. // LPS-52675
  218. if (_log.isDebugEnabled()) {
  219. _log.debug(exception, exception);
  220. }
  221. return false;
  222. }
  223. return true;
  224. }
  225. protected void moveFrontPage(
  226. long userId, WikiNode node, Map<String, String[]> options) {
  227. String frontPageTitle = MapUtil.getString(options, OPTIONS_FRONT_PAGE);
  228. if (Validator.isNull(frontPageTitle)) {
  229. return;
  230. }
  231. frontPageTitle = _wikiPageTitleValidator.normalize(frontPageTitle);
  232. try {
  233. int count = _wikiPageLocalService.getPagesCount(
  234. node.getNodeId(), frontPageTitle, true);
  235. if (count > 0) {
  236. ServiceContext serviceContext = new ServiceContext();
  237. serviceContext.setAddGroupPermissions(true);
  238. serviceContext.setAddGuestPermissions(true);
  239. _wikiPageLocalService.renamePage(
  240. userId, node.getNodeId(), frontPageTitle,
  241. _wikiGroupServiceConfiguration.frontPageName(), false,
  242. serviceContext);
  243. }
  244. }
  245. catch (Exception exception) {
  246. if (_log.isWarnEnabled()) {
  247. _log.warn(
  248. StringBundler.concat(
  249. "Could not move ",
  250. _wikiGroupServiceConfiguration.frontPageName(),
  251. " to the title provided: ", frontPageTitle),
  252. exception);
  253. }
  254. }
  255. }
  256. protected String normalize(String categoryName, int length) {
  257. categoryName = _toWord(categoryName.trim());
  258. return StringUtil.shorten(categoryName, length);
  259. }
  260. protected void processImages(
  261. long userId, WikiNode node, InputStream imagesInputStream)
  262. throws Exception {
  263. if (imagesInputStream == null) {
  264. return;
  265. }
  266. ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(
  267. imagesInputStream);
  268. List<String> entries = zipReader.getEntries();
  269. if (entries == null) {
  270. throw new ImportFilesException();
  271. }
  272. ProgressTracker progressTracker =
  273. ProgressTrackerThreadLocal.getProgressTracker();
  274. int count = 0;
  275. int total = entries.size();
  276. if (total > 0) {
  277. try {
  278. _wikiPageLocalService.getPage(
  279. node.getNodeId(), SHARED_IMAGES_TITLE);
  280. }
  281. catch (NoSuchPageException noSuchPageException) {
  282. if (_log.isDebugEnabled()) {
  283. _log.debug(noSuchPageException, noSuchPageException);
  284. }
  285. ServiceContext serviceContext = new ServiceContext();
  286. serviceContext.setAddGroupPermissions(true);
  287. serviceContext.setAddGuestPermissions(true);
  288. _wikiPageLocalService.addPage(
  289. userId, node.getNodeId(), SHARED_IMAGES_TITLE,
  290. SHARED_IMAGES_CONTENT, null, true, serviceContext);
  291. }
  292. }
  293. List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
  294. new ArrayList<>();
  295. try {
  296. int percentage = 50;
  297. for (int i = 0; i < entries.size(); i++) {
  298. String entry = entries.get(i);
  299. String key = entry;
  300. InputStream inputStream = zipReader.getEntryAsInputStream(
  301. entry);
  302. String[] paths = StringUtil.split(key, CharPool.SLASH);
  303. if (!isValidImage(paths, inputStream)) {
  304. if (_log.isInfoEnabled()) {
  305. _log.info("Ignoring " + key);
  306. }
  307. continue;
  308. }
  309. String fileName = StringUtil.toLowerCase(
  310. paths[paths.length - 1]);
  311. ObjectValuePair<String, InputStream> inputStreamOVP =
  312. new ObjectValuePair<>(fileName, inputStream);
  313. inputStreamOVPs.add(inputStreamOVP);
  314. count++;
  315. if ((i % 5) == 0) {
  316. _wikiPageLocalService.addPageAttachments(
  317. userId, node.getNodeId(), SHARED_IMAGES_TITLE,
  318. inputStreamOVPs);
  319. inputStreamOVPs.clear();
  320. if (progressTracker != null) {
  321. percentage = Math.min(50 + ((i * 50) / total), 99);
  322. progressTracker.setPercent(percentage);
  323. }
  324. }
  325. }
  326. if (!inputStreamOVPs.isEmpty()) {
  327. _wikiPageLocalService.addPageAttachments(
  328. userId, node.getNodeId(), SHARED_IMAGES_TITLE,
  329. inputStreamOVPs);
  330. }
  331. }
  332. finally {
  333. for (ObjectValuePair<String, InputStream> inputStreamOVP :
  334. inputStreamOVPs) {
  335. try (InputStream inputStream = inputStreamOVP.getValue()) {
  336. }
  337. catch (IOException ioException) {
  338. if (_log.isWarnEnabled()) {
  339. _log.warn(ioException, ioException);
  340. }
  341. }
  342. }
  343. }
  344. zipReader.close();
  345. if (_log.isInfoEnabled()) {
  346. _log.info(
  347. StringBundler.concat(
  348. "Imported ", count, " images into ", node.getName()));
  349. }
  350. }
  351. protected void processRegularPages(
  352. long userId, WikiNode node, Element rootElement,
  353. List<String> specialNamespaces, Map<String, String> usersMap,
  354. InputStream imagesInputStream, Map<String, String[]> options) {
  355. boolean importLatestVersion = MapUtil.getBoolean(
  356. options, OPTIONS_IMPORT_LATEST_VERSION);
  357. boolean strictImportMode = MapUtil.getBoolean(
  358. options, OPTIONS_STRICT_IMPORT_MODE);
  359. ProgressTracker progressTracker =
  360. ProgressTrackerThreadLocal.getProgressTracker();
  361. int count = 0;
  362. int percentage = 10;
  363. int maxPercentage = 50;
  364. if (imagesInputStream == null) {
  365. maxPercentage = 99;
  366. }
  367. List<Element> pageElements = rootElement.elements("page");
  368. for (int i = 0; i < pageElements.size(); i++) {
  369. Element pageElement = pageElements.get(i);
  370. String title = pageElement.elementText("title");
  371. if (isSpecialMediaWikiPage(title, specialNamespaces)) {
  372. continue;
  373. }
  374. title = _wikiPageTitleValidator.normalize(title);
  375. percentage = Math.min(
  376. 10 + ((i * (maxPercentage - percentage)) / pageElements.size()),
  377. maxPercentage);
  378. progressTracker.setPercent(percentage);
  379. List<Element> revisionElements = pageElement.elements("revision");
  380. if (importLatestVersion) {
  381. Element lastRevisionElement = revisionElements.get(
  382. revisionElements.size() - 1);
  383. revisionElements = new ArrayList<>();
  384. revisionElements.add(lastRevisionElement);
  385. }
  386. for (Element revisionElement : revisionElements) {
  387. Element contributorElement = revisionElement.element(
  388. "contributor");
  389. String author = contributorElement.elementText("username");
  390. String content = revisionElement.elementText("text");
  391. String summary = revisionElement.elementText("comment");
  392. try {
  393. importPage(
  394. userId, author, node, title, content, summary, usersMap,
  395. strictImportMode);
  396. }
  397. catch (Exception exception) {
  398. if (_log.isWarnEnabled()) {
  399. _log.warn(
  400. "Page with title " + title +
  401. " could not be imported",
  402. exception);
  403. }
  404. }
  405. }
  406. count++;
  407. }
  408. if (_log.isInfoEnabled()) {
  409. _log.info(
  410. StringBundler.concat(
  411. "Imported ", count, " pages into ", node.getName()));
  412. }
  413. }
  414. protected void processSpecialPages(
  415. long userId, WikiNode node, Element rootElement,
  416. List<String> specialNamespaces)
  417. throws PortalException {
  418. ProgressTracker progressTracker =
  419. ProgressTrackerThreadLocal.getProgressTracker();
  420. List<Element> pageElements = rootElement.elements("page");
  421. for (int i = 0; i < pageElements.size(); i++) {
  422. Element pageElement = pageElements.get(i);
  423. String title = pageElement.elementText("title");
  424. if (!title.startsWith("Category:")) {
  425. if (isSpecialMediaWikiPage(title, specialNamespaces)) {
  426. rootElement.remove(pageElement);
  427. }
  428. continue;
  429. }
  430. String categoryName = title.substring("Category:".length());
  431. categoryName = normalize(categoryName, 75);
  432. _assetTagLocalService.checkTags(
  433. userId, node.getGroupId(), new String[] {categoryName});
  434. if ((i % 5) == 0) {
  435. progressTracker.setPercent((i * 10) / pageElements.size());
  436. }
  437. }
  438. }
  439. protected String[] readAssetTagNames(
  440. long userId, WikiNode node, String content)
  441. throws PortalException {
  442. Matcher matcher = _categoriesPattern.matcher(content);
  443. List<String> assetTagNames = new ArrayList<>();
  444. while (matcher.find()) {
  445. String categoryName = matcher.group(1);
  446. categoryName = normalize(categoryName, 75);
  447. List<AssetTag> assetTags = _assetTagLocalService.checkTags(
  448. userId, node.getGroupId(), new String[] {categoryName});
  449. assetTagNames.addAll(
  450. ListUtil.toList(assetTags, AssetTag.NAME_ACCESSOR));
  451. }
  452. if (content.contains(_WORK_IN_PROGRESS)) {
  453. assetTagNames.add(_WORK_IN_PROGRESS_TAG);
  454. }
  455. return assetTagNames.toArray(new String[0]);
  456. }
  457. protected String readParentTitle(String content) {
  458. Matcher matcher = _parentPattern.matcher(content);
  459. String redirectTitle = StringPool.BLANK;
  460. if (matcher.find()) {
  461. redirectTitle = matcher.group(1);
  462. redirectTitle = _wikiPageTitleValidator.normalize(redirectTitle);
  463. redirectTitle += " (disambiguation)";
  464. }
  465. return redirectTitle;
  466. }
  467. protected String readRedirectTitle(String content) {
  468. Matcher matcher = _redirectPattern.matcher(content);
  469. String redirectTitle = StringPool.BLANK;
  470. if (matcher.find()) {
  471. redirectTitle = matcher.group(1);
  472. redirectTitle = _wikiPageTitleValidator.normalize(redirectTitle);
  473. }
  474. return redirectTitle;
  475. }
  476. protected List<String> readSpecialNamespaces(Element root)
  477. throws ImportFilesException {
  478. Element siteinfoElement = root.element("siteinfo");
  479. if (siteinfoElement == null) {
  480. throw new ImportFilesException("Invalid pages XML file");
  481. }
  482. List<String> namespaces = new ArrayList<>();
  483. Element namespacesElement = siteinfoElement.element("namespaces");
  484. List<Element> namespaceElements = namespacesElement.elements(
  485. "namespace");
  486. for (Element namespaceElement : namespaceElements) {
  487. Attribute attribute = namespaceElement.attribute("key");
  488. String value = attribute.getValue();
  489. if (!value.equals("0")) {
  490. namespaces.add(namespaceElement.getText());
  491. }
  492. }
  493. return namespaces;
  494. }
  495. protected Map<String, String> readUsersFile(InputStream usersInputStream)
  496. throws IOException {
  497. if (usersInputStream == null) {
  498. return Collections.emptyMap();
  499. }
  500. Map<String, String> usersMap = new HashMap<>();
  501. UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
  502. new InputStreamReader(usersInputStream));
  503. String line = unsyncBufferedReader.readLine();
  504. while (line != null) {
  505. String[] array = StringUtil.split(line);
  506. if ((array.length == 2) && Validator.isNotNull(array[0]) &&
  507. Validator.isNotNull(array[1])) {
  508. usersMap.put(array[0], array[1]);
  509. }
  510. else {
  511. if (_log.isInfoEnabled()) {
  512. _log.info(
  513. "Ignoring line " + line +
  514. " because it does not contain exactly 2 columns");
  515. }
  516. }
  517. line = unsyncBufferedReader.readLine();
  518. }
  519. return usersMap;
  520. }
  521. protected String translateMediaLinks(WikiNode node, String content) {
  522. try {
  523. StringBuffer sb = new StringBuffer();
  524. WikiPage sharedImagesPage = _wikiPageLocalService.getPage(
  525. node.getNodeId(), SHARED_IMAGES_TITLE);
  526. Company company = _companyLocalService.getCompany(
  527. node.getCompanyId());
  528. String portalURL = company.getPortalURL(node.getGroupId());
  529. Matcher matcher = _mediaLinkPattern.matcher(content);
  530. while (matcher.find()) {
  531. String fileName = matcher.group(2);
  532. FileEntry fileEntry =
  533. _portletFileRepository.fetchPortletFileEntry(
  534. node.getGroupId(),
  535. sharedImagesPage.getAttachmentsFolderId(), fileName);
  536. if (fileEntry == null) {
  537. matcher.appendReplacement(sb, matcher.group());
  538. continue;
  539. }
  540. String fileEntryURL =
  541. _portletFileRepository.getPortletFileEntryURL(
  542. null, fileEntry, StringPool.BLANK);
  543. String linkLabel = matcher.group(3);
  544. if (linkLabel == null) {
  545. linkLabel = StringPool.PIPE + fileName;
  546. }
  547. matcher.appendReplacement(
  548. sb,
  549. StringBundler.concat(
  550. "[[", portalURL, fileEntryURL, linkLabel, "]]"));
  551. }
  552. matcher.appendTail(sb);
  553. return sb.toString();
  554. }
  555. catch (PortalException portalException) {
  556. if (_log.isWarnEnabled()) {
  557. _log.warn(portalException, portalException);
  558. }
  559. return content;
  560. }
  561. }
  562. protected String translateMediaWikiToCreole(
  563. String content, boolean strictImportMode) {
  564. _translator.setStrictImportMode(strictImportMode);
  565. return _translator.translate(content);
  566. }
  567. private String _toWord(String text) {
  568. if (Validator.isNull(text)) {
  569. return text;
  570. }
  571. char[] textCharArray = text.toCharArray();
  572. for (int i = 0; i < textCharArray.length; i++) {
  573. char c = textCharArray[i];
  574. for (char invalidChar : AssetHelper.INVALID_CHARACTERS) {
  575. if (c == invalidChar) {
  576. textCharArray[i] = CharPool.SPACE;
  577. break;
  578. }
  579. }
  580. }
  581. return new String(textCharArray);
  582. }
  583. private static final String _WORK_IN_PROGRESS = "{{Work in progress}}";
  584. private static final String _WORK_IN_PROGRESS_TAG = "work in progress";
  585. private static final Log _log = LogFactoryUtil.getLog(
  586. MediaWikiImporter.class);
  587. private static final Pattern _categoriesPattern = Pattern.compile(
  588. "\\[\\[[Cc]ategory:([^\\]]*)\\]\\][\\n]*");
  589. private static final Pattern _mediaLinkPattern = Pattern.compile(
  590. "\\[\\[(Media:)([^\\]\\|]*)(\\|[^\\]]*)?\\]\\]", Pattern.DOTALL);
  591. private static final Pattern _parentPattern = Pattern.compile(
  592. "\\{{2}OtherTopics\\|([^\\}]*)\\}{2}");
  593. private static final Pattern _redirectPattern = Pattern.compile(
  594. "#REDIRECT \\[\\[([^\\]]*)\\]\\]");
  595. private static final Set<String> _specialMediaWikiDirs = SetUtil.fromArray(
  596. "archive", "temp", "thumb");
  597. @Reference
  598. private AssetTagLocalService _assetTagLocalService;
  599. @Reference
  600. private CompanyLocalService _companyLocalService;
  601. @Reference
  602. private PortletFileRepository _portletFileRepository;
  603. private final MediaWikiToCreoleTranslator _translator =
  604. new MediaWikiToCreoleTranslator();
  605. @Reference
  606. private UserLocalService _userLocalService;
  607. @Reference
  608. private WikiGroupServiceConfiguration _wikiGroupServiceConfiguration;
  609. @Reference
  610. private WikiPageLocalService _wikiPageLocalService;
  611. @Reference
  612. private WikiPageTitleValidator _wikiPageTitleValidator;
  613. }