001
014
015 package com.liferay.portlet.wiki.lar;
016
017 import com.liferay.portal.kernel.dao.orm.QueryUtil;
018 import com.liferay.portal.kernel.lar.BasePortletDataHandler;
019 import com.liferay.portal.kernel.lar.PortletDataContext;
020 import com.liferay.portal.kernel.lar.PortletDataException;
021 import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
022 import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
023 import com.liferay.portal.kernel.util.MapUtil;
024 import com.liferay.portal.kernel.util.StreamUtil;
025 import com.liferay.portal.kernel.util.StringBundler;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.workflow.WorkflowConstants;
028 import com.liferay.portal.kernel.xml.Document;
029 import com.liferay.portal.kernel.xml.Element;
030 import com.liferay.portal.kernel.xml.SAXReaderUtil;
031 import com.liferay.portal.model.CompanyConstants;
032 import com.liferay.portal.service.ServiceContext;
033 import com.liferay.portal.util.PortletKeys;
034 import com.liferay.portal.util.PropsValues;
035 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
036 import com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl;
037 import com.liferay.portlet.wiki.NoSuchNodeException;
038 import com.liferay.portlet.wiki.NoSuchPageException;
039 import com.liferay.portlet.wiki.model.WikiNode;
040 import com.liferay.portlet.wiki.model.WikiPage;
041 import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
042 import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
043 import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
044 import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
045 import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
046 import com.liferay.portlet.wiki.util.WikiCacheUtil;
047 import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
048
049 import java.io.InputStream;
050
051 import java.util.List;
052 import java.util.Map;
053
054 import javax.portlet.PortletPreferences;
055
056
062 public class WikiPortletDataHandlerImpl extends BasePortletDataHandler {
063
064 public static void exportNode(
065 PortletDataContext portletDataContext, Element nodesElement,
066 Element pagesElement, WikiNode node)
067 throws Exception {
068
069 if (portletDataContext.isWithinDateRange(node.getModifiedDate())) {
070 String path = getNodePath(portletDataContext, node);
071
072 if (portletDataContext.isPathNotProcessed(path)) {
073 Element nodeElement = nodesElement.addElement("node");
074
075 portletDataContext.addClassedModel(
076 nodeElement, path, node, _NAMESPACE);
077 }
078 }
079
080 Element dlFileEntryTypesElement = pagesElement.addElement(
081 "dl-file-entry-types");
082 Element dlFoldersElement = pagesElement.addElement("dl-folders");
083 Element dlFileEntriesElement = pagesElement.addElement(
084 "dl-file-entries");
085 Element dlFileRanksElement = pagesElement.addElement("dl-file-ranks");
086 Element dlRepositoriesElement = pagesElement.addElement(
087 "dl-repositories");
088 Element dlRepositoryEntriesElement = pagesElement.addElement(
089 "dl-repository-entries");
090
091 List<WikiPage> pages = WikiPageUtil.findByN_S(
092 node.getNodeId(), WorkflowConstants.STATUS_APPROVED,
093 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
094 new PageVersionComparator(true));
095
096 for (WikiPage page : pages) {
097 exportPage(
098 portletDataContext, nodesElement, pagesElement,
099 dlFileEntryTypesElement, dlFoldersElement, dlFileEntriesElement,
100 dlFileRanksElement, dlRepositoriesElement,
101 dlRepositoryEntriesElement, page, true);
102 }
103 }
104
105 public static PortletDataHandlerControl[] getMetadataControls() {
106 return _metadataControls;
107 }
108
109 public static void importNode(
110 PortletDataContext portletDataContext, WikiNode node)
111 throws Exception {
112
113 long userId = portletDataContext.getUserId(node.getUserUuid());
114
115 ServiceContext serviceContext = new ServiceContext();
116
117 serviceContext.setAddGroupPermissions(true);
118 serviceContext.setAddGuestPermissions(true);
119 serviceContext.setCreateDate(node.getCreateDate());
120 serviceContext.setModifiedDate(node.getModifiedDate());
121 serviceContext.setScopeGroupId(portletDataContext.getScopeGroupId());
122
123 WikiNode importedNode = null;
124
125 if (portletDataContext.isDataStrategyMirror()) {
126 WikiNode existingNode = WikiNodeUtil.fetchByUUID_G(
127 node.getUuid(), portletDataContext.getScopeGroupId());
128
129 String initialNodeName = PropsValues.WIKI_INITIAL_NODE_NAME;
130
131 if ((existingNode == null) &&
132 initialNodeName.equals(node.getName())) {
133
134 try {
135 WikiNodeUtil.removeByG_N(
136 portletDataContext.getScopeGroupId(), node.getName());
137 }
138 catch (NoSuchNodeException nsne) {
139 }
140 }
141
142 if (existingNode == null) {
143 serviceContext.setUuid(node.getUuid());
144
145 importedNode = WikiNodeLocalServiceUtil.addNode(
146 userId, node.getName(), node.getDescription(),
147 serviceContext);
148 }
149 else {
150 importedNode = WikiNodeLocalServiceUtil.updateNode(
151 existingNode.getNodeId(), node.getName(),
152 node.getDescription(), serviceContext);
153 }
154 }
155 else {
156 String initialNodeName = PropsValues.WIKI_INITIAL_NODE_NAME;
157
158 if (initialNodeName.equals(node.getName())) {
159 try {
160 WikiNodeUtil.removeByG_N(
161 portletDataContext.getScopeGroupId(), node.getName());
162 }
163 catch (NoSuchNodeException nsne) {
164 }
165 }
166
167 String nodeName = getNodeName(
168 portletDataContext, node, node.getName(), 2);
169
170 importedNode = WikiNodeLocalServiceUtil.addNode(
171 userId, nodeName, node.getDescription(), serviceContext);
172 }
173
174 portletDataContext.importClassedModel(node, importedNode, _NAMESPACE);
175 }
176
177 public static void importPage(
178 PortletDataContext portletDataContext, Element pageElement,
179 WikiPage page)
180 throws Exception {
181
182 long userId = portletDataContext.getUserId(page.getUserUuid());
183
184 Map<Long, Long> nodeIds =
185 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
186 WikiNode.class);
187
188 long nodeId = MapUtil.getLong(
189 nodeIds, page.getNodeId(), page.getNodeId());
190
191 String content = JournalPortletDataHandlerImpl.importReferencedContent(
192 portletDataContext, pageElement, page.getContent());
193
194 page.setContent(content);
195
196 ServiceContext serviceContext = portletDataContext.createServiceContext(
197 pageElement, page, _NAMESPACE);
198
199 if (page.getStatus() != WorkflowConstants.STATUS_APPROVED) {
200 serviceContext.setWorkflowAction(
201 WorkflowConstants.ACTION_SAVE_DRAFT);
202 }
203
204 WikiPage importedPage = null;
205
206 WikiPage existingPage = WikiPageUtil.fetchByUUID_G(
207 page.getUuid(), portletDataContext.getScopeGroupId());
208
209 if (existingPage == null) {
210 try {
211 existingPage = WikiPageLocalServiceUtil.getPage(
212 nodeId, page.getTitle());
213 }
214 catch (NoSuchPageException nspe) {
215 }
216 }
217
218 if (existingPage == null) {
219 serviceContext.setUuid(page.getUuid());
220
221 importedPage = WikiPageLocalServiceUtil.addPage(
222 userId, nodeId, page.getTitle(), page.getVersion(),
223 page.getContent(), page.getSummary(), page.isMinorEdit(),
224 page.getFormat(), page.getHead(), page.getParentTitle(),
225 page.getRedirectTitle(), serviceContext);
226 }
227 else {
228 importedPage = WikiPageLocalServiceUtil.updatePage(
229 userId, nodeId, existingPage.getTitle(), 0, page.getContent(),
230 page.getSummary(), page.isMinorEdit(), page.getFormat(),
231 page.getParentTitle(), page.getRedirectTitle(), serviceContext);
232 }
233
234 if (portletDataContext.getBooleanParameter(_NAMESPACE, "attachments") &&
235 page.isHead()) {
236
237 for (Element attachmentElement :
238 pageElement.elements("attachment")) {
239
240 String name = attachmentElement.attributeValue("name");
241 String binPath = attachmentElement.attributeValue("bin-path");
242
243 InputStream inputStream = null;
244
245 try {
246 inputStream = portletDataContext.getZipEntryAsInputStream(
247 binPath);
248
249 WikiPageLocalServiceUtil.addPageAttachment(
250 importedPage.getCompanyId(),
251 importedPage.getAttachmentsDir(),
252 importedPage.getModifiedDate(), name, inputStream);
253 }
254 finally {
255 StreamUtil.cleanUp(inputStream);
256 }
257 }
258 }
259
260 portletDataContext.importClassedModel(page, importedPage, _NAMESPACE);
261 }
262
263 @Override
264 public PortletDataHandlerControl[] getExportControls() {
265 return new PortletDataHandlerControl[] {
266 _nodesAndPages
267 };
268 }
269
270 @Override
271 public PortletDataHandlerControl[] getExportMetadataControls() {
272 return new PortletDataHandlerControl[] {
273 new PortletDataHandlerBoolean(
274 _NAMESPACE, "wiki-pages", true, _metadataControls)
275 };
276 }
277
278 @Override
279 public PortletDataHandlerControl[] getImportControls() {
280 return new PortletDataHandlerControl[] {
281 _nodesAndPages
282 };
283 }
284
285 @Override
286 public PortletDataHandlerControl[] getImportMetadataControls() {
287 return new PortletDataHandlerControl[] {
288 new PortletDataHandlerBoolean(
289 _NAMESPACE, "wiki-pages", true, _metadataControls)
290 };
291 }
292
293 @Override
294 public PortletPreferences importData(
295 PortletDataContext portletDataContext, String portletId,
296 PortletPreferences portletPreferences, String data)
297 throws PortletDataException {
298
299 WikiCacheThreadLocal.setClearCache(false);
300
301 try {
302 return super.importData(
303 portletDataContext, portletId, portletPreferences, data);
304 }
305 finally {
306 WikiCacheThreadLocal.setClearCache(true);
307 }
308 }
309
310 protected static void exportNode(
311 PortletDataContext portletDataContext, Element nodesElement,
312 long nodeId)
313 throws Exception {
314
315 if (!portletDataContext.hasDateRange()) {
316 return;
317 }
318
319 WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
320
321 String path = getNodePath(portletDataContext, node);
322
323 if (!portletDataContext.isPathNotProcessed(path)) {
324 return;
325 }
326
327 Element nodeElement = nodesElement.addElement("node");
328
329 portletDataContext.addClassedModel(nodeElement, path, node, _NAMESPACE);
330 }
331
332 protected static void exportPage(
333 PortletDataContext portletDataContext, Element nodesElement,
334 Element pagesElement, Element dlFileEntryTypesElement,
335 Element dlFoldersElement, Element dlFileEntriesElement,
336 Element dlFileRanksElement, Element dlRepositoriesElement,
337 Element dlRepositoryEntriesElement, WikiPage page,
338 boolean checkDateRange)
339 throws Exception {
340
341 if (!portletDataContext.isWithinDateRange(page.getModifiedDate())) {
342 return;
343 }
344
345 String path = getPagePath(portletDataContext, page);
346
347
348
349
350 page = (WikiPage)page.clone();
351
352 Element pageElement = (Element)pagesElement.selectSingleNode(
353 "
354
355 if (portletDataContext.isPathNotProcessed(path)) {
356 if (pageElement == null) {
357 pageElement = pagesElement.addElement("page");
358 }
359
360 String content =
361 JournalPortletDataHandlerImpl.exportReferencedContent(
362 portletDataContext, dlFileEntryTypesElement,
363 dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
364 dlRepositoriesElement, dlRepositoryEntriesElement,
365 pageElement, page.getContent());
366
367 page.setContent(content);
368
369 String imagePath = getPageImagePath(portletDataContext, page);
370
371 pageElement.addAttribute("image-path", imagePath);
372
373 if (portletDataContext.getBooleanParameter(
374 _NAMESPACE, "attachments") &&
375 page.isHead()) {
376
377 String[] attachmentsFiles = page.getAttachmentsFiles();
378
379 for (int i = 0; i < attachmentsFiles.length; i++) {
380 String attachment = attachmentsFiles[i];
381
382 Element attachmentElement = pageElement.addElement(
383 "attachment");
384
385 int pos = attachment.lastIndexOf(StringPool.SLASH);
386
387 String name = attachment.substring(pos + 1);
388
389 attachmentElement.addAttribute("name", name);
390
391 String binPath = getPageAttachementBinPath(
392 portletDataContext, page, i);
393
394 attachmentElement.addAttribute("bin-path", binPath);
395
396 byte[] bytes = DLStoreUtil.getFileAsBytes(
397 portletDataContext.getCompanyId(),
398 CompanyConstants.SYSTEM, attachment);
399
400 portletDataContext.addZipEntry(binPath, bytes);
401 }
402
403 page.setAttachmentsDir(page.getAttachmentsDir());
404 }
405
406 portletDataContext.addClassedModel(
407 pageElement, path, page, _NAMESPACE);
408 }
409
410 exportNode(portletDataContext, nodesElement, page.getNodeId());
411 }
412
413 protected static String getNodeName(
414 PortletDataContext portletDataContext, WikiNode node, String name,
415 int count)
416 throws Exception {
417
418 WikiNode existingNode = WikiNodeUtil.fetchByG_N(
419 portletDataContext.getScopeGroupId(), name);
420
421 if (existingNode == null) {
422 return name;
423 }
424
425 String nodeName = node.getName();
426
427 return getNodeName(
428 portletDataContext, node,
429 nodeName.concat(StringPool.SPACE).concat(String.valueOf(count)),
430 ++count);
431 }
432
433 protected static String getNodePath(
434 PortletDataContext portletDataContext, WikiNode node) {
435
436 StringBundler sb = new StringBundler(4);
437
438 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
439 sb.append("/nodes/");
440 sb.append(node.getNodeId());
441 sb.append(".xml");
442
443 return sb.toString();
444 }
445
446 protected static String getPageAttachementBinPath(
447 PortletDataContext portletDataContext, WikiPage page, int count) {
448
449 StringBundler sb = new StringBundler(6);
450
451 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
452 sb.append("/bin/");
453 sb.append(page.getPageId());
454 sb.append(StringPool.SLASH);
455 sb.append("attachement");
456 sb.append(count);
457
458 return sb.toString();
459 }
460
461 protected static String getPageImagePath(
462 PortletDataContext portletDataContext, WikiPage page)
463 throws Exception {
464
465 StringBundler sb = new StringBundler(6);
466
467 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
468 sb.append("/page/");
469 sb.append(page.getUuid());
470 sb.append(StringPool.SLASH);
471 sb.append(page.getVersion());
472 sb.append(StringPool.SLASH);
473
474 return sb.toString();
475 }
476
477 protected static String getPagePath(
478 PortletDataContext portletDataContext, WikiPage page) {
479
480 StringBundler sb = new StringBundler(4);
481
482 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
483 sb.append("/pages/");
484 sb.append(page.getPageId());
485 sb.append(".xml");
486
487 return sb.toString();
488 }
489
490 @Override
491 protected PortletPreferences doDeleteData(
492 PortletDataContext portletDataContext, String portletId,
493 PortletPreferences portletPreferences)
494 throws Exception {
495
496 if (!portletDataContext.addPrimaryKey(
497 WikiPortletDataHandlerImpl.class, "deleteData")) {
498
499 WikiNodeLocalServiceUtil.deleteNodes(
500 portletDataContext.getScopeGroupId());
501 }
502
503 return null;
504 }
505
506 @Override
507 protected String doExportData(
508 PortletDataContext portletDataContext, String portletId,
509 PortletPreferences portletPreferences)
510 throws Exception {
511
512 portletDataContext.addPermissions(
513 "com.liferay.portlet.wiki", portletDataContext.getScopeGroupId());
514
515 Document document = SAXReaderUtil.createDocument();
516
517 Element rootElement = document.addElement("wiki-data");
518
519 rootElement.addAttribute(
520 "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
521
522 Element nodesElement = rootElement.addElement("nodes");
523 Element pagesElement = rootElement.addElement("pages");
524
525 List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
526 portletDataContext.getScopeGroupId());
527
528 for (WikiNode node : nodes) {
529 exportNode(portletDataContext, nodesElement, pagesElement, node);
530 }
531
532 return document.formattedString();
533 }
534
535 @Override
536 protected PortletPreferences doImportData(
537 PortletDataContext portletDataContext, String portletId,
538 PortletPreferences portletPreferences, String data)
539 throws Exception {
540
541 portletDataContext.importPermissions(
542 "com.liferay.portlet.wiki", portletDataContext.getSourceGroupId(),
543 portletDataContext.getScopeGroupId());
544
545 Document document = SAXReaderUtil.read(data);
546
547 Element rootElement = document.getRootElement();
548
549 Element nodesElement = rootElement.element("nodes");
550
551 for (Element nodeElement : nodesElement.elements("node")) {
552 String path = nodeElement.attributeValue("path");
553
554 if (!portletDataContext.isPathNotProcessed(path)) {
555 continue;
556 }
557
558 WikiNode node = (WikiNode)portletDataContext.getZipEntryAsObject(
559 path);
560
561 importNode(portletDataContext, node);
562 }
563
564 Element pagesElement = rootElement.element("pages");
565
566 JournalPortletDataHandlerImpl.importReferencedData(
567 portletDataContext, pagesElement);
568
569 for (Element pageElement : pagesElement.elements("page")) {
570 String path = pageElement.attributeValue("path");
571
572 if (!portletDataContext.isPathNotProcessed(path)) {
573 continue;
574 }
575
576 WikiPage page = (WikiPage)portletDataContext.getZipEntryAsObject(
577 path);
578
579 importPage(portletDataContext, pageElement, page);
580 }
581
582 Map<Long, Long> nodeIds =
583 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
584 WikiNode.class);
585
586 for (long nodeId : nodeIds.values()) {
587 WikiCacheUtil.clearCache(nodeId);
588 }
589
590 return null;
591 }
592
593 private static final String _NAMESPACE = "wiki";
594
595 private static PortletDataHandlerControl[] _metadataControls =
596 new PortletDataHandlerControl[] {
597 new PortletDataHandlerBoolean(_NAMESPACE, "attachments"),
598 new PortletDataHandlerBoolean(_NAMESPACE, "categories"),
599 new PortletDataHandlerBoolean(_NAMESPACE, "comments"),
600 new PortletDataHandlerBoolean(_NAMESPACE, "ratings"),
601 new PortletDataHandlerBoolean(_NAMESPACE, "tags")
602 };
603
604 private static PortletDataHandlerBoolean _nodesAndPages =
605 new PortletDataHandlerBoolean(
606 _NAMESPACE, "wikis-and-pages", true, true);
607
608 }