1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
13   */
14  
15  package com.liferay.portlet.wiki.lar;
16  
17  import com.liferay.documentlibrary.service.DLServiceUtil;
18  import com.liferay.portal.PortalException;
19  import com.liferay.portal.SystemException;
20  import com.liferay.portal.kernel.dao.orm.QueryUtil;
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 existingNode = null;
111 
112         if (context.getDataStrategy().equals(
113                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
114 
115             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                 existingNode = WikiNodeLocalServiceUtil.addNode(
131                     node.getUuid(), userId, node.getName(),
132                     node.getDescription(), serviceContext);
133             }
134             else {
135                 existingNode = 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             existingNode = WikiNodeLocalServiceUtil.addNode(
153                 userId, node.getName(), node.getDescription(), serviceContext);
154         }
155 
156         nodePKs.put(node.getNodeId(), existingNode.getNodeId());
157 
158         context.importPermissions(
159             WikiNode.class, node.getNodeId(), existingNode.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         String[] tagsCategories = null;
172         String[] tagsEntries = null;
173 
174         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
175             tagsCategories = context.getTagsCategories(
176                 WikiPage.class, page.getResourcePrimKey());
177         }
178 
179         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
180             tagsEntries = context.getTagsEntries(
181                 WikiPage.class, page.getResourcePrimKey());
182         }
183 
184         ServiceContext serviceContext = new ServiceContext();
185 
186         serviceContext.setAddCommunityPermissions(true);
187         serviceContext.setAddGuestPermissions(true);
188         serviceContext.setTagsCategories(tagsCategories);
189         serviceContext.setTagsEntries(tagsEntries);
190         serviceContext.setCreateDate(page.getCreateDate());
191         serviceContext.setModifiedDate(page.getModifiedDate());
192 
193         WikiPage existingPage = null;
194 
195         try {
196             WikiNodeUtil.findByPrimaryKey(nodeId);
197 
198             if (context.getDataStrategy().equals(
199                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
200 
201                 try {
202                     existingPage = WikiPageUtil.findByUUID_G(
203                         page.getUuid(), context.getGroupId());
204                 }
205                 catch (NoSuchPageException nspe) {
206                 }
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                     existingPage = WikiPageLocalServiceUtil.updatePage(
219                         userId, nodeId, existingPage.getTitle(), 0,
220                         page.getContent(), page.getSummary(), true,
221                         page.getFormat(), page.getParentTitle(),
222                         page.getRedirectTitle(), serviceContext);
223                 }
224                 else {
225                     existingPage = WikiPageLocalServiceUtil.addPage(
226                         page.getUuid(), userId, nodeId, page.getTitle(),
227                         page.getVersion(), page.getContent(), page.getSummary(),
228                         true, page.getFormat(), page.getHead(),
229                         page.getParentTitle(), page.getRedirectTitle(),
230                         serviceContext);
231                 }
232             }
233             else {
234                 existingPage = WikiPageLocalServiceUtil.addPage(
235                     null, userId, nodeId, page.getTitle(), page.getVersion(),
236                     page.getContent(), page.getSummary(), true,
237                     page.getFormat(), page.getHead(), page.getParentTitle(),
238                     page.getRedirectTitle(), serviceContext);
239             }
240 
241             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
242                 page.isHead()) {
243 
244                 List<Element> attachmentEls = pageEl.elements("attachment");
245 
246                 List<ObjectValuePair<String, byte[]>> files =
247                     new ArrayList<ObjectValuePair<String, byte[]>>();
248 
249                 for (Element attachmentEl : attachmentEls) {
250                     String name = attachmentEl.attributeValue("name");
251                     String binPath = attachmentEl.attributeValue("bin-path");
252 
253                     byte[] bytes = context.getZipEntryAsByteArray(binPath);
254 
255                     files.add(new ObjectValuePair<String, byte[]>(name, bytes));
256                 }
257 
258                 if (files.size() > 0) {
259                     WikiPageLocalServiceUtil.addPageAttachments(
260                         nodeId, page.getTitle(), files);
261                 }
262             }
263 
264             context.importPermissions(
265                 WikiPage.class, page.getResourcePrimKey(),
266                 existingPage.getResourcePrimKey());
267 
268             if (context.getBooleanParameter(_NAMESPACE, "comments") &&
269                 page.isHead()) {
270 
271                 context.importComments(
272                     WikiPage.class, page.getResourcePrimKey(),
273                     existingPage.getResourcePrimKey(), context.getGroupId());
274             }
275 
276             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
277                 context.importRatingsEntries(
278                     WikiPage.class, page.getResourcePrimKey(),
279                     existingPage.getResourcePrimKey());
280             }
281         }
282         catch (NoSuchNodeException nsne) {
283             _log.error("Could not find the node for page " + page.getPageId());
284         }
285     }
286 
287     public PortletPreferences deleteData(
288             PortletDataContext context, String portletId,
289             PortletPreferences preferences)
290         throws PortletDataException {
291 
292         try {
293             if (!context.addPrimaryKey(
294                     WikiPortletDataHandlerImpl.class, "deleteData")) {
295 
296                 WikiNodeLocalServiceUtil.deleteNodes(context.getGroupId());
297             }
298 
299             return null;
300         }
301         catch (Exception e) {
302             throw new PortletDataException(e);
303         }
304     }
305 
306     public String exportData(
307             PortletDataContext context, String portletId,
308             PortletPreferences preferences)
309         throws PortletDataException {
310 
311         try {
312             context.addPermissions(
313                 "com.liferay.portlet.wiki", context.getGroupId());
314 
315             Document doc = SAXReaderUtil.createDocument();
316 
317             Element root = doc.addElement("wiki-data");
318 
319             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
320 
321             Element nodesEl = root.addElement("nodes");
322             Element pagesEl = root.addElement("pages");
323 
324             List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
325                 context.getGroupId());
326 
327             for (WikiNode node : nodes) {
328                 exportNode(context, nodesEl, pagesEl, node);
329             }
330 
331             return doc.formattedString();
332         }
333         catch (Exception e) {
334             throw new PortletDataException(e);
335         }
336     }
337 
338     public PortletDataHandlerControl[] getExportControls() {
339         return new PortletDataHandlerControl[] {
340             _nodesAndPages, _attachments, _categories, _comments, _tags
341         };
342     }
343 
344     public PortletDataHandlerControl[] getImportControls() {
345         return new PortletDataHandlerControl[] {
346             _nodesAndPages, _attachments, _categories, _comments, _tags
347         };
348     }
349 
350     public PortletPreferences importData(
351             PortletDataContext context, String portletId,
352             PortletPreferences preferences, String data)
353         throws PortletDataException {
354 
355         try {
356             context.importPermissions(
357                 "com.liferay.portlet.wiki", context.getSourceGroupId(),
358                 context.getGroupId());
359 
360             Document doc = SAXReaderUtil.read(data);
361 
362             Element root = doc.getRootElement();
363 
364             List<Element> nodeEls = root.element("nodes").elements("node");
365 
366             Map<Long, Long> nodePKs =
367                 (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
368 
369             for (Element nodeEl : nodeEls) {
370                 String path = nodeEl.attributeValue("path");
371 
372                 if (!context.isPathNotProcessed(path)) {
373                     continue;
374                 }
375 
376                 WikiNode node = (WikiNode)context.getZipEntryAsObject(path);
377 
378                 importNode(context, nodePKs, node);
379             }
380 
381             List<Element> pageEls = root.element("pages").elements("page");
382 
383             for (Element pageEl : pageEls) {
384                 String path = pageEl.attributeValue("path");
385 
386                 if (!context.isPathNotProcessed(path)) {
387                     continue;
388                 }
389 
390                 WikiPage page = (WikiPage)context.getZipEntryAsObject(path);
391 
392                 importPage(context, nodePKs, pageEl, page);
393             }
394 
395             return null;
396         }
397         catch (Exception e) {
398             throw new PortletDataException(e);
399         }
400     }
401 
402     protected static void exportNode(
403             PortletDataContext context, Element nodesEl, long nodeId)
404         throws PortalException, SystemException {
405 
406         if (!context.hasDateRange()) {
407             return;
408         }
409 
410         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
411 
412         String path = getNodePath(context, node);
413 
414         if (!context.isPathNotProcessed(path)) {
415             return;
416         }
417 
418         Element nodeEl = nodesEl.addElement("node");
419 
420         nodeEl.addAttribute("path", path);
421 
422         node.setUserUuid(node.getUserUuid());
423 
424         context.addPermissions(WikiNode.class, node.getNodeId());
425 
426         context.addZipEntry(path, node);
427     }
428 
429     protected static void exportPage(
430             PortletDataContext context, Element nodesEl, Element pagesEl,
431             WikiPage page)
432         throws PortalException, SystemException {
433 
434         if (!context.isWithinDateRange(page.getModifiedDate())) {
435             return;
436         }
437 
438         String path = getPagePath(context, page);
439 
440         if (context.isPathNotProcessed(path)) {
441             Element pageEl = pagesEl.addElement("page");
442 
443             pageEl.addAttribute("path", path);
444 
445             page.setUserUuid(page.getUserUuid());
446 
447             context.addPermissions(WikiPage.class, page.getResourcePrimKey());
448 
449             if (context.getBooleanParameter(_NAMESPACE, "categories")) {
450                 context.addTagsCategories(
451                     WikiPage.class, page.getResourcePrimKey());
452             }
453 
454             if (context.getBooleanParameter(_NAMESPACE, "comments")) {
455                 context.addComments(WikiPage.class, page.getResourcePrimKey());
456             }
457 
458             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
459                 context.addTagsEntries(
460                     WikiPage.class, page.getResourcePrimKey());
461             }
462 
463             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
464                 page.isHead()) {
465 
466                 for (String attachment : page.getAttachmentsFiles()) {
467                     int pos = attachment.lastIndexOf(StringPool.SLASH);
468 
469                     String name = attachment.substring(pos + 1);
470                     String binPath = getPageAttachementBinPath(
471                         context, page, name);
472 
473                     Element attachmentEl = pageEl.addElement("attachment");
474 
475                     attachmentEl.addAttribute("name", name);
476                     attachmentEl.addAttribute("bin-path", binPath);
477 
478                     byte[] bytes = DLServiceUtil.getFile(
479                         context.getCompanyId(), CompanyConstants.SYSTEM,
480                         attachment);
481 
482                     context.addZipEntry(binPath, bytes);
483                 }
484 
485                 page.setAttachmentsDir(page.getAttachmentsDir());
486             }
487 
488             context.addZipEntry(path, page);
489         }
490 
491         exportNode(context, nodesEl, page.getNodeId());
492     }
493 
494     protected static String getNodePath(
495         PortletDataContext context, WikiNode node) {
496 
497         StringBundler sb = new StringBundler(4);
498 
499         sb.append(context.getPortletPath(PortletKeys.WIKI));
500         sb.append("/nodes/");
501         sb.append(node.getNodeId());
502         sb.append(".xml");
503 
504         return sb.toString();
505     }
506 
507     protected static String getPageAttachementBinPath(
508         PortletDataContext context, WikiPage page, String attachment) {
509 
510         StringBundler sb = new StringBundler(5);
511 
512         sb.append(context.getPortletPath(PortletKeys.WIKI));
513         sb.append("/bin/");
514         sb.append(page.getPageId());
515         sb.append(StringPool.SLASH);
516         sb.append(attachment);
517 
518         return sb.toString();
519     }
520 
521     protected static String getPagePath(
522         PortletDataContext context, WikiPage page) {
523 
524         StringBundler sb = new StringBundler(4);
525 
526         sb.append(context.getPortletPath(PortletKeys.WIKI));
527         sb.append("/pages/");
528         sb.append(page.getPageId());
529         sb.append(".xml");
530 
531         return sb.toString();
532     }
533 
534     private static final String _NAMESPACE = "wiki";
535 
536     private static final PortletDataHandlerBoolean _nodesAndPages =
537         new PortletDataHandlerBoolean(
538             _NAMESPACE, "wikis-and-pages", true, true);
539 
540     private static final PortletDataHandlerBoolean _attachments =
541         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
542 
543     private static final PortletDataHandlerBoolean _categories =
544         new PortletDataHandlerBoolean(_NAMESPACE, "categories");
545 
546     private static final PortletDataHandlerBoolean _comments =
547         new PortletDataHandlerBoolean(_NAMESPACE, "comments");
548 
549     private static final PortletDataHandlerBoolean _tags =
550         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
551 
552     private static Log _log = LogFactoryUtil.getLog(
553         WikiPortletDataHandlerImpl.class);
554 
555 }