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