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.MimeTypesUtil;
026 import com.liferay.portal.kernel.util.StreamUtil;
027 import com.liferay.portal.kernel.util.StringBundler;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.workflow.WorkflowConstants;
030 import com.liferay.portal.kernel.xml.Document;
031 import com.liferay.portal.kernel.xml.Element;
032 import com.liferay.portal.kernel.xml.SAXReaderUtil;
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.dynamicdatamapping.lar.DDMPortletDataHandler;
037 import com.liferay.portlet.journal.lar.JournalPortletDataHandler;
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 WikiPortletDataHandler extends BasePortletDataHandler {
064
065 public static final String NAMESPACE = "wiki";
066
067 public static void exportNode(
068 PortletDataContext portletDataContext, Element nodesElement,
069 Element pagesElement, WikiNode node)
070 throws Exception {
071
072 if (portletDataContext.isWithinDateRange(node.getModifiedDate())) {
073 String path = getNodePath(portletDataContext, node);
074
075 if (portletDataContext.isPathNotProcessed(path)) {
076 Element nodeElement = nodesElement.addElement("node");
077
078 portletDataContext.addClassedModel(
079 nodeElement, path, node, NAMESPACE);
080 }
081 }
082
083 Element dlFileEntryTypesElement = pagesElement.addElement(
084 "dl-file-entry-types");
085 Element dlFoldersElement = pagesElement.addElement("dl-folders");
086 Element dlFileEntriesElement = pagesElement.addElement(
087 "dl-file-entries");
088 Element dlFileRanksElement = pagesElement.addElement("dl-file-ranks");
089 Element dlRepositoriesElement = pagesElement.addElement(
090 "dl-repositories");
091 Element dlRepositoryEntriesElement = pagesElement.addElement(
092 "dl-repository-entries");
093
094 List<WikiPage> pages = WikiPageUtil.findByN_S(
095 node.getNodeId(), WorkflowConstants.STATUS_APPROVED,
096 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
097 new PageVersionComparator(true));
098
099 for (WikiPage page : pages) {
100 exportPage(
101 portletDataContext, nodesElement, pagesElement,
102 dlFileEntryTypesElement, dlFoldersElement, dlFileEntriesElement,
103 dlFileRanksElement, dlRepositoriesElement,
104 dlRepositoryEntriesElement, page, true);
105 }
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 = JournalPortletDataHandler.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 String mimeType = null;
244
245 try {
246 inputStream = portletDataContext.getZipEntryAsInputStream(
247 binPath);
248
249 mimeType = MimeTypesUtil.getContentType(inputStream, name);
250 }
251 finally {
252 StreamUtil.cleanUp(inputStream);
253 }
254
255 try {
256 inputStream = portletDataContext.getZipEntryAsInputStream(
257 binPath);
258
259 WikiPageLocalServiceUtil.addPageAttachment(
260 userId, importedPage.getNodeId(),
261 importedPage.getTitle(), name, inputStream, mimeType);
262 }
263 finally {
264 StreamUtil.cleanUp(inputStream);
265 }
266 }
267 }
268
269 portletDataContext.importClassedModel(page, importedPage, NAMESPACE);
270 }
271
272 public WikiPortletDataHandler() {
273 setExportControls(
274 new PortletDataHandlerBoolean(
275 NAMESPACE, "wikis-and-pages", true, true));
276 setExportMetadataControls(
277 new PortletDataHandlerBoolean(
278 NAMESPACE, "wiki-pages", true,
279 new PortletDataHandlerControl[] {
280 new PortletDataHandlerBoolean(NAMESPACE, "attachments"),
281 new PortletDataHandlerBoolean(NAMESPACE, "categories"),
282 new PortletDataHandlerBoolean(NAMESPACE, "comments"),
283 new PortletDataHandlerBoolean(NAMESPACE, "ratings"),
284 new PortletDataHandlerBoolean(NAMESPACE, "tags")
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, Element dlRepositoriesElement,
332 Element dlRepositoryEntriesElement, WikiPage page,
333 boolean checkDateRange)
334 throws Exception {
335
336 if (!portletDataContext.isWithinDateRange(page.getModifiedDate())) {
337 return;
338 }
339
340 String path = getPagePath(portletDataContext, page);
341
342
343
344
345 page = (WikiPage)page.clone();
346
347 Element pageElement = (Element)pagesElement.selectSingleNode(
348 "
349
350 if (portletDataContext.isPathNotProcessed(path)) {
351 if (pageElement == null) {
352 pageElement = pagesElement.addElement("page");
353 }
354
355 String content = DDMPortletDataHandler.exportReferencedContent(
356 portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
357 dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
358 dlRepositoryEntriesElement, pageElement, page.getContent());
359
360 page.setContent(content);
361
362 String imagePath = getPageImagePath(portletDataContext, page);
363
364 pageElement.addAttribute("image-path", imagePath);
365
366 if (portletDataContext.getBooleanParameter(
367 NAMESPACE, "attachments") &&
368 page.isHead()) {
369
370 int i = 0;
371
372 for (FileEntry fileEntry : page.getAttachmentsFileEntries()) {
373 Element attachmentElement = pageElement.addElement(
374 "attachment");
375
376 attachmentElement.addAttribute(
377 "name", fileEntry.getTitle());
378
379 String binPath = getPageAttachementBinPath(
380 portletDataContext, page, i++);
381
382 attachmentElement.addAttribute("bin-path", binPath);
383
384 portletDataContext.addZipEntry(
385 binPath, fileEntry.getContentStream());
386 }
387
388 page.setAttachmentsFolderId(page.getAttachmentsFolderId());
389 }
390
391 portletDataContext.addClassedModel(
392 pageElement, path, page, NAMESPACE);
393 }
394
395 exportNode(portletDataContext, nodesElement, page.getNodeId());
396 }
397
398 protected static String getNodeName(
399 PortletDataContext portletDataContext, WikiNode node, String name,
400 int count)
401 throws Exception {
402
403 WikiNode existingNode = WikiNodeUtil.fetchByG_N(
404 portletDataContext.getScopeGroupId(), name);
405
406 if (existingNode == null) {
407 return name;
408 }
409
410 String nodeName = node.getName();
411
412 return getNodeName(
413 portletDataContext, node,
414 nodeName.concat(StringPool.SPACE).concat(String.valueOf(count)),
415 ++count);
416 }
417
418 protected static String getNodePath(
419 PortletDataContext portletDataContext, WikiNode node) {
420
421 StringBundler sb = new StringBundler(4);
422
423 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
424 sb.append("/nodes/");
425 sb.append(node.getNodeId());
426 sb.append(".xml");
427
428 return sb.toString();
429 }
430
431 protected static String getPageAttachementBinPath(
432 PortletDataContext portletDataContext, WikiPage page, int count) {
433
434 StringBundler sb = new StringBundler(6);
435
436 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
437 sb.append("/bin/");
438 sb.append(page.getPageId());
439 sb.append(StringPool.SLASH);
440 sb.append("attachement");
441 sb.append(count);
442
443 return sb.toString();
444 }
445
446 protected static String getPageImagePath(
447 PortletDataContext portletDataContext, WikiPage page)
448 throws Exception {
449
450 StringBundler sb = new StringBundler(6);
451
452 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
453 sb.append("/page/");
454 sb.append(page.getUuid());
455 sb.append(StringPool.SLASH);
456 sb.append(page.getVersion());
457 sb.append(StringPool.SLASH);
458
459 return sb.toString();
460 }
461
462 protected static String getPagePath(
463 PortletDataContext portletDataContext, WikiPage page) {
464
465 StringBundler sb = new StringBundler(4);
466
467 sb.append(portletDataContext.getPortletPath(PortletKeys.WIKI));
468 sb.append("/pages/");
469 sb.append(page.getPageId());
470 sb.append(".xml");
471
472 return sb.toString();
473 }
474
475 @Override
476 protected PortletPreferences doDeleteData(
477 PortletDataContext portletDataContext, String portletId,
478 PortletPreferences portletPreferences)
479 throws Exception {
480
481 if (portletDataContext.addPrimaryKey(
482 WikiPortletDataHandler.class, "deleteData")) {
483
484 return portletPreferences;
485 }
486
487 WikiNodeLocalServiceUtil.deleteNodes(
488 portletDataContext.getScopeGroupId());
489
490 return portletPreferences;
491 }
492
493 @Override
494 protected String doExportData(
495 PortletDataContext portletDataContext, String portletId,
496 PortletPreferences portletPreferences)
497 throws Exception {
498
499 portletDataContext.addPermissions(
500 "com.liferay.portlet.wiki", portletDataContext.getScopeGroupId());
501
502 Element rootElement = addExportRootElement();
503
504 rootElement.addAttribute(
505 "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
506
507 Element nodesElement = rootElement.addElement("nodes");
508 Element pagesElement = rootElement.addElement("pages");
509
510 List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
511 portletDataContext.getScopeGroupId());
512
513 for (WikiNode node : nodes) {
514 exportNode(portletDataContext, nodesElement, pagesElement, node);
515 }
516
517 return rootElement.formattedString();
518 }
519
520 @Override
521 protected PortletPreferences doImportData(
522 PortletDataContext portletDataContext, String portletId,
523 PortletPreferences portletPreferences, String data)
524 throws Exception {
525
526 portletDataContext.importPermissions(
527 "com.liferay.portlet.wiki", portletDataContext.getSourceGroupId(),
528 portletDataContext.getScopeGroupId());
529
530 Document document = SAXReaderUtil.read(data);
531
532 Element rootElement = document.getRootElement();
533
534 Element nodesElement = rootElement.element("nodes");
535
536 for (Element nodeElement : nodesElement.elements("node")) {
537 String path = nodeElement.attributeValue("path");
538
539 if (!portletDataContext.isPathNotProcessed(path)) {
540 continue;
541 }
542
543 WikiNode node = (WikiNode)portletDataContext.getZipEntryAsObject(
544 path);
545
546 importNode(portletDataContext, node);
547 }
548
549 Element pagesElement = rootElement.element("pages");
550
551 JournalPortletDataHandler.importReferencedData(
552 portletDataContext, pagesElement);
553
554 for (Element pageElement : pagesElement.elements("page")) {
555 String path = pageElement.attributeValue("path");
556
557 if (!portletDataContext.isPathNotProcessed(path)) {
558 continue;
559 }
560
561 WikiPage page = (WikiPage)portletDataContext.getZipEntryAsObject(
562 path);
563
564 importPage(portletDataContext, pageElement, page);
565 }
566
567 Map<Long, Long> nodeIds =
568 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
569 WikiNode.class);
570
571 for (long nodeId : nodeIds.values()) {
572 WikiCacheUtil.clearCache(nodeId);
573 }
574
575 return null;
576 }
577
578 }