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