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