1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.wiki.lar;
16  
17  import com.liferay.documentlibrary.service.DLServiceUtil;
18  import com.liferay.portal.kernel.dao.orm.QueryUtil;
19  import com.liferay.portal.kernel.exception.PortalException;
20  import com.liferay.portal.kernel.exception.SystemException;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.util.MapUtil;
24  import com.liferay.portal.kernel.util.ObjectValuePair;
25  import com.liferay.portal.kernel.util.PropsKeys;
26  import com.liferay.portal.kernel.util.StringBundler;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.xml.Document;
29  import com.liferay.portal.kernel.xml.Element;
30  import com.liferay.portal.kernel.xml.SAXReaderUtil;
31  import com.liferay.portal.lar.BasePortletDataHandler;
32  import com.liferay.portal.lar.PortletDataContext;
33  import com.liferay.portal.lar.PortletDataException;
34  import com.liferay.portal.lar.PortletDataHandlerBoolean;
35  import com.liferay.portal.lar.PortletDataHandlerControl;
36  import com.liferay.portal.lar.PortletDataHandlerKeys;
37  import com.liferay.portal.model.CompanyConstants;
38  import com.liferay.portal.service.ServiceContext;
39  import com.liferay.portal.util.PortletKeys;
40  import com.liferay.portal.util.PropsUtil;
41  import com.liferay.portlet.wiki.NoSuchNodeException;
42  import com.liferay.portlet.wiki.NoSuchPageException;
43  import com.liferay.portlet.wiki.model.WikiNode;
44  import com.liferay.portlet.wiki.model.WikiPage;
45  import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
46  import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
47  import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
48  import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
49  import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
50  
51  import java.util.ArrayList;
52  import java.util.List;
53  import java.util.Map;
54  
55  import javax.portlet.PortletPreferences;
56  
57  /**
58   * <a href="WikiPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
59   *
60   * @author Bruno Farache
61   * @author Jorge Ferrer
62   * @author Marcellus Tavares
63   */
64  public class WikiPortletDataHandlerImpl extends BasePortletDataHandler {
65  
66      public static void exportNode(
67              PortletDataContext context, Element nodesEl, Element pagesEl,
68              WikiNode node)
69          throws PortalException, SystemException {
70  
71          if (context.isWithinDateRange(node.getModifiedDate())) {
72              String path = getNodePath(context, node);
73  
74              if (context.isPathNotProcessed(path)) {
75                  Element nodeEl = nodesEl.addElement("node");
76  
77                  nodeEl.addAttribute("path", path);
78  
79                  node.setUserUuid(node.getUserUuid());
80  
81                  context.addPermissions(WikiNode.class, node.getNodeId());
82  
83                  context.addZipEntry(path, node);
84              }
85          }
86  
87          List<WikiPage> nodePages = WikiPageUtil.findByNodeId(
88              node.getNodeId(), QueryUtil.ALL_POS, QueryUtil.ALL_POS,
89              new PageCreateDateComparator(true));
90  
91          for (WikiPage page : nodePages) {
92              exportPage(context, nodesEl, pagesEl, page);
93          }
94      }
95  
96      public static void importNode(
97              PortletDataContext context, Map<Long, Long> nodePKs, WikiNode node)
98          throws Exception {
99  
100         long userId = context.getUserId(node.getUserUuid());
101 
102         ServiceContext serviceContext = new ServiceContext();
103 
104         serviceContext.setAddCommunityPermissions(true);
105         serviceContext.setAddGuestPermissions(true);
106         serviceContext.setCreateDate(node.getCreateDate());
107         serviceContext.setModifiedDate(node.getModifiedDate());
108         serviceContext.setScopeGroupId(context.getGroupId());
109 
110         WikiNode importedNode = null;
111 
112         if (context.getDataStrategy().equals(
113                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
114 
115             WikiNode existingNode = WikiNodeUtil.fetchByUUID_G(
116                 node.getUuid(), context.getGroupId());
117 
118             String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
119 
120             if ((existingNode == null) && node.getName().equals(nodeName)) {
121                 try {
122                     WikiNodeUtil.removeByG_N(
123                         context.getGroupId(), node.getName());
124                 }
125                 catch (NoSuchNodeException nsne) {
126                 }
127             }
128 
129             if (existingNode == null) {
130                 importedNode = WikiNodeLocalServiceUtil.addNode(
131                     node.getUuid(), userId, node.getName(),
132                     node.getDescription(), serviceContext);
133             }
134             else {
135                 importedNode = WikiNodeLocalServiceUtil.updateNode(
136                     existingNode.getNodeId(), node.getName(),
137                     node.getDescription(), serviceContext);
138             }
139         }
140         else {
141             String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
142 
143             if (node.getName().equals(nodeName)) {
144                 try {
145                     WikiNodeUtil.removeByG_N(
146                         context.getGroupId(), node.getName());
147                 }
148                 catch (NoSuchNodeException nsne) {
149                 }
150             }
151 
152             importedNode = WikiNodeLocalServiceUtil.addNode(
153                 userId, node.getName(), node.getDescription(), serviceContext);
154         }
155 
156         nodePKs.put(node.getNodeId(), importedNode.getNodeId());
157 
158         context.importPermissions(
159             WikiNode.class, node.getNodeId(), importedNode.getNodeId());
160     }
161 
162     public static void importPage(
163             PortletDataContext context, Map<Long, Long> nodePKs, Element pageEl,
164             WikiPage page)
165         throws Exception {
166 
167         long userId = context.getUserId(page.getUserUuid());
168         long nodeId = MapUtil.getLong(
169             nodePKs, page.getNodeId(), page.getNodeId());
170 
171         long[] assetCategoryIds = null;
172         String[] assetTagNames = null;
173 
174         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
175             assetCategoryIds = context.getAssetCategoryIds(
176                 WikiPage.class, page.getResourcePrimKey());
177         }
178 
179         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
180             assetTagNames = context.getAssetTagNames(
181                 WikiPage.class, page.getResourcePrimKey());
182         }
183 
184         ServiceContext serviceContext = new ServiceContext();
185 
186         serviceContext.setAddCommunityPermissions(true);
187         serviceContext.setAddGuestPermissions(true);
188         serviceContext.setAssetCategoryIds(assetCategoryIds);
189         serviceContext.setAssetTagNames(assetTagNames);
190         serviceContext.setCreateDate(page.getCreateDate());
191         serviceContext.setModifiedDate(page.getModifiedDate());
192 
193         WikiPage importedPage = null;
194 
195         try {
196             WikiNodeUtil.findByPrimaryKey(nodeId);
197 
198             if (context.getDataStrategy().equals(
199                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
200 
201                 WikiPage existingPage = WikiPageUtil.fetchByUUID_G(
202                     page.getUuid(), context.getGroupId());
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                     importedPage = WikiPageLocalServiceUtil.addPage(
215                         page.getUuid(), userId, nodeId, page.getTitle(),
216                         page.getVersion(), page.getContent(), page.getSummary(),
217                         true, page.getFormat(), page.getHead(),
218                         page.getParentTitle(), page.getRedirectTitle(),
219                         serviceContext);
220                 }
221                 else {
222                     importedPage = WikiPageLocalServiceUtil.updatePage(
223                         userId, nodeId, existingPage.getTitle(), 0,
224                         page.getContent(), page.getSummary(), true,
225                         page.getFormat(), page.getParentTitle(),
226                         page.getRedirectTitle(), serviceContext);
227                 }
228             }
229             else {
230                 importedPage = WikiPageLocalServiceUtil.addPage(
231                     null, userId, nodeId, page.getTitle(), page.getVersion(),
232                     page.getContent(), page.getSummary(), true,
233                     page.getFormat(), page.getHead(), page.getParentTitle(),
234                     page.getRedirectTitle(), serviceContext);
235             }
236 
237             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
238                 page.isHead()) {
239 
240                 List<Element> attachmentEls = pageEl.elements("attachment");
241 
242                 List<ObjectValuePair<String, byte[]>> files =
243                     new ArrayList<ObjectValuePair<String, byte[]>>();
244 
245                 for (Element attachmentEl : attachmentEls) {
246                     String name = attachmentEl.attributeValue("name");
247                     String binPath = attachmentEl.attributeValue("bin-path");
248 
249                     byte[] bytes = context.getZipEntryAsByteArray(binPath);
250 
251                     files.add(new ObjectValuePair<String, byte[]>(name, bytes));
252                 }
253 
254                 if (files.size() > 0) {
255                     WikiPageLocalServiceUtil.addPageAttachments(
256                         nodeId, page.getTitle(), files);
257                 }
258             }
259 
260             context.importPermissions(
261                 WikiPage.class, page.getResourcePrimKey(),
262                 importedPage.getResourcePrimKey());
263 
264             if (context.getBooleanParameter(_NAMESPACE, "comments") &&
265                 page.isHead()) {
266 
267                 context.importComments(
268                     WikiPage.class, page.getResourcePrimKey(),
269                     importedPage.getResourcePrimKey(), context.getGroupId());
270             }
271 
272             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
273                 context.importRatingsEntries(
274                     WikiPage.class, page.getResourcePrimKey(),
275                     importedPage.getResourcePrimKey());
276             }
277         }
278         catch (NoSuchNodeException nsne) {
279             _log.error("Could not find the node for page " + page.getPageId());
280         }
281     }
282 
283     public PortletPreferences deleteData(
284             PortletDataContext context, String portletId,
285             PortletPreferences preferences)
286         throws PortletDataException {
287 
288         try {
289             if (!context.addPrimaryKey(
290                     WikiPortletDataHandlerImpl.class, "deleteData")) {
291 
292                 WikiNodeLocalServiceUtil.deleteNodes(context.getGroupId());
293             }
294 
295             return null;
296         }
297         catch (Exception e) {
298             throw new PortletDataException(e);
299         }
300     }
301 
302     public String exportData(
303             PortletDataContext context, String portletId,
304             PortletPreferences preferences)
305         throws PortletDataException {
306 
307         try {
308             context.addPermissions(
309                 "com.liferay.portlet.wiki", context.getGroupId());
310 
311             Document doc = SAXReaderUtil.createDocument();
312 
313             Element root = doc.addElement("wiki-data");
314 
315             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
316 
317             Element nodesEl = root.addElement("nodes");
318             Element pagesEl = root.addElement("pages");
319 
320             List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
321                 context.getGroupId());
322 
323             for (WikiNode node : nodes) {
324                 exportNode(context, nodesEl, pagesEl, node);
325             }
326 
327             return doc.formattedString();
328         }
329         catch (Exception e) {
330             throw new PortletDataException(e);
331         }
332     }
333 
334     public PortletDataHandlerControl[] getExportControls() {
335         return new PortletDataHandlerControl[] {
336             _nodesAndPages, _attachments, _categories, _comments, _tags
337         };
338     }
339 
340     public PortletDataHandlerControl[] getImportControls() {
341         return new PortletDataHandlerControl[] {
342             _nodesAndPages, _attachments, _categories, _comments, _tags
343         };
344     }
345 
346     public PortletPreferences importData(
347             PortletDataContext context, String portletId,
348             PortletPreferences preferences, String data)
349         throws PortletDataException {
350 
351         try {
352             context.importPermissions(
353                 "com.liferay.portlet.wiki", context.getSourceGroupId(),
354                 context.getGroupId());
355 
356             Document doc = SAXReaderUtil.read(data);
357 
358             Element root = doc.getRootElement();
359 
360             List<Element> nodeEls = root.element("nodes").elements("node");
361 
362             Map<Long, Long> nodePKs =
363                 (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
364 
365             for (Element nodeEl : nodeEls) {
366                 String path = nodeEl.attributeValue("path");
367 
368                 if (!context.isPathNotProcessed(path)) {
369                     continue;
370                 }
371 
372                 WikiNode node = (WikiNode)context.getZipEntryAsObject(path);
373 
374                 importNode(context, nodePKs, node);
375             }
376 
377             List<Element> pageEls = root.element("pages").elements("page");
378 
379             for (Element pageEl : pageEls) {
380                 String path = pageEl.attributeValue("path");
381 
382                 if (!context.isPathNotProcessed(path)) {
383                     continue;
384                 }
385 
386                 WikiPage page = (WikiPage)context.getZipEntryAsObject(path);
387 
388                 importPage(context, nodePKs, pageEl, page);
389             }
390 
391             return null;
392         }
393         catch (Exception e) {
394             throw new PortletDataException(e);
395         }
396     }
397 
398     protected static void exportNode(
399             PortletDataContext context, Element nodesEl, long nodeId)
400         throws PortalException, SystemException {
401 
402         if (!context.hasDateRange()) {
403             return;
404         }
405 
406         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
407 
408         String path = getNodePath(context, node);
409 
410         if (!context.isPathNotProcessed(path)) {
411             return;
412         }
413 
414         Element nodeEl = nodesEl.addElement("node");
415 
416         nodeEl.addAttribute("path", path);
417 
418         node.setUserUuid(node.getUserUuid());
419 
420         context.addPermissions(WikiNode.class, node.getNodeId());
421 
422         context.addZipEntry(path, node);
423     }
424 
425     protected static void exportPage(
426             PortletDataContext context, Element nodesEl, Element pagesEl,
427             WikiPage page)
428         throws PortalException, SystemException {
429 
430         if (!context.isWithinDateRange(page.getModifiedDate())) {
431             return;
432         }
433 
434         String path = getPagePath(context, page);
435 
436         if (context.isPathNotProcessed(path)) {
437             Element pageEl = pagesEl.addElement("page");
438 
439             pageEl.addAttribute("path", path);
440 
441             page.setUserUuid(page.getUserUuid());
442 
443             context.addPermissions(WikiPage.class, page.getResourcePrimKey());
444 
445             if (context.getBooleanParameter(_NAMESPACE, "categories")) {
446                 context.addAssetCategories(
447                     WikiPage.class, page.getResourcePrimKey());
448             }
449 
450             if (context.getBooleanParameter(_NAMESPACE, "comments")) {
451                 context.addComments(WikiPage.class, page.getResourcePrimKey());
452             }
453 
454             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
455                 context.addAssetTags(WikiPage.class, page.getResourcePrimKey());
456             }
457 
458             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
459                 page.isHead()) {
460 
461                 for (String attachment : page.getAttachmentsFiles()) {
462                     int pos = attachment.lastIndexOf(StringPool.SLASH);
463 
464                     String name = attachment.substring(pos + 1);
465                     String binPath = getPageAttachementBinPath(
466                         context, page, name);
467 
468                     Element attachmentEl = pageEl.addElement("attachment");
469 
470                     attachmentEl.addAttribute("name", name);
471                     attachmentEl.addAttribute("bin-path", binPath);
472 
473                     byte[] bytes = DLServiceUtil.getFile(
474                         context.getCompanyId(), CompanyConstants.SYSTEM,
475                         attachment);
476 
477                     context.addZipEntry(binPath, bytes);
478                 }
479 
480                 page.setAttachmentsDir(page.getAttachmentsDir());
481             }
482 
483             context.addZipEntry(path, page);
484         }
485 
486         exportNode(context, nodesEl, page.getNodeId());
487     }
488 
489     protected static String getNodePath(
490         PortletDataContext context, WikiNode node) {
491 
492         StringBundler sb = new StringBundler(4);
493 
494         sb.append(context.getPortletPath(PortletKeys.WIKI));
495         sb.append("/nodes/");
496         sb.append(node.getNodeId());
497         sb.append(".xml");
498 
499         return sb.toString();
500     }
501 
502     protected static String getPageAttachementBinPath(
503         PortletDataContext context, WikiPage page, String attachment) {
504 
505         StringBundler sb = new StringBundler(5);
506 
507         sb.append(context.getPortletPath(PortletKeys.WIKI));
508         sb.append("/bin/");
509         sb.append(page.getPageId());
510         sb.append(StringPool.SLASH);
511         sb.append(attachment);
512 
513         return sb.toString();
514     }
515 
516     protected static String getPagePath(
517         PortletDataContext context, WikiPage page) {
518 
519         StringBundler sb = new StringBundler(4);
520 
521         sb.append(context.getPortletPath(PortletKeys.WIKI));
522         sb.append("/pages/");
523         sb.append(page.getPageId());
524         sb.append(".xml");
525 
526         return sb.toString();
527     }
528 
529     private static final String _NAMESPACE = "wiki";
530 
531     private static final PortletDataHandlerBoolean _nodesAndPages =
532         new PortletDataHandlerBoolean(
533             _NAMESPACE, "wikis-and-pages", true, true);
534 
535     private static final PortletDataHandlerBoolean _attachments =
536         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
537 
538     private static final PortletDataHandlerBoolean _categories =
539         new PortletDataHandlerBoolean(_NAMESPACE, "categories");
540 
541     private static final PortletDataHandlerBoolean _comments =
542         new PortletDataHandlerBoolean(_NAMESPACE, "comments");
543 
544     private static final PortletDataHandlerBoolean _tags =
545         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
546 
547     private static Log _log = LogFactoryUtil.getLog(
548         WikiPortletDataHandlerImpl.class);
549 
550 }