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