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