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