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.CharPool;
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.model.CompanyConstants;
033 import com.liferay.portal.service.ServiceContext;
034 import com.liferay.portal.util.PortletKeys;
035 import com.liferay.portal.util.PropsValues;
036 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
037 import com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl;
038 import com.liferay.portlet.wiki.NoSuchNodeException;
039 import com.liferay.portlet.wiki.NoSuchPageException;
040 import com.liferay.portlet.wiki.model.WikiNode;
041 import com.liferay.portlet.wiki.model.WikiPage;
042 import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
043 import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
044 import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
045 import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
046 import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
047 import com.liferay.portlet.wiki.util.WikiCacheUtil;
048 import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
049
050 import java.io.InputStream;
051
052 import java.util.List;
053 import java.util.Map;
054
055 import javax.portlet.PortletPreferences;
056
057
063 public class WikiPortletDataHandlerImpl extends BasePortletDataHandler {
064
065 public static void exportNode(
066 PortletDataContext portletDataContext, Element nodesElement,
067 Element pagesElement, WikiNode node)
068 throws Exception {
069
070 if (portletDataContext.isWithinDateRange(node.getModifiedDate())) {
071 String path = getNodePath(portletDataContext, node);
072
073 if (portletDataContext.isPathNotProcessed(path)) {
074 Element nodeElement = nodesElement.addElement("node");
075
076 portletDataContext.addClassedModel(
077 nodeElement, path, node, _NAMESPACE);
078 }
079 }
080
081 Element dlFileEntryTypesElement = pagesElement.addElement(
082 "dl-file-entry-types");
083 Element dlFoldersElement = pagesElement.addElement("dl-folders");
084 Element dlFileEntriesElement = pagesElement.addElement(
085 "dl-file-entries");
086 Element dlFileRanksElement = pagesElement.addElement("dl-file-ranks");
087 Element igFoldersElement = pagesElement.addElement("ig-folders");
088 Element igImagesElement = pagesElement.addElement("ig-images");
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, igFoldersElement, igImagesElement, page,
100 true);
101 }
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, _attachments, _categories, _comments, _ratings,
262 _tags
263 };
264 }
265
266 @Override
267 public PortletDataHandlerControl[] getImportControls() {
268 return new PortletDataHandlerControl[] {
269 _nodesAndPages, _attachments, _categories, _comments, _ratings,
270 _tags
271 };
272 }
273
274 @Override
275 public PortletPreferences importData(
276 PortletDataContext portletDataContext, String portletId,
277 PortletPreferences portletPreferences, String data)
278 throws PortletDataException {
279
280 WikiCacheThreadLocal.setClearCache(false);
281
282 try {
283 return super.importData(
284 portletDataContext, portletId, portletPreferences, data);
285 }
286 finally {
287 WikiCacheThreadLocal.setClearCache(true);
288 }
289 }
290
291 protected static void exportNode(
292 PortletDataContext portletDataContext, Element nodesElement,
293 long nodeId)
294 throws Exception {
295
296 if (!portletDataContext.hasDateRange()) {
297 return;
298 }
299
300 WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
301
302 String path = getNodePath(portletDataContext, node);
303
304 if (!portletDataContext.isPathNotProcessed(path)) {
305 return;
306 }
307
308 Element nodeElement = nodesElement.addElement("node");
309
310 portletDataContext.addClassedModel(nodeElement, path, node, _NAMESPACE);
311 }
312
313 protected static void exportPage(
314 PortletDataContext portletDataContext, Element nodesElement,
315 Element pagesElement, Element dlFileEntryTypesElement,
316 Element dlFoldersElement, Element dlFileEntriesElement,
317 Element dlFileRanksElement, Element igFoldersElement,
318 Element igImagesElement, WikiPage page, boolean checkDateRange)
319 throws Exception {
320
321 if (!portletDataContext.isWithinDateRange(page.getModifiedDate())) {
322 return;
323 }
324
325 String path = getPagePath(portletDataContext, page);
326
327
328
329
330 page = (WikiPage)page.clone();
331
332 Element pageElement = (Element)pagesElement.selectSingleNode(
333 "
334
335 if (portletDataContext.isPathNotProcessed(path)) {
336 if (pageElement == null) {
337 pageElement = pagesElement.addElement("page");
338 }
339
340 String content =
341 JournalPortletDataHandlerImpl.exportReferencedContent(
342 portletDataContext, dlFileEntryTypesElement,
343 dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
344 igFoldersElement, igImagesElement, pageElement,
345 page.getContent(), checkDateRange);
346
347 page.setContent(content);
348
349 String imagePath = getPageImagePath(portletDataContext, page);
350
351 pageElement.addAttribute("image-path", imagePath);
352
353 if (portletDataContext.getBooleanParameter(
354 _NAMESPACE, "attachments") &&
355 page.isHead()) {
356
357 for (String attachment : page.getAttachmentsFiles()) {
358 int pos = attachment.lastIndexOf(CharPool.SLASH);
359
360 String name = attachment.substring(pos + 1);
361 String binPath = getPageAttachementBinPath(
362 portletDataContext, page, name);
363
364 Element attachmentEl = pageElement.addElement("attachment");
365
366 attachmentEl.addAttribute("name", name);
367 attachmentEl.addAttribute("bin-path", binPath);
368
369 byte[] bytes = DLStoreUtil.getFileAsBytes(
370 portletDataContext.getCompanyId(),
371 CompanyConstants.SYSTEM, attachment);
372
373 portletDataContext.addZipEntry(binPath, bytes);
374 }
375
376 page.setAttachmentsDir(page.getAttachmentsDir());
377 }
378
379 portletDataContext.addClassedModel(
380 pageElement, path, page, _NAMESPACE);
381 }
382
383 exportNode(portletDataContext, nodesElement, page.getNodeId());
384 }
385
386 protected static String getNodeName(
387 PortletDataContext portletDataContext, WikiNode node, String name,
388 int count)
389 throws Exception {
390
391 WikiNode existingNode = WikiNodeUtil.fetchByG_N(
392 portletDataContext.getScopeGroupId(), name);
393
394 if (existingNode == null) {
395 return name;
396 }
397
398 String nodeName = node.getName();
399
400 return getNodeName(
401 portletDataContext, node,
402 nodeName.concat(StringPool.SPACE).concat(String.valueOf(count)),
403 ++count);
404 }
405
406 protected static String getNodePath(
407 PortletDataContext portletDataContext, WikiNode node) {
408
409 StringBundler sb = new StringBundler(4);
410
411 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
412 sb.append("/nodes/");
413 sb.append(node.getNodeId());
414 sb.append(".xml");
415
416 return sb.toString();
417 }
418
419 protected static String getPageAttachementBinPath(
420 PortletDataContext portletDataContext, WikiPage page,
421 String attachment) {
422
423 StringBundler sb = new StringBundler(5);
424
425 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
426 sb.append("/bin/");
427 sb.append(page.getPageId());
428 sb.append(StringPool.SLASH);
429 sb.append(attachment);
430
431 return sb.toString();
432 }
433
434 protected static String getPageImagePath(
435 PortletDataContext portletDataContext, WikiPage page)
436 throws Exception {
437
438 StringBundler sb = new StringBundler(6);
439
440 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
441 sb.append("/page/");
442 sb.append(page.getUuid());
443 sb.append(StringPool.SLASH);
444 sb.append(page.getVersion());
445 sb.append(StringPool.SLASH);
446
447 return sb.toString();
448 }
449
450 protected static String getPagePath(
451 PortletDataContext portletDataContext, WikiPage page) {
452
453 StringBundler sb = new StringBundler(4);
454
455 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
456 sb.append("/pages/");
457 sb.append(page.getPageId());
458 sb.append(".xml");
459
460 return sb.toString();
461 }
462
463 @Override
464 protected PortletPreferences doDeleteData(
465 PortletDataContext portletDataContext, String portletId,
466 PortletPreferences portletPreferences)
467 throws Exception {
468
469 if (!portletDataContext.addPrimaryKey(
470 WikiPortletDataHandlerImpl.class, "deleteData")) {
471
472 WikiNodeLocalServiceUtil.deleteNodes(
473 portletDataContext.getScopeGroupId());
474 }
475
476 return null;
477 }
478
479 @Override
480 protected String doExportData(
481 PortletDataContext portletDataContext, String portletId,
482 PortletPreferences portletPreferences)
483 throws Exception {
484
485 portletDataContext.addPermissions(
486 "com.liferay.portlet.wiki", portletDataContext.getScopeGroupId());
487
488 Document document = SAXReaderUtil.createDocument();
489
490 Element rootElement = document.addElement("wiki-data");
491
492 rootElement.addAttribute(
493 "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
494
495 Element nodesElement = rootElement.addElement("nodes");
496 Element pagesElement = rootElement.addElement("pages");
497
498 List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
499 portletDataContext.getScopeGroupId());
500
501 for (WikiNode node : nodes) {
502 exportNode(portletDataContext, nodesElement, pagesElement, node);
503 }
504
505 return document.formattedString();
506 }
507
508 @Override
509 protected PortletPreferences doImportData(
510 PortletDataContext portletDataContext, String portletId,
511 PortletPreferences portletPreferences, String data)
512 throws Exception {
513
514 portletDataContext.importPermissions(
515 "com.liferay.portlet.wiki", portletDataContext.getSourceGroupId(),
516 portletDataContext.getScopeGroupId());
517
518 Document document = SAXReaderUtil.read(data);
519
520 Element rootElement = document.getRootElement();
521
522 Element nodesElement = rootElement.element("nodes");
523
524 for (Element nodeElement : nodesElement.elements("node")) {
525 String path = nodeElement.attributeValue("path");
526
527 if (!portletDataContext.isPathNotProcessed(path)) {
528 continue;
529 }
530
531 WikiNode node = (WikiNode)portletDataContext.getZipEntryAsObject(
532 path);
533
534 importNode(portletDataContext, node);
535 }
536
537 Element pagesElement = rootElement.element("pages");
538
539 JournalPortletDataHandlerImpl.importReferencedData(
540 portletDataContext, pagesElement);
541
542 for (Element pageElement : pagesElement.elements("page")) {
543 String path = pageElement.attributeValue("path");
544
545 if (!portletDataContext.isPathNotProcessed(path)) {
546 continue;
547 }
548
549 WikiPage page = (WikiPage)portletDataContext.getZipEntryAsObject(
550 path);
551
552 importPage(portletDataContext, pageElement, page);
553 }
554
555 Map<Long, Long> nodePKs =
556 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
557 WikiNode.class);
558
559 for (long nodeId : nodePKs.values()) {
560 WikiCacheUtil.clearCache(nodeId);
561 }
562
563 return null;
564 }
565
566 private static final String _NAMESPACE = "wiki";
567
568 private static PortletDataHandlerBoolean _attachments =
569 new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
570
571 private static PortletDataHandlerBoolean _categories =
572 new PortletDataHandlerBoolean(_NAMESPACE, "categories");
573
574 private static PortletDataHandlerBoolean _comments =
575 new PortletDataHandlerBoolean(_NAMESPACE, "comments");
576
577 private static PortletDataHandlerBoolean _nodesAndPages =
578 new PortletDataHandlerBoolean(
579 _NAMESPACE, "wikis-and-pages", true, true);
580
581 private static PortletDataHandlerBoolean _ratings =
582 new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
583
584 private static PortletDataHandlerBoolean _tags =
585 new PortletDataHandlerBoolean(_NAMESPACE, "tags");
586
587 }