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
087 List<WikiPage> pages = WikiPageUtil.findByN_S(
088 node.getNodeId(), WorkflowConstants.STATUS_APPROVED,
089 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
090 new PageVersionComparator(true));
091
092 for (WikiPage page : pages) {
093 exportPage(
094 portletDataContext, nodesElement, pagesElement,
095 dlFileEntryTypesElement, dlFoldersElement, dlFileEntriesElement,
096 dlFileRanksElement, page, true);
097 }
098 }
099
100 public static PortletDataHandlerControl[] getMetadataControls() {
101 return _metadataControls;
102 }
103
104 public static void importNode(
105 PortletDataContext portletDataContext, WikiNode node)
106 throws Exception {
107
108 long userId = portletDataContext.getUserId(node.getUserUuid());
109
110 ServiceContext serviceContext = new ServiceContext();
111
112 serviceContext.setAddGroupPermissions(true);
113 serviceContext.setAddGuestPermissions(true);
114 serviceContext.setCreateDate(node.getCreateDate());
115 serviceContext.setModifiedDate(node.getModifiedDate());
116 serviceContext.setScopeGroupId(portletDataContext.getScopeGroupId());
117
118 WikiNode importedNode = null;
119
120 if (portletDataContext.isDataStrategyMirror()) {
121 WikiNode existingNode = WikiNodeUtil.fetchByUUID_G(
122 node.getUuid(), portletDataContext.getScopeGroupId());
123
124 String initialNodeName = PropsValues.WIKI_INITIAL_NODE_NAME;
125
126 if ((existingNode == null) &&
127 initialNodeName.equals(node.getName())) {
128
129 try {
130 WikiNodeUtil.removeByG_N(
131 portletDataContext.getScopeGroupId(), node.getName());
132 }
133 catch (NoSuchNodeException nsne) {
134 }
135 }
136
137 if (existingNode == null) {
138 serviceContext.setUuid(node.getUuid());
139
140 importedNode = WikiNodeLocalServiceUtil.addNode(
141 userId, node.getName(), node.getDescription(),
142 serviceContext);
143 }
144 else {
145 importedNode = WikiNodeLocalServiceUtil.updateNode(
146 existingNode.getNodeId(), node.getName(),
147 node.getDescription(), serviceContext);
148 }
149 }
150 else {
151 String initialNodeName = PropsValues.WIKI_INITIAL_NODE_NAME;
152
153 if (initialNodeName.equals(node.getName())) {
154 try {
155 WikiNodeUtil.removeByG_N(
156 portletDataContext.getScopeGroupId(), node.getName());
157 }
158 catch (NoSuchNodeException nsne) {
159 }
160 }
161
162 String nodeName = getNodeName(
163 portletDataContext, node, node.getName(), 2);
164
165 importedNode = WikiNodeLocalServiceUtil.addNode(
166 userId, nodeName, node.getDescription(), serviceContext);
167 }
168
169 portletDataContext.importClassedModel(node, importedNode, _NAMESPACE);
170 }
171
172 public static void importPage(
173 PortletDataContext portletDataContext, Element pageElement,
174 WikiPage page)
175 throws Exception {
176
177 long userId = portletDataContext.getUserId(page.getUserUuid());
178
179 Map<Long, Long> nodePKs =
180 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
181 WikiNode.class);
182
183 long nodeId = MapUtil.getLong(
184 nodePKs, page.getNodeId(), page.getNodeId());
185
186 String content = JournalPortletDataHandlerImpl.importReferencedContent(
187 portletDataContext, pageElement, page.getContent());
188
189 page.setContent(content);
190
191 ServiceContext serviceContext = portletDataContext.createServiceContext(
192 pageElement, page, _NAMESPACE);
193
194 if (page.getStatus() != WorkflowConstants.STATUS_APPROVED) {
195 serviceContext.setWorkflowAction(
196 WorkflowConstants.ACTION_SAVE_DRAFT);
197 }
198
199 WikiPage importedPage = null;
200
201 WikiPage existingPage = WikiPageUtil.fetchByUUID_G(
202 page.getUuid(), portletDataContext.getScopeGroupId());
203
204 if (existingPage == null) {
205 try {
206 existingPage = WikiPageLocalServiceUtil.getPage(
207 nodeId, page.getTitle());
208 }
209 catch (NoSuchPageException nspe) {
210 }
211 }
212
213 if (existingPage == null) {
214 serviceContext.setUuid(page.getUuid());
215
216 importedPage = WikiPageLocalServiceUtil.addPage(
217 userId, nodeId, page.getTitle(), page.getVersion(),
218 page.getContent(), page.getSummary(), page.isMinorEdit(),
219 page.getFormat(), page.getHead(), page.getParentTitle(),
220 page.getRedirectTitle(), serviceContext);
221 }
222 else {
223 importedPage = WikiPageLocalServiceUtil.updatePage(
224 userId, nodeId, existingPage.getTitle(), 0, page.getContent(),
225 page.getSummary(), page.isMinorEdit(), page.getFormat(),
226 page.getParentTitle(), page.getRedirectTitle(), serviceContext);
227 }
228
229 if (portletDataContext.getBooleanParameter(_NAMESPACE, "attachments") &&
230 page.isHead()) {
231
232 for (Element attachmentElement :
233 pageElement.elements("attachment")) {
234
235 String name = attachmentElement.attributeValue("name");
236 String binPath = attachmentElement.attributeValue("bin-path");
237
238 InputStream inputStream = null;
239
240 try {
241 inputStream = portletDataContext.getZipEntryAsInputStream(
242 binPath);
243
244 WikiPageLocalServiceUtil.addPageAttachment(
245 importedPage.getCompanyId(),
246 importedPage.getAttachmentsDir(),
247 importedPage.getModifiedDate(), name, inputStream);
248 }
249 finally {
250 StreamUtil.cleanUp(inputStream);
251 }
252 }
253 }
254
255 portletDataContext.importClassedModel(page, importedPage, _NAMESPACE);
256 }
257
258 @Override
259 public PortletDataHandlerControl[] getExportControls() {
260 return new PortletDataHandlerControl[] {
261 _nodesAndPages
262 };
263 }
264
265 @Override
266 public PortletDataHandlerControl[] getExportMetadataControls() {
267 return new PortletDataHandlerControl[] {
268 new PortletDataHandlerBoolean(
269 _NAMESPACE, "wiki-pages", true, _metadataControls)
270 };
271 }
272
273 @Override
274 public PortletDataHandlerControl[] getImportControls() {
275 return new PortletDataHandlerControl[] {
276 _nodesAndPages
277 };
278 }
279
280 @Override
281 public PortletDataHandlerControl[] getImportMetadataControls() {
282 return new PortletDataHandlerControl[] {
283 new PortletDataHandlerBoolean(
284 _NAMESPACE, "wiki-pages", true, _metadataControls)
285 };
286 }
287
288 @Override
289 public PortletPreferences importData(
290 PortletDataContext portletDataContext, String portletId,
291 PortletPreferences portletPreferences, String data)
292 throws PortletDataException {
293
294 WikiCacheThreadLocal.setClearCache(false);
295
296 try {
297 return super.importData(
298 portletDataContext, portletId, portletPreferences, data);
299 }
300 finally {
301 WikiCacheThreadLocal.setClearCache(true);
302 }
303 }
304
305 protected static void exportNode(
306 PortletDataContext portletDataContext, Element nodesElement,
307 long nodeId)
308 throws Exception {
309
310 if (!portletDataContext.hasDateRange()) {
311 return;
312 }
313
314 WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
315
316 String path = getNodePath(portletDataContext, node);
317
318 if (!portletDataContext.isPathNotProcessed(path)) {
319 return;
320 }
321
322 Element nodeElement = nodesElement.addElement("node");
323
324 portletDataContext.addClassedModel(nodeElement, path, node, _NAMESPACE);
325 }
326
327 protected static void exportPage(
328 PortletDataContext portletDataContext, Element nodesElement,
329 Element pagesElement, Element dlFileEntryTypesElement,
330 Element dlFoldersElement, Element dlFileEntriesElement,
331 Element dlFileRanksElement, WikiPage page, boolean checkDateRange)
332 throws Exception {
333
334 if (!portletDataContext.isWithinDateRange(page.getModifiedDate())) {
335 return;
336 }
337
338 String path = getPagePath(portletDataContext, page);
339
340
341
342
343 page = (WikiPage)page.clone();
344
345 Element pageElement = (Element)pagesElement.selectSingleNode(
346 "
347
348 if (portletDataContext.isPathNotProcessed(path)) {
349 if (pageElement == null) {
350 pageElement = pagesElement.addElement("page");
351 }
352
353 String content =
354 JournalPortletDataHandlerImpl.exportReferencedContent(
355 portletDataContext, dlFileEntryTypesElement,
356 dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
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 List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
518 portletDataContext.getScopeGroupId());
519
520 for (WikiNode node : nodes) {
521 exportNode(portletDataContext, nodesElement, pagesElement, node);
522 }
523
524 return document.formattedString();
525 }
526
527 @Override
528 protected PortletPreferences doImportData(
529 PortletDataContext portletDataContext, String portletId,
530 PortletPreferences portletPreferences, String data)
531 throws Exception {
532
533 portletDataContext.importPermissions(
534 "com.liferay.portlet.wiki", portletDataContext.getSourceGroupId(),
535 portletDataContext.getScopeGroupId());
536
537 Document document = SAXReaderUtil.read(data);
538
539 Element rootElement = document.getRootElement();
540
541 Element nodesElement = rootElement.element("nodes");
542
543 for (Element nodeElement : nodesElement.elements("node")) {
544 String path = nodeElement.attributeValue("path");
545
546 if (!portletDataContext.isPathNotProcessed(path)) {
547 continue;
548 }
549
550 WikiNode node = (WikiNode)portletDataContext.getZipEntryAsObject(
551 path);
552
553 importNode(portletDataContext, node);
554 }
555
556 Element pagesElement = rootElement.element("pages");
557
558 JournalPortletDataHandlerImpl.importReferencedData(
559 portletDataContext, pagesElement);
560
561 for (Element pageElement : pagesElement.elements("page")) {
562 String path = pageElement.attributeValue("path");
563
564 if (!portletDataContext.isPathNotProcessed(path)) {
565 continue;
566 }
567
568 WikiPage page = (WikiPage)portletDataContext.getZipEntryAsObject(
569 path);
570
571 importPage(portletDataContext, pageElement, page);
572 }
573
574 Map<Long, Long> nodePKs =
575 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
576 WikiNode.class);
577
578 for (long nodeId : nodePKs.values()) {
579 WikiCacheUtil.clearCache(nodeId);
580 }
581
582 return null;
583 }
584
585 private static final String _NAMESPACE = "wiki";
586
587 private static PortletDataHandlerControl[] _metadataControls =
588 new PortletDataHandlerControl[] {
589 new PortletDataHandlerBoolean(_NAMESPACE, "attachments"),
590 new PortletDataHandlerBoolean(_NAMESPACE, "categories"),
591 new PortletDataHandlerBoolean(_NAMESPACE, "comments"),
592 new PortletDataHandlerBoolean(_NAMESPACE, "ratings"),
593 new PortletDataHandlerBoolean(_NAMESPACE, "tags")
594 };
595
596 private static PortletDataHandlerBoolean _nodesAndPages =
597 new PortletDataHandlerBoolean(
598 _NAMESPACE, "wikis-and-pages", true, true);
599
600 }